From a47b2ddd0ab6600b53f30b0eaeb67a0d8b3e8668 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 19 Jan 2010 13:45:51 +0100 Subject: [PATCH] libblkid: don't call read() per FAT dir-entry on large disks Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/vfat.c | 45 +++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 1662f131..29066c34 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -111,32 +111,59 @@ struct fat32_fsinfo { static const char *no_name = "NO NAME "; +/* + * Look for LABEL (name) in the FAT root directory. + */ static unsigned char *search_fat_label(blkid_probe pr, uint32_t offset, uint32_t entries) { - struct vfat_dir_entry *dir; + struct vfat_dir_entry *ent, *dir = NULL; int i; - for (i = 0; i < entries; i++) { + DBG(DEBUG_LOWPROBE, + printf("\tlook for label in root-dir " + "(entries: %d, offset: %d)\n", entries, offset)); + if (!blkid_probe_is_tiny(pr)) { + /* large disk, read whole root directory */ dir = (struct vfat_dir_entry *) + blkid_probe_get_buffer(pr, + offset, + entries * sizeof(struct vfat_dir_entry)); + if (!dir) + return NULL; + } + + for (i = 0; i < entries; i++) { + /* + * The root directory could be relatively large (4-16kB). + * Fortunately, the LABEL is usually the first entry in the + * directory. On tiny disks we call read() per entry. + */ + if (!dir) + ent = (struct vfat_dir_entry *) blkid_probe_get_extra_buffer(pr, offset + (i * sizeof(struct vfat_dir_entry)), sizeof(struct vfat_dir_entry)); - if (dir->name[0] == 0x00) + else + ent = &dir[i]; + + if (!ent || ent->name[0] == 0x00) break; - if ((dir->name[0] == FAT_ENTRY_FREE) || - (dir->cluster_high != 0 || dir->cluster_low != 0) || - ((dir->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) + if ((ent->name[0] == FAT_ENTRY_FREE) || + (ent->cluster_high != 0 || ent->cluster_low != 0) || + ((ent->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) continue; - if ((dir->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == + if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { - return dir->name; + DBG(DEBUG_LOWPROBE, + printf("\tfound fs LABEL at entry %d\n", i)); + return ent->name; } } - return 0; + return NULL; } /* -- 2.39.5