vfat.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Copyright (C) 1999 by Andries Brouwer
  3. * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
  4. * Copyright (C) 2001 by Andreas Dilger
  5. * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
  6. * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
  7. *
  8. * This file may be redistributed under the terms of the
  9. * GNU Lesser General Public License.
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <string.h>
  15. #include <errno.h>
  16. #include <ctype.h>
  17. #include <stdint.h>
  18. #if 0
  19. #include "pt-mbr.h"
  20. #endif
  21. #include "superblocks.h"
  22. /* Yucky misaligned values */
  23. struct vfat_super_block {
  24. /* 00*/ unsigned char vs_ignored[3];
  25. /* 03*/ unsigned char vs_sysid[8];
  26. /* 0b*/ unsigned char vs_sector_size[2];
  27. /* 0d*/ uint8_t vs_cluster_size;
  28. /* 0e*/ uint16_t vs_reserved;
  29. /* 10*/ uint8_t vs_fats;
  30. /* 11*/ unsigned char vs_dir_entries[2];
  31. /* 13*/ unsigned char vs_sectors[2];
  32. /* 15*/ unsigned char vs_media;
  33. /* 16*/ uint16_t vs_fat_length;
  34. /* 18*/ uint16_t vs_secs_track;
  35. /* 1a*/ uint16_t vs_heads;
  36. /* 1c*/ uint32_t vs_hidden;
  37. /* 20*/ uint32_t vs_total_sect;
  38. /* 24*/ uint32_t vs_fat32_length;
  39. /* 28*/ uint16_t vs_flags;
  40. /* 2a*/ uint8_t vs_version[2];
  41. /* 2c*/ uint32_t vs_root_cluster;
  42. /* 30*/ uint16_t vs_fsinfo_sector;
  43. /* 32*/ uint16_t vs_backup_boot;
  44. /* 34*/ uint16_t vs_reserved2[6];
  45. /* 40*/ unsigned char vs_unknown[3];
  46. /* 43*/ unsigned char vs_serno[4];
  47. /* 47*/ unsigned char vs_label[11];
  48. /* 52*/ unsigned char vs_magic[8];
  49. /* 5a*/ unsigned char vs_dummy2[0x1fe - 0x5a];
  50. /*1fe*/ unsigned char vs_pmagic[2];
  51. } __attribute__((packed));
  52. /* Yucky misaligned values */
  53. struct msdos_super_block {
  54. /* 00*/ unsigned char ms_ignored[3];
  55. /* 03*/ unsigned char ms_sysid[8];
  56. /* 0b*/ unsigned char ms_sector_size[2];
  57. /* 0d*/ uint8_t ms_cluster_size;
  58. /* 0e*/ uint16_t ms_reserved;
  59. /* 10*/ uint8_t ms_fats;
  60. /* 11*/ unsigned char ms_dir_entries[2];
  61. /* 13*/ unsigned char ms_sectors[2]; /* =0 iff V3 or later */
  62. /* 15*/ unsigned char ms_media;
  63. /* 16*/ uint16_t ms_fat_length; /* Sectors per FAT */
  64. /* 18*/ uint16_t ms_secs_track;
  65. /* 1a*/ uint16_t ms_heads;
  66. /* 1c*/ uint32_t ms_hidden;
  67. /* V3 BPB */
  68. /* 20*/ uint32_t ms_total_sect; /* iff ms_sectors == 0 */
  69. /* V4 BPB */
  70. /* 24*/ unsigned char ms_unknown[3]; /* Phys drive no., resvd, V4 sig (0x29) */
  71. /* 27*/ unsigned char ms_serno[4];
  72. /* 2b*/ unsigned char ms_label[11];
  73. /* 36*/ unsigned char ms_magic[8];
  74. /* 3e*/ unsigned char ms_dummy2[0x1fe - 0x3e];
  75. /*1fe*/ unsigned char ms_pmagic[2];
  76. } __attribute__((packed));
  77. struct vfat_dir_entry {
  78. uint8_t name[11];
  79. uint8_t attr;
  80. uint16_t time_creat;
  81. uint16_t date_creat;
  82. uint16_t time_acc;
  83. uint16_t date_acc;
  84. uint16_t cluster_high;
  85. uint16_t time_write;
  86. uint16_t date_write;
  87. uint16_t cluster_low;
  88. uint32_t size;
  89. } __attribute__((packed));
  90. struct fat32_fsinfo {
  91. uint8_t signature1[4];
  92. uint32_t reserved1[120];
  93. uint8_t signature2[4];
  94. uint32_t free_clusters;
  95. uint32_t next_cluster;
  96. uint32_t reserved2[4];
  97. } __attribute__((packed));
  98. /* maximum number of clusters */
  99. #define FAT12_MAX 0xFF4
  100. #define FAT16_MAX 0xFFF4
  101. #define FAT32_MAX 0x0FFFFFF6
  102. #define FAT_ATTR_VOLUME_ID 0x08
  103. #define FAT_ATTR_DIR 0x10
  104. #define FAT_ATTR_LONG_NAME 0x0f
  105. #define FAT_ATTR_MASK 0x3f
  106. #define FAT_ENTRY_FREE 0xe5
  107. static const char *no_name = "NO NAME ";
  108. #define unaligned_le16(x) \
  109. (((unsigned char *) x)[0] + (((unsigned char *) x)[1] << 8))
  110. /*
  111. * Look for LABEL (name) in the FAT root directory.
  112. */
  113. static unsigned char *search_fat_label(blkid_probe pr,
  114. uint64_t offset, uint32_t entries)
  115. {
  116. struct vfat_dir_entry *ent, *dir = NULL;
  117. uint32_t i;
  118. DBG(LOWPROBE, ul_debug("\tlook for label in root-dir "
  119. "(entries: %d, offset: %jd)", entries, offset));
  120. if (!blkid_probe_is_tiny(pr)) {
  121. /* large disk, read whole root directory */
  122. dir = (struct vfat_dir_entry *)
  123. blkid_probe_get_buffer(pr,
  124. offset,
  125. (blkid_loff_t) entries *
  126. sizeof(struct vfat_dir_entry));
  127. if (!dir)
  128. return NULL;
  129. }
  130. for (i = 0; i < entries; i++) {
  131. /*
  132. * The root directory could be relatively large (4-16kB).
  133. * Fortunately, the LABEL is usually the first entry in the
  134. * directory. On tiny disks we call read() per entry.
  135. */
  136. if (!dir)
  137. ent = (struct vfat_dir_entry *)
  138. blkid_probe_get_buffer(pr,
  139. (blkid_loff_t) offset + (i *
  140. sizeof(struct vfat_dir_entry)),
  141. sizeof(struct vfat_dir_entry));
  142. else
  143. ent = &dir[i];
  144. if (!ent || ent->name[0] == 0x00)
  145. break;
  146. if ((ent->name[0] == FAT_ENTRY_FREE) ||
  147. (ent->cluster_high != 0 || ent->cluster_low != 0) ||
  148. ((ent->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
  149. continue;
  150. if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
  151. FAT_ATTR_VOLUME_ID) {
  152. DBG(LOWPROBE, ul_debug("\tfound fs LABEL at entry %d", i));
  153. if (ent->name[0] == 0x05)
  154. ent->name[0] = 0xE5;
  155. return ent->name;
  156. }
  157. }
  158. return NULL;
  159. }
  160. static int fat_valid_superblock(blkid_probe pr,
  161. const struct blkid_idmag *mag,
  162. struct msdos_super_block *ms,
  163. struct vfat_super_block *vs,
  164. uint32_t *cluster_count, uint32_t *fat_size)
  165. {
  166. uint16_t sector_size, dir_entries, reserved;
  167. uint32_t sect_count, __fat_size, dir_size, __cluster_count, fat_length;
  168. uint32_t max_count;
  169. /* extra check for FATs without magic strings */
  170. if (mag->len <= 2) {
  171. /* Old floppies have a valid MBR signature */
  172. if (ms->ms_pmagic[0] != 0x55 || ms->ms_pmagic[1] != 0xAA)
  173. return 0;
  174. /*
  175. * OS/2 and apparently DFSee will place a FAT12/16-like
  176. * pseudo-superblock in the first 512 bytes of non-FAT
  177. * filesystems --- at least JFS and HPFS, and possibly others.
  178. * So we explicitly check for those filesystems at the
  179. * FAT12/16 filesystem magic field identifier, and if they are
  180. * present, we rule this out as a FAT filesystem, despite the
  181. * FAT-like pseudo-header.
  182. */
  183. if ((memcmp(ms->ms_magic, "JFS ", 8) == 0) ||
  184. (memcmp(ms->ms_magic, "HPFS ", 8) == 0))
  185. return 0;
  186. }
  187. /* fat counts(Linux kernel expects at least 1 FAT table) */
  188. if (!ms->ms_fats)
  189. return 0;
  190. if (!ms->ms_reserved)
  191. return 0;
  192. if (!(0xf8 <= ms->ms_media || ms->ms_media == 0xf0))
  193. return 0;
  194. if (!is_power_of_2(ms->ms_cluster_size))
  195. return 0;
  196. sector_size = unaligned_le16(&ms->ms_sector_size);
  197. if (!is_power_of_2(sector_size) ||
  198. sector_size < 512 || sector_size > 4096)
  199. return 0;
  200. dir_entries = unaligned_le16(&ms->ms_dir_entries);
  201. reserved = le16_to_cpu(ms->ms_reserved);
  202. sect_count = unaligned_le16(&ms->ms_sectors);
  203. if (sect_count == 0)
  204. sect_count = le32_to_cpu(ms->ms_total_sect);
  205. fat_length = le16_to_cpu(ms->ms_fat_length);
  206. if (fat_length == 0)
  207. fat_length = le32_to_cpu(vs->vs_fat32_length);
  208. __fat_size = fat_length * ms->ms_fats;
  209. dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
  210. (sector_size-1)) / sector_size;
  211. __cluster_count = (sect_count - (reserved + __fat_size + dir_size)) /
  212. ms->ms_cluster_size;
  213. if (!ms->ms_fat_length && vs->vs_fat32_length)
  214. max_count = FAT32_MAX;
  215. else
  216. max_count = __cluster_count > FAT12_MAX ? FAT16_MAX : FAT12_MAX;
  217. if (__cluster_count > max_count)
  218. return 0;
  219. if (fat_size)
  220. *fat_size = __fat_size;
  221. if (cluster_count)
  222. *cluster_count = __cluster_count;
  223. #if 0
  224. if (blkid_probe_is_wholedisk(pr)) {
  225. /* OK, seems like FAT, but it's possible that we found boot
  226. * sector with crazy FAT-like stuff (magic strings, media,
  227. * etc..) before MBR. Let's make sure that there is no MBR with
  228. * usable partition. */
  229. unsigned char *buf = (unsigned char *) ms;
  230. if (mbr_is_valid_magic(buf)) {
  231. struct dos_partition *p0 = mbr_get_partition(buf, 0);
  232. if (dos_partition_get_size(p0) != 0 &&
  233. (p0->boot_ind == 0 || p0->boot_ind == 0x80))
  234. return 0;
  235. }
  236. }
  237. #endif
  238. return 1; /* valid */
  239. }
  240. #if 0
  241. /*
  242. * This function is used by MBR partition table parser to avoid
  243. * misinterpretation of FAT filesystem.
  244. */
  245. int blkid_probe_is_vfat(blkid_probe pr)
  246. {
  247. struct vfat_super_block *vs;
  248. struct msdos_super_block *ms;
  249. const struct blkid_idmag *mag = NULL;
  250. int rc;
  251. rc = blkid_probe_get_idmag(pr, &vfat_idinfo, NULL, &mag);
  252. if (rc < 0)
  253. return rc; /* error */
  254. if (rc != BLKID_PROBE_OK || !mag)
  255. return 0;
  256. ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
  257. if (!ms)
  258. return errno ? -errno : 0;
  259. vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block);
  260. if (!vs)
  261. return errno ? -errno : 0;
  262. return fat_valid_superblock(pr, mag, ms, vs, NULL, NULL);
  263. }
  264. #endif
  265. /* FAT label extraction from the root directory taken from Kay
  266. * Sievers's volume_id library */
  267. static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
  268. {
  269. struct vfat_super_block *vs;
  270. struct msdos_super_block *ms;
  271. unsigned char *vol_label = 0;
  272. const unsigned char *boot_label = NULL;
  273. unsigned char *vol_serno = NULL, vol_label_buf[12] = { 0 };
  274. uint16_t sector_size = 0, reserved;
  275. uint32_t cluster_count, fat_size;
  276. const char *version = NULL;
  277. ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
  278. if (!ms)
  279. return errno ? -errno : 1;
  280. vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block);
  281. if (!vs)
  282. return errno ? -errno : 1;
  283. if (!fat_valid_superblock(pr, mag, ms, vs, &cluster_count, &fat_size))
  284. return 1;
  285. sector_size = unaligned_le16(&ms->ms_sector_size);
  286. reserved = le16_to_cpu(ms->ms_reserved);
  287. if (ms->ms_fat_length) {
  288. /* the label may be an attribute in the root directory */
  289. uint32_t root_start = (reserved + fat_size) * sector_size;
  290. uint32_t root_dir_entries = unaligned_le16(&vs->vs_dir_entries);
  291. vol_label = search_fat_label(pr, root_start, root_dir_entries);
  292. if (vol_label) {
  293. memcpy(vol_label_buf, vol_label, 11);
  294. vol_label = vol_label_buf;
  295. }
  296. boot_label = ms->ms_label;
  297. vol_serno = ms->ms_serno;
  298. blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "msdos",
  299. sizeof("msdos"));
  300. if (cluster_count < FAT12_MAX)
  301. version = "FAT12";
  302. else if (cluster_count < FAT16_MAX)
  303. version = "FAT16";
  304. } else if (vs->vs_fat32_length) {
  305. unsigned char *buf;
  306. uint16_t fsinfo_sect;
  307. int maxloop = 100;
  308. /* Search the FAT32 root dir for the label attribute */
  309. uint32_t buf_size = vs->vs_cluster_size * sector_size;
  310. uint32_t start_data_sect = reserved + fat_size;
  311. uint32_t entries = le32_to_cpu(vs->vs_fat32_length) *
  312. sector_size / sizeof(uint32_t);
  313. uint32_t next = le32_to_cpu(vs->vs_root_cluster);
  314. while (next && next < entries && --maxloop) {
  315. uint32_t next_sect_off;
  316. uint64_t next_off, fat_entry_off;
  317. int count;
  318. next_sect_off = (next - 2) * vs->vs_cluster_size;
  319. next_off = (uint64_t)(start_data_sect + next_sect_off) *
  320. sector_size;
  321. count = buf_size / sizeof(struct vfat_dir_entry);
  322. vol_label = search_fat_label(pr, next_off, count);
  323. if (vol_label) {
  324. memcpy(vol_label_buf, vol_label, 11);
  325. vol_label = vol_label_buf;
  326. break;
  327. }
  328. /* get FAT entry */
  329. fat_entry_off = ((uint64_t) reserved * sector_size) +
  330. (next * sizeof(uint32_t));
  331. buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size);
  332. if (buf == NULL)
  333. break;
  334. /* set next cluster */
  335. next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff;
  336. }
  337. version = "FAT32";
  338. boot_label = vs->vs_label;
  339. vol_serno = vs->vs_serno;
  340. /*
  341. * FAT32 should have a valid signature in the fsinfo block,
  342. * but also allow all bytes set to '\0', because some volumes
  343. * do not set the signature at all.
  344. */
  345. fsinfo_sect = le16_to_cpu(vs->vs_fsinfo_sector);
  346. if (fsinfo_sect) {
  347. struct fat32_fsinfo *fsinfo;
  348. buf = blkid_probe_get_buffer(pr,
  349. (blkid_loff_t) fsinfo_sect * sector_size,
  350. sizeof(struct fat32_fsinfo));
  351. if (buf == NULL)
  352. return errno ? -errno : 1;
  353. fsinfo = (struct fat32_fsinfo *) buf;
  354. if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 &&
  355. memcmp(fsinfo->signature1, "\x52\x52\x64\x41", 4) != 0 &&
  356. memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0)
  357. return 1;
  358. if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 &&
  359. memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0)
  360. return 1;
  361. }
  362. }
  363. if (boot_label && memcmp(boot_label, no_name, 11))
  364. blkid_probe_set_id_label(pr, "LABEL_FATBOOT", (unsigned char *) boot_label, 11);
  365. if (vol_label) {
  366. strtok((char *) vol_label, " ");
  367. blkid_probe_set_label(pr, (unsigned char *) vol_label, 11);
  368. }
  369. /* We can't just print them as %04X, because they are unaligned */
  370. if (vol_serno)
  371. blkid_probe_sprintf_uuid(pr, vol_serno, 4, "%02X%02X-%02X%02X",
  372. vol_serno[3], vol_serno[2], vol_serno[1], vol_serno[0]);
  373. if (version)
  374. blkid_probe_set_version(pr, version);
  375. return 0;
  376. }
  377. const struct blkid_idinfo vfat_idinfo =
  378. {
  379. .name = "vfat",
  380. .usage = BLKID_USAGE_FILESYSTEM,
  381. .probefunc = probe_vfat,
  382. .magics =
  383. {
  384. { .magic = "MSWIN", .len = 5, .sboff = 0x52 },
  385. { .magic = "FAT32 ", .len = 8, .sboff = 0x52 },
  386. { .magic = "MSDOS", .len = 5, .sboff = 0x36 },
  387. { .magic = "FAT16 ", .len = 8, .sboff = 0x36 },
  388. { .magic = "FAT12 ", .len = 8, .sboff = 0x36 },
  389. { .magic = "FAT ", .len = 8, .sboff = 0x36 },
  390. { .magic = "\353", .len = 1, },
  391. { .magic = "\351", .len = 1, },
  392. { .magic = "\125\252", .len = 2, .sboff = 0x1fe },
  393. { NULL }
  394. }
  395. };