hal/hald/linux/volume_id volume_id.c,1.34,1.35
Kay Sievers
kay at freedesktop.org
Thu Sep 16 16:18:09 PDT 2004
Update of /cvs/hal/hal/hald/linux/volume_id
In directory gabe:/tmp/cvs-serv27372/hald/linux/volume_id
Modified Files:
volume_id.c
Log Message:
2004-09-17 Kay Sievers <kay.sievers at vrfy.org>
* hald/linux/volume_id/volume_id.c: (probe_vfat):
Fix endless loop for FAT32 volumes where the root directory
cluster chain is not terminated. Follow a maximum of 100 clusters
now and stop searching if we find a directory-end entry.
Index: volume_id.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/volume_id/volume_id.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- volume_id.c 15 Sep 2004 20:57:19 -0000 1.34
+++ volume_id.c 16 Sep 2004 23:18:06 -0000 1.35
@@ -735,52 +735,6 @@
#define FAT12_MAX 0xff5
#define FAT16_MAX 0xfff5
#define FAT_ATTR_VOLUME 0x08
-struct vfat_dir_entry {
- __u8 name[11];
- __u8 attr;
- __u16 time_creat;
- __u16 date_creat;
- __u16 time_acc;
- __u16 date_acc;
- __u16 cluster_high;
- __u16 time_write;
- __u16 date_write;
- __u16 cluster_low;
- __u32 size;
-} __attribute__((__packed__));
-
-static char *vfat_search_label_in_dir(const __u8 *buf, __u16 size)
-{
- struct vfat_dir_entry *dir;
- int i;
- __u16 count;
-
- dir = (struct vfat_dir_entry*) buf;
- count = size / sizeof(struct vfat_dir_entry);
- dbg("expected entries 0x%x", count);
-
- for (i = 0; i <= count; i++) {
- /* end marker */
- if (dir[i].attr == 0x00) {
- dbg("end of dir");
- return NULL;
- }
-
- /* empty entry */
- if (dir[i].attr == 0xe5)
- continue;
-
- if (dir[i].attr == FAT_ATTR_VOLUME) {
- dbg("found ATTR_VOLUME id in root dir");
- return dir[i].name;
- }
-
- dbg("skip dir entry");
- }
-
- return NULL;
-}
-
static int probe_vfat(struct volume_id *id, __u64 off)
{
struct vfat_super_block {
@@ -825,6 +779,20 @@
} __attribute__((__packed__)) type;
} __attribute__((__packed__)) *vs;
+ struct vfat_dir_entry {
+ __u8 name[11];
+ __u8 attr;
+ __u16 time_creat;
+ __u16 date_creat;
+ __u16 time_acc;
+ __u16 date_acc;
+ __u16 cluster_high;
+ __u16 time_write;
+ __u16 date_write;
+ __u16 cluster_low;
+ __u32 size;
+ } __attribute__((__packed__)) *dir;
+
__u16 sector_size;
__u16 dir_entries;
__u32 sect_count;
@@ -841,6 +809,8 @@
__u32 buf_size;
__u8 *label = NULL;
__u32 next;
+ int maxloop;
+ int i;
vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
if (vs == NULL)
@@ -935,15 +905,35 @@
/* the label may be an attribute in the root directory */
root_start = (reserved + fat_size) * sector_size;
- root_dir_entries = le16_to_cpu(vs->dir_entries);
dbg("root dir start 0x%x", root_start);
+ root_dir_entries = le16_to_cpu(vs->dir_entries);
+ dbg("expected entries 0x%x", root_dir_entries);
buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
buf = get_buffer(id, off + root_start, buf_size);
if (buf == NULL)
goto found;
- label = vfat_search_label_in_dir(buf, buf_size);
+ dir = (struct vfat_dir_entry*) buf;
+
+ for (i = 0; i <= root_dir_entries; i++) {
+ /* end marker */
+ if (dir[i].attr == 0x00) {
+ dbg("end of dir");
+ break;
+ }
+
+ /* empty entry */
+ if (dir[i].attr == 0xe5)
+ continue;
+
+ if (dir[i].attr == FAT_ATTR_VOLUME) {
+ dbg("found ATTR_VOLUME id in root dir");
+ label = dir[i].name;
+ }
+
+ dbg("skip dir entry");
+ }
if (label != NULL && strncmp(label, "NO NAME ", 11) != 0) {
set_label_raw(id, label, 11);
@@ -963,10 +953,12 @@
start_data_sect = reserved + fat_size;
next = root_cluster;
- while (1) {
+ maxloop = 100;
+ while (maxloop--) {
__u32 next_sect_off;
__u64 next_off;
__u64 fat_entry_off;
+ int count;
dbg("next cluster %u", next);
next_sect_off = (next - 2) * vs->sectors_per_cluster;
@@ -978,9 +970,29 @@
if (buf == NULL)
goto found;
- label = vfat_search_label_in_dir(buf, buf_size);
- if (label != NULL)
- break;
+ dir = (struct vfat_dir_entry*) buf;
+ count = buf_size / sizeof(struct vfat_dir_entry);
+ dbg("expected entries 0x%x", count);
+
+ for (i = 0; i <= count; i++) {
+ /* end marker */
+ if (dir[i].attr == 0x00) {
+ dbg("end of dir");
+ goto fat32_label;
+ }
+
+ /* empty entry */
+ if (dir[i].attr == 0xe5)
+ continue;
+
+ if (dir[i].attr == FAT_ATTR_VOLUME) {
+ dbg("found ATTR_VOLUME id in root dir");
+ label = dir[i].name;
+ goto fat32_label;
+ }
+
+ dbg("skip dir entry");
+ }
/* get FAT entry */
fat_entry_off = (reserved * sector_size) + (next * sizeof(__u32));
@@ -993,7 +1005,10 @@
if (next == 0)
break;
}
+ if (maxloop == 0)
+ dbg("reached maximum follow count of root cluster chain, give up");
+fat32_label:
if (label != NULL && strncmp(label, "NO NAME ", 11) != 0) {
set_label_raw(id, label, 11);
set_label_string(id, label, 11);
More information about the hal-commit
mailing list