fat.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. /* fat.c - FAT filesystem */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/fs.h>
  20. #include <grub/disk.h>
  21. #include <grub/file.h>
  22. #include <grub/types.h>
  23. #include <grub/misc.h>
  24. #include <grub/mm.h>
  25. #include <grub/err.h>
  26. #include <grub/dl.h>
  27. #include <grub/charset.h>
  28. #define GRUB_FAT_DIR_ENTRY_SIZE 32
  29. #define GRUB_FAT_ATTR_READ_ONLY 0x01
  30. #define GRUB_FAT_ATTR_HIDDEN 0x02
  31. #define GRUB_FAT_ATTR_SYSTEM 0x04
  32. #define GRUB_FAT_ATTR_VOLUME_ID 0x08
  33. #define GRUB_FAT_ATTR_DIRECTORY 0x10
  34. #define GRUB_FAT_ATTR_ARCHIVE 0x20
  35. #define GRUB_FAT_MAXFILE 256
  36. #define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
  37. | GRUB_FAT_ATTR_HIDDEN \
  38. | GRUB_FAT_ATTR_SYSTEM \
  39. | GRUB_FAT_ATTR_VOLUME_ID)
  40. #define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
  41. | GRUB_FAT_ATTR_HIDDEN \
  42. | GRUB_FAT_ATTR_SYSTEM \
  43. | GRUB_FAT_ATTR_DIRECTORY \
  44. | GRUB_FAT_ATTR_ARCHIVE \
  45. | GRUB_FAT_ATTR_VOLUME_ID)
  46. struct grub_fat_bpb
  47. {
  48. grub_uint8_t jmp_boot[3];
  49. grub_uint8_t oem_name[8];
  50. grub_uint16_t bytes_per_sector;
  51. grub_uint8_t sectors_per_cluster;
  52. grub_uint16_t num_reserved_sectors;
  53. grub_uint8_t num_fats;
  54. grub_uint16_t num_root_entries;
  55. grub_uint16_t num_total_sectors_16;
  56. grub_uint8_t media;
  57. grub_uint16_t sectors_per_fat_16;
  58. grub_uint16_t sectors_per_track;
  59. grub_uint16_t num_heads;
  60. grub_uint32_t num_hidden_sectors;
  61. grub_uint32_t num_total_sectors_32;
  62. union
  63. {
  64. struct
  65. {
  66. grub_uint8_t num_ph_drive;
  67. grub_uint8_t reserved;
  68. grub_uint8_t boot_sig;
  69. grub_uint32_t num_serial;
  70. grub_uint8_t label[11];
  71. grub_uint8_t fstype[8];
  72. } __attribute__ ((packed)) fat12_or_fat16;
  73. struct
  74. {
  75. grub_uint32_t sectors_per_fat_32;
  76. grub_uint16_t extended_flags;
  77. grub_uint16_t fs_version;
  78. grub_uint32_t root_cluster;
  79. grub_uint16_t fs_info;
  80. grub_uint16_t backup_boot_sector;
  81. grub_uint8_t reserved[12];
  82. grub_uint8_t num_ph_drive;
  83. grub_uint8_t reserved1;
  84. grub_uint8_t boot_sig;
  85. grub_uint32_t num_serial;
  86. grub_uint8_t label[11];
  87. grub_uint8_t fstype[8];
  88. } __attribute__ ((packed)) fat32;
  89. } __attribute__ ((packed)) version_specific;
  90. } __attribute__ ((packed));
  91. struct grub_fat_dir_entry
  92. {
  93. grub_uint8_t name[11];
  94. grub_uint8_t attr;
  95. grub_uint8_t nt_reserved;
  96. grub_uint8_t c_time_tenth;
  97. grub_uint16_t c_time;
  98. grub_uint16_t c_date;
  99. grub_uint16_t a_date;
  100. grub_uint16_t first_cluster_high;
  101. grub_uint16_t w_time;
  102. grub_uint16_t w_date;
  103. grub_uint16_t first_cluster_low;
  104. grub_uint32_t file_size;
  105. } __attribute__ ((packed));
  106. struct grub_fat_long_name_entry
  107. {
  108. grub_uint8_t id;
  109. grub_uint16_t name1[5];
  110. grub_uint8_t attr;
  111. grub_uint8_t reserved;
  112. grub_uint8_t checksum;
  113. grub_uint16_t name2[6];
  114. grub_uint16_t first_cluster;
  115. grub_uint16_t name3[2];
  116. } __attribute__ ((packed));
  117. struct grub_fat_data
  118. {
  119. int logical_sector_bits;
  120. grub_uint32_t num_sectors;
  121. grub_uint16_t fat_sector;
  122. grub_uint32_t sectors_per_fat;
  123. int fat_size;
  124. grub_uint32_t root_cluster;
  125. grub_uint32_t root_sector;
  126. grub_uint32_t num_root_sectors;
  127. int cluster_bits;
  128. grub_uint32_t cluster_eof_mark;
  129. grub_uint32_t cluster_sector;
  130. grub_uint32_t num_clusters;
  131. grub_uint8_t attr;
  132. grub_ssize_t file_size;
  133. grub_uint32_t file_cluster;
  134. grub_uint32_t cur_cluster_num;
  135. grub_uint32_t cur_cluster;
  136. grub_uint32_t uuid;
  137. };
  138. static grub_dl_t my_mod;
  139. static int
  140. fat_log2 (unsigned x)
  141. {
  142. int i;
  143. if (x == 0)
  144. return -1;
  145. for (i = 0; (x & 1) == 0; i++)
  146. x >>= 1;
  147. if (x != 1)
  148. return -1;
  149. return i;
  150. }
  151. static struct grub_fat_data *
  152. grub_fat_mount (grub_disk_t disk)
  153. {
  154. struct grub_fat_bpb bpb;
  155. struct grub_fat_data *data = 0;
  156. grub_uint32_t first_fat, magic;
  157. if (! disk)
  158. goto fail;
  159. data = (struct grub_fat_data *) grub_malloc (sizeof (*data));
  160. if (! data)
  161. goto fail;
  162. /* Read the BPB. */
  163. if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
  164. goto fail;
  165. if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5)
  166. && grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5)
  167. && grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5))
  168. goto fail;
  169. /* Get the sizes of logical sectors and clusters. */
  170. data->logical_sector_bits =
  171. fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
  172. if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS)
  173. goto fail;
  174. data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
  175. data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
  176. if (data->cluster_bits < 0)
  177. goto fail;
  178. data->cluster_bits += data->logical_sector_bits;
  179. /* Get information about FATs. */
  180. data->fat_sector = (grub_le_to_cpu16 (bpb.num_reserved_sectors)
  181. << data->logical_sector_bits);
  182. if (data->fat_sector == 0)
  183. goto fail;
  184. data->sectors_per_fat = ((bpb.sectors_per_fat_16
  185. ? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
  186. : grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
  187. << data->logical_sector_bits);
  188. if (data->sectors_per_fat == 0)
  189. goto fail;
  190. /* Get the number of sectors in this volume. */
  191. data->num_sectors = ((bpb.num_total_sectors_16
  192. ? grub_le_to_cpu16 (bpb.num_total_sectors_16)
  193. : grub_le_to_cpu32 (bpb.num_total_sectors_32))
  194. << data->logical_sector_bits);
  195. if (data->num_sectors == 0)
  196. goto fail;
  197. /* Get information about the root directory. */
  198. if (bpb.num_fats == 0)
  199. goto fail;
  200. data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
  201. data->num_root_sectors
  202. = ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
  203. * GRUB_FAT_DIR_ENTRY_SIZE
  204. + grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
  205. >> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
  206. << (data->logical_sector_bits));
  207. data->cluster_sector = data->root_sector + data->num_root_sectors;
  208. data->num_clusters = (((data->num_sectors - data->cluster_sector)
  209. >> (data->cluster_bits + data->logical_sector_bits))
  210. + 2);
  211. if (data->num_clusters <= 2)
  212. goto fail;
  213. if (! bpb.sectors_per_fat_16)
  214. {
  215. /* FAT32. */
  216. grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
  217. data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
  218. data->fat_size = 32;
  219. data->cluster_eof_mark = 0x0ffffff8;
  220. if (flags & 0x80)
  221. {
  222. /* Get an active FAT. */
  223. unsigned active_fat = flags & 0xf;
  224. if (active_fat > bpb.num_fats)
  225. goto fail;
  226. data->fat_sector += active_fat * data->sectors_per_fat;
  227. }
  228. if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
  229. goto fail;
  230. }
  231. else
  232. {
  233. /* FAT12 or FAT16. */
  234. data->root_cluster = ~0U;
  235. if (data->num_clusters <= 4085 + 2)
  236. {
  237. /* FAT12. */
  238. data->fat_size = 12;
  239. data->cluster_eof_mark = 0x0ff8;
  240. }
  241. else
  242. {
  243. /* FAT16. */
  244. data->fat_size = 16;
  245. data->cluster_eof_mark = 0xfff8;
  246. }
  247. }
  248. /* More sanity checks. */
  249. if (data->num_sectors <= data->fat_sector)
  250. goto fail;
  251. if (grub_disk_read (disk,
  252. data->fat_sector,
  253. 0,
  254. sizeof (first_fat),
  255. &first_fat))
  256. goto fail;
  257. first_fat = grub_le_to_cpu32 (first_fat);
  258. if (data->fat_size == 32)
  259. {
  260. first_fat &= 0x0fffffff;
  261. magic = 0x0fffff00;
  262. }
  263. else if (data->fat_size == 16)
  264. {
  265. first_fat &= 0x0000ffff;
  266. magic = 0xff00;
  267. }
  268. else
  269. {
  270. first_fat &= 0x00000fff;
  271. magic = 0x0f00;
  272. }
  273. /* Serial number. */
  274. if (bpb.sectors_per_fat_16)
  275. data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
  276. else
  277. data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
  278. /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
  279. descriptor, even if it is a so-called superfloppy (e.g. an USB key).
  280. The check may be too strict for this kind of stupid BIOSes, as
  281. they overwrite the media descriptor. */
  282. if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
  283. goto fail;
  284. /* Start from the root directory. */
  285. data->file_cluster = data->root_cluster;
  286. data->cur_cluster_num = ~0U;
  287. data->attr = GRUB_FAT_ATTR_DIRECTORY;
  288. return data;
  289. fail:
  290. grub_free (data);
  291. grub_error (GRUB_ERR_BAD_FS, "not a FAT filesystem");
  292. return 0;
  293. }
  294. static grub_ssize_t
  295. grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
  296. void (*read_hook) (grub_disk_addr_t sector,
  297. unsigned offset, unsigned length,
  298. void *closure),
  299. void *closure, int flags,
  300. grub_off_t offset, grub_size_t len, char *buf)
  301. {
  302. grub_size_t size;
  303. grub_uint32_t logical_cluster;
  304. unsigned logical_cluster_bits;
  305. grub_ssize_t ret = 0;
  306. unsigned long sector;
  307. /* This is a special case. FAT12 and FAT16 doesn't have the root directory
  308. in clusters. */
  309. if (data->file_cluster == ~0U)
  310. {
  311. size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
  312. if (size > len)
  313. size = len;
  314. if (grub_disk_read (disk, data->root_sector, offset, size, buf))
  315. return -1;
  316. return size;
  317. }
  318. /* Calculate the logical cluster number and offset. */
  319. logical_cluster_bits = (data->cluster_bits
  320. + data->logical_sector_bits
  321. + GRUB_DISK_SECTOR_BITS);
  322. logical_cluster = offset >> logical_cluster_bits;
  323. offset &= (1 << logical_cluster_bits) - 1;
  324. if (logical_cluster < data->cur_cluster_num)
  325. {
  326. data->cur_cluster_num = 0;
  327. data->cur_cluster = data->file_cluster;
  328. }
  329. while (len)
  330. {
  331. while (logical_cluster > data->cur_cluster_num)
  332. {
  333. /* Find next cluster. */
  334. grub_uint32_t next_cluster;
  335. unsigned long fat_offset;
  336. switch (data->fat_size)
  337. {
  338. case 32:
  339. fat_offset = data->cur_cluster << 2;
  340. break;
  341. case 16:
  342. fat_offset = data->cur_cluster << 1;
  343. break;
  344. default:
  345. /* case 12: */
  346. fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
  347. break;
  348. }
  349. /* Read the FAT. */
  350. if (grub_disk_read (disk, data->fat_sector, fat_offset,
  351. (data->fat_size + 7) >> 3,
  352. (char *) &next_cluster))
  353. return -1;
  354. next_cluster = grub_le_to_cpu32 (next_cluster);
  355. switch (data->fat_size)
  356. {
  357. case 16:
  358. next_cluster &= 0xFFFF;
  359. break;
  360. case 12:
  361. if (data->cur_cluster & 1)
  362. next_cluster >>= 4;
  363. next_cluster &= 0x0FFF;
  364. break;
  365. }
  366. grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
  367. data->fat_size, next_cluster);
  368. /* Check the end. */
  369. if (next_cluster >= data->cluster_eof_mark)
  370. return ret;
  371. if (next_cluster < 2 || next_cluster >= data->num_clusters)
  372. {
  373. grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
  374. next_cluster);
  375. return -1;
  376. }
  377. data->cur_cluster = next_cluster;
  378. data->cur_cluster_num++;
  379. }
  380. /* Read the data here. */
  381. sector = (data->cluster_sector
  382. + ((data->cur_cluster - 2)
  383. << (data->cluster_bits + data->logical_sector_bits)));
  384. size = (1 << logical_cluster_bits) - offset;
  385. if (size > len)
  386. size = len;
  387. disk->read_hook = read_hook;
  388. disk->closure = closure;
  389. grub_disk_read_ex (disk, sector, offset, size, buf, flags);
  390. disk->read_hook = 0;
  391. if (grub_errno)
  392. return -1;
  393. len -= size;
  394. if (buf)
  395. buf += size;
  396. ret += size;
  397. logical_cluster++;
  398. offset = 0;
  399. }
  400. return ret;
  401. }
  402. static grub_err_t
  403. grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
  404. int (*hook) (const char *filename,
  405. struct grub_fat_dir_entry *dir,
  406. void *closure),
  407. void *closure)
  408. {
  409. struct grub_fat_dir_entry dir;
  410. char *filename, *filep = 0;
  411. grub_uint16_t *unibuf;
  412. int slot = -1, slots = -1;
  413. int checksum = -1;
  414. grub_ssize_t offset = -sizeof(dir);
  415. if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
  416. return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
  417. /* Allocate space enough to hold a long name. */
  418. filename = grub_malloc (0x40 * 13 * 4 + 1);
  419. unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
  420. if (! filename || ! unibuf)
  421. {
  422. grub_free (filename);
  423. grub_free (unibuf);
  424. return 0;
  425. }
  426. while (1)
  427. {
  428. unsigned i;
  429. /* Adjust the offset. */
  430. offset += sizeof (dir);
  431. /* Read a directory entry. */
  432. if ((grub_fat_read_data (disk, data, 0, 0, 0,
  433. offset, sizeof (dir), (char *) &dir)
  434. != sizeof (dir) || dir.name[0] == 0))
  435. break;
  436. /* Handle long name entries. */
  437. if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
  438. {
  439. struct grub_fat_long_name_entry *long_name
  440. = (struct grub_fat_long_name_entry *) &dir;
  441. grub_uint8_t id = long_name->id;
  442. if (id & 0x40)
  443. {
  444. id &= 0x3f;
  445. slots = slot = id;
  446. checksum = long_name->checksum;
  447. }
  448. if (id != slot || slot == 0 || checksum != long_name->checksum)
  449. {
  450. checksum = -1;
  451. continue;
  452. }
  453. slot--;
  454. grub_memcpy (unibuf + slot * 13, long_name->name1, 5 * 2);
  455. grub_memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
  456. grub_memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
  457. continue;
  458. }
  459. /* Check if this entry is valid. */
  460. if (dir.name[0] == 0xe5 || (dir.attr & ~GRUB_FAT_ATTR_VALID))
  461. continue;
  462. /* This is a workaround for Japanese. */
  463. if (dir.name[0] == 0x05)
  464. dir.name[0] = 0xe5;
  465. if (checksum != -1 && slot == 0)
  466. {
  467. grub_uint8_t sum;
  468. for (sum = 0, i = 0; i < sizeof (dir.name); i++)
  469. sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
  470. if (sum == checksum)
  471. {
  472. int u;
  473. for (u = 0; u < slots * 13; u++)
  474. unibuf[u] = grub_le_to_cpu16 (unibuf[u]);
  475. *grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
  476. slots * 13) = '\0';
  477. if (hook (filename, &dir, closure))
  478. break;
  479. checksum = -1;
  480. continue;
  481. }
  482. checksum = -1;
  483. }
  484. /* Convert the 8.3 file name. */
  485. filep = filename;
  486. if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
  487. {
  488. for (i = 0; i < sizeof (dir.name) && dir.name[i]
  489. && ! grub_isspace (dir.name[i]); i++)
  490. *filep++ = dir.name[i];
  491. }
  492. else
  493. {
  494. for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
  495. *filep++ = grub_tolower (dir.name[i]);
  496. *filep = '.';
  497. for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
  498. *++filep = grub_tolower (dir.name[i]);
  499. if (*filep != '.')
  500. filep++;
  501. }
  502. *filep = '\0';
  503. if (hook (filename, &dir, closure))
  504. break;
  505. }
  506. grub_free (filename);
  507. grub_free (unibuf);
  508. return grub_errno;
  509. }
  510. struct grub_fat_find_dir_closure
  511. {
  512. struct grub_fat_data *data;
  513. int (*hook) (const char *filename,
  514. const struct grub_dirhook_info *info,
  515. void *closure);
  516. void *closure;
  517. char *dirname;
  518. int call_hook;
  519. int found;
  520. };
  521. static int
  522. grub_fat_find_dir_hook (const char *filename, struct grub_fat_dir_entry *dir,
  523. void *closure)
  524. {
  525. struct grub_fat_find_dir_closure *c = closure;
  526. struct grub_dirhook_info info;
  527. grub_memset (&info, 0, sizeof (info));
  528. info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
  529. info.case_insensitive = 1;
  530. if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
  531. return 0;
  532. if (*(c->dirname) == '\0' && (c->call_hook))
  533. return c->hook (filename, &info, c->closure);
  534. if (grub_strcasecmp (c->dirname, filename) == 0)
  535. {
  536. struct grub_fat_data *data = c->data;
  537. c->found = 1;
  538. data->attr = dir->attr;
  539. data->file_size = grub_le_to_cpu32 (dir->file_size);
  540. data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
  541. | grub_le_to_cpu16 (dir->first_cluster_low));
  542. data->cur_cluster_num = ~0U;
  543. if (c->call_hook)
  544. c->hook (filename, &info, c->closure);
  545. return 1;
  546. }
  547. return 0;
  548. }
  549. /* Find the underlying directory or file in PATH and return the
  550. next path. If there is no next path or an error occurs, return NULL.
  551. If HOOK is specified, call it with each file name. */
  552. static char *
  553. grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
  554. const char *path,
  555. int (*hook) (const char *filename,
  556. const struct grub_dirhook_info *info,
  557. void *closure),
  558. void *closure)
  559. {
  560. char *dirname, *dirp;
  561. struct grub_fat_find_dir_closure c;
  562. if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
  563. {
  564. grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
  565. return 0;
  566. }
  567. /* Extract a directory name. */
  568. while (*path == '/')
  569. path++;
  570. dirp = grub_strchr (path, '/');
  571. if (dirp)
  572. {
  573. unsigned len = dirp - path;
  574. dirname = grub_malloc (len + 1);
  575. if (! dirname)
  576. return 0;
  577. grub_memcpy (dirname, path, len);
  578. dirname[len] = '\0';
  579. }
  580. else
  581. /* This is actually a file. */
  582. dirname = grub_strdup (path);
  583. c.data = data;
  584. c.hook = hook;
  585. c.closure = closure;
  586. c.dirname =dirname;
  587. c.found = 0;
  588. c.call_hook = (! dirp && hook);
  589. grub_fat_iterate_dir (disk, data, grub_fat_find_dir_hook, &c);
  590. if (grub_errno == GRUB_ERR_NONE && ! c.found && !c.call_hook)
  591. grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
  592. grub_free (dirname);
  593. return c.found ? dirp : 0;
  594. }
  595. static grub_err_t
  596. grub_fat_dir (grub_device_t device, const char *path,
  597. int (*hook) (const char *filename,
  598. const struct grub_dirhook_info *info, void *closure),
  599. void *closure)
  600. {
  601. struct grub_fat_data *data = 0;
  602. grub_disk_t disk = device->disk;
  603. grub_size_t len;
  604. char *dirname = 0;
  605. char *p;
  606. grub_dl_ref (my_mod);
  607. data = grub_fat_mount (disk);
  608. if (! data)
  609. goto fail;
  610. /* Make sure that DIRNAME terminates with '/'. */
  611. len = grub_strlen (path);
  612. dirname = grub_malloc (len + 1 + 1);
  613. if (! dirname)
  614. goto fail;
  615. grub_memcpy (dirname, path, len);
  616. p = dirname + len;
  617. if (path[len - 1] != '/')
  618. *p++ = '/';
  619. *p = '\0';
  620. p = dirname;
  621. do
  622. {
  623. p = grub_fat_find_dir (disk, data, p, hook, closure);
  624. }
  625. while (p && grub_errno == GRUB_ERR_NONE);
  626. fail:
  627. grub_free (dirname);
  628. grub_free (data);
  629. grub_dl_unref (my_mod);
  630. return grub_errno;
  631. }
  632. static grub_err_t
  633. grub_fat_open (grub_file_t file, const char *name)
  634. {
  635. struct grub_fat_data *data = 0;
  636. char *p = (char *) name;
  637. grub_dl_ref (my_mod);
  638. data = grub_fat_mount (file->device->disk);
  639. if (! data)
  640. goto fail;
  641. do
  642. {
  643. p = grub_fat_find_dir (file->device->disk, data, p, 0, 0);
  644. if (grub_errno != GRUB_ERR_NONE)
  645. goto fail;
  646. }
  647. while (p);
  648. if (data->attr & GRUB_FAT_ATTR_DIRECTORY)
  649. {
  650. grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
  651. goto fail;
  652. }
  653. file->data = data;
  654. file->size = data->file_size;
  655. return GRUB_ERR_NONE;
  656. fail:
  657. grub_free (data);
  658. grub_dl_unref (my_mod);
  659. return grub_errno;
  660. }
  661. static grub_ssize_t
  662. grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
  663. {
  664. return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
  665. file->closure, file->flags,
  666. file->offset, len, buf);
  667. }
  668. static grub_err_t
  669. grub_fat_close (grub_file_t file)
  670. {
  671. grub_free (file->data);
  672. grub_dl_unref (my_mod);
  673. return grub_errno;
  674. }
  675. static int
  676. grub_fat_label_hook (const char *filename, struct grub_fat_dir_entry *dir,
  677. void *closure)
  678. {
  679. char **label = closure;
  680. if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
  681. {
  682. *label = grub_strdup (filename);
  683. return 1;
  684. }
  685. return 0;
  686. }
  687. static grub_err_t
  688. grub_fat_label (grub_device_t device, char **label)
  689. {
  690. struct grub_fat_data *data;
  691. grub_disk_t disk = device->disk;
  692. grub_dl_ref (my_mod);
  693. data = grub_fat_mount (disk);
  694. if (! data)
  695. goto fail;
  696. if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
  697. {
  698. grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
  699. return 0;
  700. }
  701. *label = 0;
  702. grub_fat_iterate_dir (disk, data, grub_fat_label_hook, label);
  703. fail:
  704. grub_dl_unref (my_mod);
  705. grub_free (data);
  706. return grub_errno;
  707. }
  708. static grub_err_t
  709. grub_fat_uuid (grub_device_t device, char **uuid)
  710. {
  711. struct grub_fat_data *data;
  712. grub_disk_t disk = device->disk;
  713. grub_dl_ref (my_mod);
  714. data = grub_fat_mount (disk);
  715. if (data)
  716. {
  717. *uuid = grub_xasprintf ("%04x-%04x",
  718. (grub_uint16_t) (data->uuid >> 16),
  719. (grub_uint16_t) data->uuid);
  720. }
  721. else
  722. *uuid = NULL;
  723. grub_dl_unref (my_mod);
  724. grub_free (data);
  725. return grub_errno;
  726. }
  727. static struct grub_fs grub_fat_fs =
  728. {
  729. .name = "fat",
  730. .dir = grub_fat_dir,
  731. .open = grub_fat_open,
  732. .read = grub_fat_read,
  733. .close = grub_fat_close,
  734. .label = grub_fat_label,
  735. .uuid = grub_fat_uuid,
  736. #ifdef GRUB_UTIL
  737. .reserved_first_sector = 1,
  738. #endif
  739. .next = 0
  740. };
  741. GRUB_MOD_INIT(fat)
  742. {
  743. grub_fs_register (&grub_fat_fs);
  744. my_mod = mod;
  745. }
  746. GRUB_MOD_FINI(fat)
  747. {
  748. grub_fs_unregister (&grub_fat_fs);
  749. }