From: Karel Zak Date: Thu, 20 Nov 2008 14:04:48 +0000 (+0100) Subject: blkid: add version and probe FSInfo X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de8e25fa00a80eca685d0c495a2b62e60c029bee;p=util-linux blkid: add version and probe FSInfo Signed-off-by: Karel Zak --- diff --git a/libs/blkid/src/probers/vfat.c b/libs/blkid/src/probers/vfat.c index c277afe8..e3b9bb30 100644 --- a/libs/blkid/src/probers/vfat.c +++ b/libs/blkid/src/probers/vfat.c @@ -45,7 +45,7 @@ struct vfat_super_block { /* 28*/ uint16_t vs_flags; /* 2a*/ uint8_t vs_version[2]; /* 2c*/ uint32_t vs_root_cluster; -/* 30*/ uint16_t vs_insfo_sector; +/* 30*/ uint16_t vs_fsinfo_sector; /* 32*/ uint16_t vs_backup_boot; /* 34*/ uint16_t vs_reserved2[6]; /* 40*/ unsigned char vs_unknown[3]; @@ -94,6 +94,15 @@ struct vfat_dir_entry { uint32_t size; }; +struct fat32_fsinfo { + uint8_t signature1[4]; + uint32_t reserved1[120]; + uint8_t signature2[4]; + uint32_t free_clusters; + uint32_t next_cluster; + uint32_t reserved2[4]; +}; + /* maximum number of clusters */ #define FAT12_MAX 0xFF4 #define FAT16_MAX 0xFFF4 @@ -188,6 +197,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) uint16_t sector_size, dir_entries, reserved; uint32_t sect_count, fat_size, dir_size, cluster_count, fat_length; uint32_t buf_size, start_data_sect, next, root_start, root_dir_entries; + const char *version = NULL; /* non-standard magic strings */ @@ -251,12 +261,21 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "msdos", sizeof("msdos")); + + if (cluster_count < FAT12_MAX) + version = "FAT12"; + else if (cluster_count < FAT16_MAX) + version = "FAT16"; } else { unsigned char *buf; + uint16_t fsinfo_sect; + /* Search the FAT32 root dir for the label attribute */ buf_size = vs->vs_cluster_size * sector_size; start_data_sect = reserved + fat_size; + version = "FAT32"; + next = le32_to_cpu(vs->vs_root_cluster); while (next && --maxloop) { uint32_t next_sect_off; @@ -292,6 +311,30 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) if (!vol_label || !memcmp(vol_label, no_name, 11)) vol_label = vs->vs_label; vol_serno = vs->vs_serno; + + /* + * FAT32 should have a valid signature in the fsinfo block, + * but also allow all bytes set to '\0', because some volumes + * do not set the signature at all. + */ + fsinfo_sect = le16_to_cpu(vs->vs_fsinfo_sector); + if (fsinfo_sect) { + struct fat32_fsinfo *fsinfo; + + buf = blkid_probe_get_buffer(pr, + fsinfo_sect * sector_size, + sizeof(struct fat32_fsinfo)); + if (buf == NULL) + return -1; + + fsinfo = (struct fat32_fsinfo *) buf; + if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 && + memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0) + return -1; + if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 && + memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0) + return -1; + } } if (vol_label && memcmp(vol_label, no_name, 11)) @@ -301,6 +344,9 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) blkid_probe_sprintf_uuid(pr, vol_serno, 4, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2], vol_serno[1], vol_serno[0]); + if (version) + blkid_probe_set_version(pr, version); + return 0; }