ntfs.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. /* ntfs.c - NTFS filesystem */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
  5. *
  6. * This program 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. * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #define grub_fshelp_node grub_ntfs_file
  20. #include <grub/file.h>
  21. #include <grub/mm.h>
  22. #include <grub/misc.h>
  23. #include <grub/disk.h>
  24. #include <grub/dl.h>
  25. #include <grub/fshelp.h>
  26. #include <grub/ntfs.h>
  27. #include <grub/charset.h>
  28. GRUB_MOD_LICENSE ("GPLv3+");
  29. static grub_dl_t my_mod;
  30. #define grub_fshelp_node grub_ntfs_file
  31. static inline grub_uint16_t
  32. u16at (void *ptr, grub_size_t ofs)
  33. {
  34. return grub_le_to_cpu16 (grub_get_unaligned16 ((char *) ptr + ofs));
  35. }
  36. static inline grub_uint32_t
  37. u32at (void *ptr, grub_size_t ofs)
  38. {
  39. return grub_le_to_cpu32 (grub_get_unaligned32 ((char *) ptr + ofs));
  40. }
  41. static inline grub_uint64_t
  42. u64at (void *ptr, grub_size_t ofs)
  43. {
  44. return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs));
  45. }
  46. static grub_uint16_t
  47. first_attr_off (void *mft_buf_ptr)
  48. {
  49. return u16at (mft_buf_ptr, 0x14);
  50. }
  51. static grub_uint16_t
  52. res_attr_data_off (void *res_attr_ptr)
  53. {
  54. return u16at (res_attr_ptr, 0x14);
  55. }
  56. static grub_uint32_t
  57. res_attr_data_len (void *res_attr_ptr)
  58. {
  59. return u32at (res_attr_ptr, 0x10);
  60. }
  61. grub_ntfscomp_func_t grub_ntfscomp_func;
  62. static grub_err_t
  63. fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic)
  64. {
  65. grub_uint16_t ss;
  66. grub_uint8_t *pu;
  67. grub_uint16_t us;
  68. COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE);
  69. if (grub_memcmp (buf, magic, 4))
  70. return grub_error (GRUB_ERR_BAD_FS, "%s label not found", magic);
  71. ss = u16at (buf, 6) - 1;
  72. if (ss != len)
  73. return grub_error (GRUB_ERR_BAD_FS, "size not match");
  74. pu = buf + u16at (buf, 4);
  75. us = u16at (pu, 0);
  76. buf -= 2;
  77. while (ss > 0)
  78. {
  79. buf += GRUB_DISK_SECTOR_SIZE;
  80. pu += 2;
  81. if (u16at (buf, 0) != us)
  82. return grub_error (GRUB_ERR_BAD_FS, "fixup signature not match");
  83. buf[0] = pu[0];
  84. buf[1] = pu[1];
  85. ss--;
  86. }
  87. return 0;
  88. }
  89. static grub_err_t read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf,
  90. grub_uint64_t mftno);
  91. static grub_err_t read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest,
  92. grub_disk_addr_t ofs, grub_size_t len,
  93. int cached,
  94. grub_disk_read_hook_t read_hook,
  95. void *read_hook_data);
  96. static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
  97. grub_uint8_t *dest,
  98. grub_disk_addr_t ofs, grub_size_t len,
  99. int cached,
  100. grub_disk_read_hook_t read_hook,
  101. void *read_hook_data);
  102. static void
  103. init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
  104. {
  105. at->mft = mft;
  106. at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
  107. at->attr_nxt = mft->buf + first_attr_off (mft->buf);
  108. at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
  109. }
  110. static void
  111. free_attr (struct grub_ntfs_attr *at)
  112. {
  113. grub_free (at->emft_buf);
  114. grub_free (at->edat_buf);
  115. grub_free (at->sbuf);
  116. }
  117. static grub_uint8_t *
  118. find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
  119. {
  120. if (at->flags & GRUB_NTFS_AF_ALST)
  121. {
  122. retry:
  123. while (at->attr_nxt < at->attr_end)
  124. {
  125. at->attr_cur = at->attr_nxt;
  126. at->attr_nxt += u16at (at->attr_cur, 4);
  127. if ((*at->attr_cur == attr) || (attr == 0))
  128. {
  129. grub_uint8_t *new_pos;
  130. if (at->flags & GRUB_NTFS_AF_MMFT)
  131. {
  132. if ((grub_disk_read
  133. (at->mft->data->disk, u32at (at->attr_cur, 0x10), 0,
  134. 512, at->emft_buf))
  135. ||
  136. (grub_disk_read
  137. (at->mft->data->disk, u32at (at->attr_cur, 0x14), 0,
  138. 512, at->emft_buf + 512)))
  139. return NULL;
  140. if (fixup (at->emft_buf, at->mft->data->mft_size,
  141. (const grub_uint8_t *) "FILE"))
  142. return NULL;
  143. }
  144. else
  145. {
  146. if (read_mft (at->mft->data, at->emft_buf,
  147. u32at (at->attr_cur, 0x10)))
  148. return NULL;
  149. }
  150. new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
  151. while (*new_pos != 0xFF)
  152. {
  153. if ((*new_pos == *at->attr_cur)
  154. && (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
  155. {
  156. return new_pos;
  157. }
  158. new_pos += u16at (new_pos, 4);
  159. }
  160. grub_error (GRUB_ERR_BAD_FS,
  161. "can\'t find 0x%X in attribute list",
  162. (unsigned char) *at->attr_cur);
  163. return NULL;
  164. }
  165. }
  166. return NULL;
  167. }
  168. at->attr_cur = at->attr_nxt;
  169. while (*at->attr_cur != 0xFF)
  170. {
  171. at->attr_nxt += u16at (at->attr_cur, 4);
  172. if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
  173. at->attr_end = at->attr_cur;
  174. if ((*at->attr_cur == attr) || (attr == 0))
  175. return at->attr_cur;
  176. at->attr_cur = at->attr_nxt;
  177. }
  178. if (at->attr_end)
  179. {
  180. grub_uint8_t *pa, *pa_end;
  181. at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
  182. if (at->emft_buf == NULL)
  183. return NULL;
  184. pa = at->attr_end;
  185. if (pa[8])
  186. {
  187. grub_uint32_t n;
  188. n = ((u32at (pa, 0x30) + GRUB_DISK_SECTOR_SIZE - 1)
  189. & (~(GRUB_DISK_SECTOR_SIZE - 1)));
  190. at->attr_cur = at->attr_end;
  191. at->edat_buf = grub_malloc (n);
  192. if (!at->edat_buf)
  193. return NULL;
  194. if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0))
  195. {
  196. grub_error (GRUB_ERR_BAD_FS,
  197. "fail to read non-resident attribute list");
  198. return NULL;
  199. }
  200. at->attr_nxt = at->edat_buf;
  201. at->attr_end = at->edat_buf + u32at (pa, 0x30);
  202. pa_end = at->edat_buf + n;
  203. }
  204. else
  205. {
  206. at->attr_nxt = at->attr_end + res_attr_data_off (pa);
  207. at->attr_end = at->attr_end + u32at (pa, 4);
  208. pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
  209. }
  210. at->flags |= GRUB_NTFS_AF_ALST;
  211. while (at->attr_nxt < at->attr_end)
  212. {
  213. if ((*at->attr_nxt == attr) || (attr == 0))
  214. break;
  215. at->attr_nxt += u16at (at->attr_nxt, 4);
  216. }
  217. if (at->attr_nxt >= at->attr_end)
  218. return NULL;
  219. if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA))
  220. {
  221. at->flags |= GRUB_NTFS_AF_GPOS;
  222. at->attr_cur = at->attr_nxt;
  223. pa = at->attr_cur;
  224. if ((pa >= pa_end) || (pa_end - pa < 0x18))
  225. {
  226. grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
  227. return NULL;
  228. }
  229. grub_set_unaligned32 ((char *) pa + 0x10,
  230. grub_cpu_to_le32 (at->mft->data->mft_start));
  231. grub_set_unaligned32 ((char *) pa + 0x14,
  232. grub_cpu_to_le32 (at->mft->data->mft_start
  233. + 1));
  234. pa = at->attr_nxt + u16at (pa, 4);
  235. while (pa < at->attr_end)
  236. {
  237. if (*pa != attr)
  238. break;
  239. if ((pa >= pa_end) || (pa_end - pa < 0x18))
  240. {
  241. grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
  242. return NULL;
  243. }
  244. if (read_attr
  245. (at, pa + 0x10,
  246. u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
  247. at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
  248. return NULL;
  249. pa += u16at (pa, 4);
  250. }
  251. at->attr_nxt = at->attr_cur;
  252. at->flags &= ~GRUB_NTFS_AF_GPOS;
  253. }
  254. goto retry;
  255. }
  256. return NULL;
  257. }
  258. static grub_uint8_t *
  259. locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
  260. grub_uint8_t attr)
  261. {
  262. grub_uint8_t *pa;
  263. init_attr (at, mft);
  264. pa = find_attr (at, attr);
  265. if (pa == NULL)
  266. return NULL;
  267. if ((at->flags & GRUB_NTFS_AF_ALST) == 0)
  268. {
  269. while (1)
  270. {
  271. pa = find_attr (at, attr);
  272. if (pa == NULL)
  273. break;
  274. if (at->flags & GRUB_NTFS_AF_ALST)
  275. return pa;
  276. }
  277. grub_errno = GRUB_ERR_NONE;
  278. free_attr (at);
  279. init_attr (at, mft);
  280. pa = find_attr (at, attr);
  281. }
  282. return pa;
  283. }
  284. static grub_disk_addr_t
  285. read_run_data (const grub_uint8_t *run, int nn, int sig)
  286. {
  287. grub_uint64_t r = 0;
  288. if (sig && nn && (run[nn - 1] & 0x80))
  289. r = -1;
  290. grub_memcpy (&r, run, nn);
  291. return grub_le_to_cpu64 (r);
  292. }
  293. grub_err_t
  294. grub_ntfs_read_run_list (struct grub_ntfs_rlst * ctx)
  295. {
  296. grub_uint8_t c1, c2;
  297. grub_disk_addr_t val;
  298. grub_uint8_t *run;
  299. run = ctx->cur_run;
  300. retry:
  301. c1 = ((*run) & 0x7);
  302. c2 = ((*run) >> 4) & 0x7;
  303. run++;
  304. if (!c1)
  305. {
  306. if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST))
  307. {
  308. grub_disk_read_hook_t save_hook;
  309. save_hook = ctx->comp.disk->read_hook;
  310. ctx->comp.disk->read_hook = 0;
  311. run = find_attr (ctx->attr, *ctx->attr->attr_cur);
  312. ctx->comp.disk->read_hook = save_hook;
  313. if (run)
  314. {
  315. if (run[8] == 0)
  316. return grub_error (GRUB_ERR_BAD_FS,
  317. "$DATA should be non-resident");
  318. run += u16at (run, 0x20);
  319. ctx->curr_lcn = 0;
  320. goto retry;
  321. }
  322. }
  323. return grub_error (GRUB_ERR_BAD_FS, "run list overflown");
  324. }
  325. ctx->curr_vcn = ctx->next_vcn;
  326. ctx->next_vcn += read_run_data (run, c1, 0); /* length of current VCN */
  327. run += c1;
  328. val = read_run_data (run, c2, 1); /* offset to previous LCN */
  329. run += c2;
  330. ctx->curr_lcn += val;
  331. if (val == 0)
  332. ctx->flags |= GRUB_NTFS_RF_BLNK;
  333. else
  334. ctx->flags &= ~GRUB_NTFS_RF_BLNK;
  335. ctx->cur_run = run;
  336. return 0;
  337. }
  338. static grub_disk_addr_t
  339. grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block)
  340. {
  341. struct grub_ntfs_rlst *ctx;
  342. ctx = (struct grub_ntfs_rlst *) node;
  343. if (block >= ctx->next_vcn)
  344. {
  345. if (grub_ntfs_read_run_list (ctx))
  346. return -1;
  347. return ctx->curr_lcn;
  348. }
  349. else
  350. return (ctx->flags & GRUB_NTFS_RF_BLNK) ? 0 : (block -
  351. ctx->curr_vcn + ctx->curr_lcn);
  352. }
  353. static grub_err_t
  354. read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
  355. grub_disk_addr_t ofs, grub_size_t len, int cached,
  356. grub_disk_read_hook_t read_hook, void *read_hook_data)
  357. {
  358. struct grub_ntfs_rlst cc, *ctx;
  359. if (len == 0)
  360. return 0;
  361. grub_memset (&cc, 0, sizeof (cc));
  362. ctx = &cc;
  363. ctx->attr = at;
  364. ctx->comp.log_spc = at->mft->data->log_spc;
  365. ctx->comp.disk = at->mft->data->disk;
  366. if (read_hook == grub_file_progress_hook)
  367. ctx->file = read_hook_data;
  368. if (pa[8] == 0)
  369. {
  370. if (ofs + len > res_attr_data_len (pa))
  371. return grub_error (GRUB_ERR_BAD_FS, "read out of range");
  372. if (res_attr_data_len (pa) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
  373. return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
  374. if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
  375. return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
  376. if (res_attr_data_off (pa) + res_attr_data_len (pa) >
  377. (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
  378. return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
  379. grub_memcpy (dest, pa + res_attr_data_off (pa) + ofs, len);
  380. return 0;
  381. }
  382. ctx->cur_run = pa + u16at (pa, 0x20);
  383. ctx->next_vcn = u32at (pa, 0x10);
  384. ctx->curr_lcn = 0;
  385. if ((pa[0xC] & GRUB_NTFS_FLAG_COMPRESSED)
  386. && !(at->flags & GRUB_NTFS_AF_GPOS))
  387. {
  388. if (!cached)
  389. return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed");
  390. return (grub_ntfscomp_func) ? grub_ntfscomp_func (dest, ofs, len, ctx)
  391. : grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"),
  392. "ntfscomp");
  393. }
  394. ctx->target_vcn = ofs >> (GRUB_NTFS_BLK_SHR + ctx->comp.log_spc);
  395. while (ctx->next_vcn <= ctx->target_vcn)
  396. {
  397. if (grub_ntfs_read_run_list (ctx))
  398. return grub_errno;
  399. }
  400. if (at->flags & GRUB_NTFS_AF_GPOS)
  401. {
  402. grub_disk_addr_t st0, st1;
  403. grub_uint64_t m;
  404. m = (ofs >> GRUB_NTFS_BLK_SHR) & ((1 << ctx->comp.log_spc) - 1);
  405. st0 =
  406. ((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) + m;
  407. st1 = st0 + 1;
  408. if (st1 ==
  409. (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc)
  410. {
  411. if (grub_ntfs_read_run_list (ctx))
  412. return grub_errno;
  413. st1 = ctx->curr_lcn << ctx->comp.log_spc;
  414. }
  415. grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0));
  416. grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1));
  417. return 0;
  418. }
  419. grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx,
  420. read_hook, read_hook_data, ofs, len,
  421. (char *) dest,
  422. grub_ntfs_read_block, ofs + len,
  423. ctx->comp.log_spc, 0);
  424. return grub_errno;
  425. }
  426. static grub_err_t
  427. read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
  428. grub_size_t len, int cached,
  429. grub_disk_read_hook_t read_hook, void *read_hook_data)
  430. {
  431. grub_uint8_t *save_cur;
  432. grub_uint8_t attr;
  433. grub_uint8_t *pp;
  434. grub_err_t ret;
  435. save_cur = at->attr_cur;
  436. at->attr_nxt = at->attr_cur;
  437. attr = *at->attr_nxt;
  438. if (at->flags & GRUB_NTFS_AF_ALST)
  439. {
  440. grub_uint8_t *pa;
  441. grub_disk_addr_t vcn;
  442. /* If compression is possible make sure that we include possible
  443. compressed block size. */
  444. if (GRUB_NTFS_LOG_COM_SEC >= at->mft->data->log_spc)
  445. vcn = ((ofs >> GRUB_NTFS_COM_LOG_LEN)
  446. << (GRUB_NTFS_LOG_COM_SEC - at->mft->data->log_spc)) & ~0xFULL;
  447. else
  448. vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR);
  449. pa = at->attr_nxt + u16at (at->attr_nxt, 4);
  450. while (pa < at->attr_end)
  451. {
  452. if (*pa != attr)
  453. break;
  454. if (u32at (pa, 8) > vcn)
  455. break;
  456. at->attr_nxt = pa;
  457. pa += u16at (pa, 4);
  458. }
  459. }
  460. pp = find_attr (at, attr);
  461. if (pp)
  462. ret = read_data (at, pp, dest, ofs, len, cached,
  463. read_hook, read_hook_data);
  464. else
  465. ret =
  466. (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS,
  467. "attribute not found");
  468. at->attr_cur = save_cur;
  469. return ret;
  470. }
  471. static grub_err_t
  472. read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, grub_uint64_t mftno)
  473. {
  474. if (read_attr
  475. (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR),
  476. data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
  477. return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%llx fails", (unsigned long long) mftno);
  478. return fixup (buf, data->mft_size, (const grub_uint8_t *) "FILE");
  479. }
  480. static grub_err_t
  481. init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
  482. {
  483. unsigned short flag;
  484. mft->inode_read = 1;
  485. mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
  486. if (mft->buf == NULL)
  487. return grub_errno;
  488. if (read_mft (mft->data, mft->buf, mftno))
  489. return grub_errno;
  490. flag = u16at (mft->buf, 0x16);
  491. if ((flag & 1) == 0)
  492. return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%llx is not in use",
  493. (unsigned long long) mftno);
  494. if ((flag & 2) == 0)
  495. {
  496. grub_uint8_t *pa;
  497. pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_DATA);
  498. if (pa == NULL)
  499. return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%llx",
  500. (unsigned long long) mftno);
  501. if (!pa[8])
  502. mft->size = res_attr_data_len (pa);
  503. else
  504. mft->size = u64at (pa, 0x30);
  505. if ((mft->attr.flags & GRUB_NTFS_AF_ALST) == 0)
  506. mft->attr.attr_end = 0; /* Don't jump to attribute list */
  507. }
  508. else
  509. init_attr (&mft->attr, mft);
  510. return 0;
  511. }
  512. static void
  513. free_file (struct grub_ntfs_file *mft)
  514. {
  515. free_attr (&mft->attr);
  516. grub_free (mft->buf);
  517. }
  518. static char *
  519. get_utf8 (grub_uint8_t *in, grub_size_t len)
  520. {
  521. grub_uint8_t *buf;
  522. grub_uint16_t *tmp;
  523. grub_size_t i;
  524. buf = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1);
  525. tmp = grub_calloc (len, sizeof (tmp[0]));
  526. if (!buf || !tmp)
  527. {
  528. grub_free (buf);
  529. grub_free (tmp);
  530. return NULL;
  531. }
  532. for (i = 0; i < len; i++)
  533. tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (in + 2 * i));
  534. *grub_utf16_to_utf8 (buf, tmp, len) = '\0';
  535. grub_free (tmp);
  536. return (char *) buf;
  537. }
  538. static int
  539. list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos,
  540. grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
  541. {
  542. grub_uint8_t *np;
  543. int ns;
  544. while (1)
  545. {
  546. grub_uint8_t namespace;
  547. char *ustr;
  548. if ((pos >= end_pos) || (end_pos - pos < 0x52))
  549. break;
  550. if (pos[0xC] & 2) /* end signature */
  551. break;
  552. np = pos + 0x50;
  553. ns = *(np++);
  554. namespace = *(np++);
  555. if (2 * ns > end_pos - pos - 0x52)
  556. break;
  557. /*
  558. * Ignore files in DOS namespace, as they will reappear as Win32
  559. * names.
  560. */
  561. if ((ns) && (namespace != 2))
  562. {
  563. enum grub_fshelp_filetype type;
  564. struct grub_ntfs_file *fdiro;
  565. grub_uint32_t attr;
  566. attr = u32at (pos, 0x48);
  567. if (attr & GRUB_NTFS_ATTR_REPARSE)
  568. type = GRUB_FSHELP_SYMLINK;
  569. else if (attr & GRUB_NTFS_ATTR_DIRECTORY)
  570. type = GRUB_FSHELP_DIR;
  571. else
  572. type = GRUB_FSHELP_REG;
  573. fdiro = grub_zalloc (sizeof (struct grub_ntfs_file));
  574. if (!fdiro)
  575. return 0;
  576. fdiro->data = diro->data;
  577. fdiro->ino = u64at (pos, 0) & 0xffffffffffffULL;
  578. fdiro->mtime = u64at (pos, 0x20);
  579. ustr = get_utf8 (np, ns);
  580. if (ustr == NULL)
  581. {
  582. grub_free (fdiro);
  583. return 0;
  584. }
  585. if (namespace)
  586. type |= GRUB_FSHELP_CASE_INSENSITIVE;
  587. if (hook (ustr, type, fdiro, hook_data))
  588. {
  589. grub_free (ustr);
  590. return 1;
  591. }
  592. grub_free (ustr);
  593. }
  594. pos += u16at (pos, 8);
  595. }
  596. return 0;
  597. }
  598. struct symlink_descriptor
  599. {
  600. grub_uint32_t type;
  601. grub_uint32_t total_len;
  602. grub_uint16_t off1;
  603. grub_uint16_t len1;
  604. grub_uint16_t off2;
  605. grub_uint16_t len2;
  606. } GRUB_PACKED;
  607. static char *
  608. grub_ntfs_read_symlink (grub_fshelp_node_t node)
  609. {
  610. struct grub_ntfs_file *mft;
  611. struct symlink_descriptor symdesc;
  612. grub_err_t err;
  613. grub_uint8_t *buf16 = NULL;
  614. char *buf, *end;
  615. grub_size_t len;
  616. grub_uint8_t *pa;
  617. grub_size_t off;
  618. mft = (struct grub_ntfs_file *) node;
  619. mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
  620. if (mft->buf == NULL)
  621. return NULL;
  622. if (read_mft (mft->data, mft->buf, mft->ino))
  623. goto fail;
  624. pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_SYMLINK);
  625. if (pa == NULL)
  626. {
  627. grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%llx",
  628. (unsigned long long) mft->ino);
  629. goto fail;
  630. }
  631. err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0,
  632. sizeof (struct symlink_descriptor), 1, 0, 0);
  633. if (err)
  634. goto fail;
  635. switch (grub_cpu_to_le32 (symdesc.type))
  636. {
  637. case 0xa000000c:
  638. off = (sizeof (struct symlink_descriptor) + 4
  639. + grub_cpu_to_le32 (symdesc.off1));
  640. len = grub_cpu_to_le32 (symdesc.len1);
  641. break;
  642. case 0xa0000003:
  643. off = (sizeof (struct symlink_descriptor)
  644. + grub_cpu_to_le32 (symdesc.off1));
  645. len = grub_cpu_to_le32 (symdesc.len1);
  646. break;
  647. default:
  648. grub_error (GRUB_ERR_BAD_FS, "symlink type invalid (%x)",
  649. grub_cpu_to_le32 (symdesc.type));
  650. goto fail;
  651. }
  652. buf16 = grub_malloc (len);
  653. if (!buf16)
  654. goto fail;
  655. err = read_attr (&mft->attr, buf16, off, len, 1, 0, 0);
  656. if (err)
  657. goto fail;
  658. buf = get_utf8 (buf16, len / 2);
  659. if (!buf)
  660. goto fail;
  661. grub_free (mft->buf);
  662. grub_free (buf16);
  663. for (end = buf; *end; end++)
  664. if (*end == '\\')
  665. *end = '/';
  666. /* Split the sequence to avoid GCC thinking that this is a trigraph. */
  667. if (grub_memcmp (buf, "/?" "?/", 4) == 0 && buf[5] == ':' && buf[6] == '/'
  668. && grub_isalpha (buf[4]))
  669. {
  670. grub_memmove (buf, buf + 6, end - buf + 1 - 6);
  671. end -= 6;
  672. }
  673. return buf;
  674. fail:
  675. grub_free (mft->buf);
  676. grub_free (buf16);
  677. return NULL;
  678. }
  679. static int
  680. grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
  681. grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
  682. {
  683. grub_uint8_t *bitmap;
  684. struct grub_ntfs_attr attr, *at;
  685. grub_uint8_t *cur_pos, *indx, *bmp;
  686. int ret = 0;
  687. grub_size_t bitmap_len;
  688. struct grub_ntfs_file *mft;
  689. mft = (struct grub_ntfs_file *) dir;
  690. if (!mft->inode_read)
  691. {
  692. if (init_file (mft, mft->ino))
  693. return 0;
  694. }
  695. indx = NULL;
  696. bmp = NULL;
  697. at = &attr;
  698. init_attr (at, mft);
  699. while (1)
  700. {
  701. cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT);
  702. if (cur_pos == NULL)
  703. {
  704. grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT");
  705. goto done;
  706. }
  707. /* Resident, Namelen=4, Offset=0x18, Flags=0x00, Name="$I30" */
  708. if ((u32at (cur_pos, 8) != 0x180400) ||
  709. (u32at (cur_pos, 0x18) != 0x490024) ||
  710. (u32at (cur_pos, 0x1C) != 0x300033))
  711. continue;
  712. cur_pos += res_attr_data_off (cur_pos);
  713. if (*cur_pos != 0x30) /* Not filename index */
  714. continue;
  715. break;
  716. }
  717. cur_pos += 0x10; /* Skip index root */
  718. ret = list_file (mft, cur_pos + u16at (cur_pos, 0),
  719. at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
  720. hook, hook_data);
  721. if (ret)
  722. goto done;
  723. bitmap = NULL;
  724. bitmap_len = 0;
  725. free_attr (at);
  726. init_attr (at, mft);
  727. while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL)
  728. {
  729. int ofs;
  730. ofs = cur_pos[0xA];
  731. /* Namelen=4, Name="$I30" */
  732. if ((cur_pos[9] == 4) &&
  733. (u32at (cur_pos, ofs) == 0x490024) &&
  734. (u32at (cur_pos, ofs + 4) == 0x300033))
  735. {
  736. int is_resident = (cur_pos[8] == 0);
  737. bitmap_len = ((is_resident) ? res_attr_data_len (cur_pos) :
  738. u32at (cur_pos, 0x28));
  739. bmp = grub_malloc (bitmap_len);
  740. if (bmp == NULL)
  741. goto done;
  742. if (is_resident)
  743. {
  744. if (bitmap_len > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
  745. {
  746. grub_error (GRUB_ERR_BAD_FS, "resident bitmap too large");
  747. goto done;
  748. }
  749. if (cur_pos >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
  750. {
  751. grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
  752. goto done;
  753. }
  754. if (res_attr_data_off (cur_pos) + res_attr_data_len (cur_pos) >
  755. (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos)
  756. {
  757. grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
  758. goto done;
  759. }
  760. grub_memcpy (bmp, cur_pos + res_attr_data_off (cur_pos),
  761. bitmap_len);
  762. }
  763. else
  764. {
  765. if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0))
  766. {
  767. grub_error (GRUB_ERR_BAD_FS,
  768. "fails to read non-resident $BITMAP");
  769. goto done;
  770. }
  771. bitmap_len = u32at (cur_pos, 0x30);
  772. }
  773. bitmap = bmp;
  774. break;
  775. }
  776. }
  777. free_attr (at);
  778. cur_pos = locate_attr (at, mft, GRUB_NTFS_AT_INDEX_ALLOCATION);
  779. while (cur_pos != NULL)
  780. {
  781. /* Non-resident, Namelen=4, Offset=0x40, Flags=0, Name="$I30" */
  782. if ((u32at (cur_pos, 8) == 0x400401) &&
  783. (u32at (cur_pos, 0x40) == 0x490024) &&
  784. (u32at (cur_pos, 0x44) == 0x300033))
  785. break;
  786. cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ALLOCATION);
  787. }
  788. if ((!cur_pos) && (bitmap))
  789. {
  790. grub_error (GRUB_ERR_BAD_FS, "$BITMAP without $INDEX_ALLOCATION");
  791. goto done;
  792. }
  793. if (bitmap)
  794. {
  795. grub_disk_addr_t i;
  796. grub_uint8_t v;
  797. indx = grub_malloc (mft->data->idx_size << GRUB_NTFS_BLK_SHR);
  798. if (indx == NULL)
  799. goto done;
  800. v = 1;
  801. for (i = 0; i < (grub_disk_addr_t)bitmap_len * 8; i++)
  802. {
  803. if (*bitmap & v)
  804. {
  805. if ((read_attr
  806. (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
  807. (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0, 0))
  808. || (fixup (indx, mft->data->idx_size,
  809. (const grub_uint8_t *) "INDX")))
  810. goto done;
  811. ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)],
  812. indx + (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
  813. hook, hook_data);
  814. if (ret)
  815. goto done;
  816. }
  817. v <<= 1;
  818. if (!v)
  819. {
  820. v = 1;
  821. bitmap++;
  822. }
  823. }
  824. }
  825. done:
  826. free_attr (at);
  827. grub_free (indx);
  828. grub_free (bmp);
  829. return ret;
  830. }
  831. static struct grub_ntfs_data *
  832. grub_ntfs_mount (grub_disk_t disk)
  833. {
  834. struct grub_ntfs_bpb bpb;
  835. struct grub_ntfs_data *data = 0;
  836. grub_uint32_t spc;
  837. if (!disk)
  838. goto fail;
  839. data = (struct grub_ntfs_data *) grub_zalloc (sizeof (*data));
  840. if (!data)
  841. goto fail;
  842. data->disk = disk;
  843. /* Read the BPB. */
  844. if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
  845. goto fail;
  846. if (grub_memcmp ((char *) &bpb.oem_name, "NTFS", 4) != 0
  847. || bpb.sectors_per_cluster == 0
  848. || (bpb.sectors_per_cluster & (bpb.sectors_per_cluster - 1)) != 0
  849. || bpb.bytes_per_sector == 0
  850. || (bpb.bytes_per_sector & (bpb.bytes_per_sector - 1)) != 0)
  851. goto fail;
  852. spc = (((grub_uint32_t) bpb.sectors_per_cluster
  853. * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector))
  854. >> GRUB_NTFS_BLK_SHR);
  855. if (spc == 0)
  856. goto fail;
  857. for (data->log_spc = 0; (1U << data->log_spc) < spc; data->log_spc++);
  858. if (bpb.clusters_per_mft > 0)
  859. data->mft_size = ((grub_disk_addr_t) bpb.clusters_per_mft) << data->log_spc;
  860. else if (-bpb.clusters_per_mft < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_mft >= 31)
  861. goto fail;
  862. else
  863. data->mft_size = 1ULL << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR);
  864. if (bpb.clusters_per_index > 0)
  865. data->idx_size = (((grub_disk_addr_t) bpb.clusters_per_index)
  866. << data->log_spc);
  867. else if (-bpb.clusters_per_index < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_index >= 31)
  868. goto fail;
  869. else
  870. data->idx_size = 1ULL << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR);
  871. data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) << data->log_spc;
  872. if ((data->mft_size > GRUB_NTFS_MAX_MFT) || (data->idx_size > GRUB_NTFS_MAX_IDX))
  873. goto fail;
  874. data->mmft.data = data;
  875. data->cmft.data = data;
  876. data->mmft.buf = grub_malloc (data->mft_size << GRUB_NTFS_BLK_SHR);
  877. if (!data->mmft.buf)
  878. goto fail;
  879. if (grub_disk_read
  880. (disk, data->mft_start, 0, data->mft_size << GRUB_NTFS_BLK_SHR, data->mmft.buf))
  881. goto fail;
  882. data->uuid = grub_le_to_cpu64 (bpb.num_serial);
  883. if (fixup (data->mmft.buf, data->mft_size, (const grub_uint8_t *) "FILE"))
  884. goto fail;
  885. if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA))
  886. goto fail;
  887. if (init_file (&data->cmft, GRUB_NTFS_FILE_ROOT))
  888. goto fail;
  889. return data;
  890. fail:
  891. grub_error (GRUB_ERR_BAD_FS, "not an ntfs filesystem");
  892. if (data)
  893. {
  894. free_file (&data->mmft);
  895. free_file (&data->cmft);
  896. grub_free (data);
  897. }
  898. return 0;
  899. }
  900. /* Context for grub_ntfs_dir. */
  901. struct grub_ntfs_dir_ctx
  902. {
  903. grub_fs_dir_hook_t hook;
  904. void *hook_data;
  905. };
  906. /* Helper for grub_ntfs_dir. */
  907. static int
  908. grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
  909. grub_fshelp_node_t node, void *data)
  910. {
  911. struct grub_ntfs_dir_ctx *ctx = data;
  912. struct grub_dirhook_info info;
  913. grub_memset (&info, 0, sizeof (info));
  914. info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
  915. info.mtimeset = 1;
  916. info.mtime = grub_divmod64 (node->mtime, 10000000, 0)
  917. - 86400ULL * 365 * (1970 - 1601)
  918. - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
  919. grub_free (node);
  920. return ctx->hook (filename, &info, ctx->hook_data);
  921. }
  922. static grub_err_t
  923. grub_ntfs_dir (grub_device_t device, const char *path,
  924. grub_fs_dir_hook_t hook, void *hook_data)
  925. {
  926. struct grub_ntfs_dir_ctx ctx = { hook, hook_data };
  927. struct grub_ntfs_data *data = 0;
  928. struct grub_fshelp_node *fdiro = 0;
  929. grub_dl_ref (my_mod);
  930. data = grub_ntfs_mount (device->disk);
  931. if (!data)
  932. goto fail;
  933. grub_fshelp_find_file (path, &data->cmft, &fdiro, grub_ntfs_iterate_dir,
  934. grub_ntfs_read_symlink, GRUB_FSHELP_DIR);
  935. if (grub_errno)
  936. goto fail;
  937. grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx);
  938. fail:
  939. if ((fdiro) && (fdiro != &data->cmft))
  940. {
  941. free_file (fdiro);
  942. grub_free (fdiro);
  943. }
  944. if (data)
  945. {
  946. free_file (&data->mmft);
  947. free_file (&data->cmft);
  948. grub_free (data);
  949. }
  950. grub_dl_unref (my_mod);
  951. return grub_errno;
  952. }
  953. static grub_err_t
  954. grub_ntfs_open (grub_file_t file, const char *name)
  955. {
  956. struct grub_ntfs_data *data = 0;
  957. struct grub_fshelp_node *mft = 0;
  958. grub_dl_ref (my_mod);
  959. data = grub_ntfs_mount (file->device->disk);
  960. if (!data)
  961. goto fail;
  962. grub_fshelp_find_file (name, &data->cmft, &mft, grub_ntfs_iterate_dir,
  963. grub_ntfs_read_symlink, GRUB_FSHELP_REG);
  964. if (grub_errno)
  965. goto fail;
  966. if (mft != &data->cmft)
  967. {
  968. free_file (&data->cmft);
  969. grub_memcpy (&data->cmft, mft, sizeof (*mft));
  970. grub_free (mft);
  971. if (!data->cmft.inode_read)
  972. {
  973. if (init_file (&data->cmft, data->cmft.ino))
  974. goto fail;
  975. }
  976. }
  977. file->size = data->cmft.size;
  978. file->data = data;
  979. file->offset = 0;
  980. return 0;
  981. fail:
  982. if (data)
  983. {
  984. free_file (&data->mmft);
  985. free_file (&data->cmft);
  986. grub_free (data);
  987. }
  988. grub_dl_unref (my_mod);
  989. return grub_errno;
  990. }
  991. static grub_ssize_t
  992. grub_ntfs_read (grub_file_t file, char *buf, grub_size_t len)
  993. {
  994. struct grub_ntfs_file *mft;
  995. mft = &((struct grub_ntfs_data *) file->data)->cmft;
  996. if (file->read_hook)
  997. mft->attr.save_pos = 1;
  998. read_attr (&mft->attr, (grub_uint8_t *) buf, file->offset, len, 1,
  999. file->read_hook, file->read_hook_data);
  1000. return (grub_errno) ? -1 : (grub_ssize_t) len;
  1001. }
  1002. static grub_err_t
  1003. grub_ntfs_close (grub_file_t file)
  1004. {
  1005. struct grub_ntfs_data *data;
  1006. data = file->data;
  1007. if (data)
  1008. {
  1009. free_file (&data->mmft);
  1010. free_file (&data->cmft);
  1011. grub_free (data);
  1012. }
  1013. grub_dl_unref (my_mod);
  1014. return grub_errno;
  1015. }
  1016. static grub_err_t
  1017. grub_ntfs_label (grub_device_t device, char **label)
  1018. {
  1019. struct grub_ntfs_data *data = 0;
  1020. struct grub_fshelp_node *mft = 0;
  1021. grub_uint8_t *pa;
  1022. grub_dl_ref (my_mod);
  1023. *label = 0;
  1024. data = grub_ntfs_mount (device->disk);
  1025. if (!data)
  1026. goto fail;
  1027. grub_fshelp_find_file ("/$Volume", &data->cmft, &mft, grub_ntfs_iterate_dir,
  1028. 0, GRUB_FSHELP_REG);
  1029. if (grub_errno)
  1030. goto fail;
  1031. if (!mft->inode_read)
  1032. {
  1033. mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
  1034. if (mft->buf == NULL)
  1035. goto fail;
  1036. if (read_mft (mft->data, mft->buf, mft->ino))
  1037. goto fail;
  1038. }
  1039. init_attr (&mft->attr, mft);
  1040. pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
  1041. if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
  1042. {
  1043. grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
  1044. goto fail;
  1045. }
  1046. if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa < 0x16)
  1047. {
  1048. grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
  1049. goto fail;
  1050. }
  1051. if ((pa) && (pa[8] == 0) && (res_attr_data_len (pa)))
  1052. {
  1053. int len;
  1054. len = res_attr_data_len (pa) / 2;
  1055. pa += res_attr_data_off (pa);
  1056. if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
  1057. *label = get_utf8 (pa, len);
  1058. else
  1059. grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
  1060. }
  1061. fail:
  1062. if ((mft) && (mft != &data->cmft))
  1063. {
  1064. free_file (mft);
  1065. grub_free (mft);
  1066. }
  1067. if (data)
  1068. {
  1069. free_file (&data->mmft);
  1070. free_file (&data->cmft);
  1071. grub_free (data);
  1072. }
  1073. grub_dl_unref (my_mod);
  1074. return grub_errno;
  1075. }
  1076. static grub_err_t
  1077. grub_ntfs_uuid (grub_device_t device, char **uuid)
  1078. {
  1079. struct grub_ntfs_data *data;
  1080. grub_disk_t disk = device->disk;
  1081. grub_dl_ref (my_mod);
  1082. data = grub_ntfs_mount (disk);
  1083. if (data)
  1084. {
  1085. char *ptr;
  1086. *uuid = grub_xasprintf ("%016llx", (unsigned long long) data->uuid);
  1087. if (*uuid)
  1088. for (ptr = *uuid; *ptr; ptr++)
  1089. *ptr = grub_toupper (*ptr);
  1090. free_file (&data->mmft);
  1091. free_file (&data->cmft);
  1092. grub_free (data);
  1093. }
  1094. else
  1095. *uuid = NULL;
  1096. grub_dl_unref (my_mod);
  1097. return grub_errno;
  1098. }
  1099. static struct grub_fs grub_ntfs_fs =
  1100. {
  1101. .name = "ntfs",
  1102. .fs_dir = grub_ntfs_dir,
  1103. .fs_open = grub_ntfs_open,
  1104. .fs_read = grub_ntfs_read,
  1105. .fs_close = grub_ntfs_close,
  1106. .fs_label = grub_ntfs_label,
  1107. .fs_uuid = grub_ntfs_uuid,
  1108. #ifdef GRUB_UTIL
  1109. .reserved_first_sector = 1,
  1110. .blocklist_install = 1,
  1111. #endif
  1112. .next = 0
  1113. };
  1114. GRUB_MOD_INIT (ntfs)
  1115. {
  1116. grub_fs_register (&grub_ntfs_fs);
  1117. my_mod = mod;
  1118. }
  1119. GRUB_MOD_FINI (ntfs)
  1120. {
  1121. grub_fs_unregister (&grub_ntfs_fs);
  1122. }