dir.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:30k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * dir.c
  3.  *
  4.  * Copyright (C) 1995-1997, 1999 Martin von L鰓is
  5.  * Copyright (C) 1999 Steve Dodd
  6.  * Copyright (C) 1999 Joseph Malicki
  7.  * Copyright (C) 2001 Anton Altaparmakov (AIA)
  8.  */
  9. #include "ntfstypes.h"
  10. #include "struct.h"
  11. #include "dir.h"
  12. #include "macros.h"
  13. #include <linux/errno.h>
  14. #include "super.h"
  15. #include "inode.h"
  16. #include "attr.h"
  17. #include "support.h"
  18. #include "util.h"
  19. #include <linux/smp_lock.h>
  20. #include <linux/bitops.h>
  21. static char I30[] = "$I30";
  22. /* An index record should start with INDX, and the last word in each block
  23.  * should contain the check value. If it passes, the original values need to
  24.  * be restored. */
  25. int ntfs_check_index_record(ntfs_inode *ino, char *record)
  26. {
  27. return ntfs_fixup_record(record, "INDX", ino->u.index.recordsize);
  28. }
  29. static inline int ntfs_is_top(ntfs_u64 stack)
  30. {
  31. return stack == 14;
  32. }
  33. static int ntfs_pop(ntfs_u64 *stack)
  34. {
  35. static int width[16] = {1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,-1};
  36. int res = -1;
  37. switch (width[*stack & 15]) {
  38. case 1:
  39. res = (int)((*stack & 15) >> 1);
  40. *stack >>= 4;
  41. break;
  42. case 2:
  43. res = (int)(((*stack & 63) >> 2) + 7);
  44. *stack >>= 6;
  45. break;
  46. case 3:
  47. res = (int)(((*stack & 255) >> 3) + 23);
  48. *stack >>= 8;
  49. break;
  50. case 4:
  51. res = (int)(((*stack & 1023) >> 4) + 55);
  52. *stack >>= 10;
  53. break;
  54. default:
  55. ntfs_error("Unknown encodingn");
  56. }
  57. return res;
  58. }
  59. static inline unsigned int ntfs_top(void)
  60. {
  61. return 14;
  62. }
  63. static ntfs_u64 ntfs_push(ntfs_u64 stack, int i)
  64. {
  65. if (i < 7)
  66. return (stack << 4) | (i << 1);
  67. if (i < 23)
  68. return (stack << 6) | ((i - 7) << 2) | 1;
  69. if (i < 55)
  70. return (stack << 8) | ((i - 23) << 3) | 3;
  71. if (i < 120)
  72. return (stack << 10) | ((i - 55) << 4) | 7;
  73. ntfs_error("Too many entriesn");
  74. return ~((ntfs_u64)0);
  75. }
  76. #if 0
  77. static void ntfs_display_stack(ntfs_u64 stack)
  78. {
  79. while(!ntfs_is_top(stack))
  80. {
  81. printf("%d ", ntfs_pop(&stack));
  82. }
  83. printf("n");
  84. }
  85. #endif
  86. /* True if the entry points to another block of entries. */
  87. static inline int ntfs_entry_has_subnodes(char *entry)
  88. {
  89. return (NTFS_GETU16(entry + 0xc) & 1);
  90. }
  91. /* True if it is not the 'end of dir' entry. */
  92. static inline int ntfs_entry_is_used(char *entry)
  93. {
  94. return !(NTFS_GETU16(entry + 0xc) & 2);
  95. }
  96. /*
  97.  * Removed RACE for allocating index blocks. But stil not too happy.
  98.  * There might be more races afterwards. (AIA)
  99.  */
  100. static int ntfs_allocate_index_block(ntfs_iterate_s *walk)
  101. {
  102. ntfs_attribute *allocation, *bitmap = 0;
  103. int error, size, i, bit;
  104. ntfs_u8 *bmap;
  105. ntfs_io io;
  106. ntfs_volume *vol = walk->dir->vol;
  107. /* Check for allocation attribute. */
  108. allocation = ntfs_find_attr(walk->dir, vol->at_index_allocation, I30);
  109. if (!allocation) {
  110. ntfs_u8 bmp[8];
  111. /* Create index allocation attribute. */
  112. error = ntfs_create_attr(walk->dir, vol->at_index_allocation,
  113.  I30, 0, 0, &allocation);
  114. if (error)
  115. goto err_ret;
  116. ntfs_bzero(bmp, sizeof(bmp));
  117. error = ntfs_create_attr(walk->dir, vol->at_bitmap, I30, bmp,
  118.  sizeof(bmp), &bitmap);
  119. if (error)
  120. goto err_ret;
  121. } else
  122. bitmap = ntfs_find_attr(walk->dir, vol->at_bitmap, I30);
  123. if (!bitmap) {
  124. ntfs_error("Directory w/o bitmapn");
  125. error = -EINVAL;
  126. goto err_ret;
  127. }
  128. size = bitmap->size;
  129. bmap = ntfs_malloc(size);
  130. if (!bmap) {
  131. error = -ENOMEM;
  132. goto err_ret;
  133. }
  134. io.fn_put = ntfs_put;
  135. io.fn_get = ntfs_get;
  136. try_again:
  137. io.param = bmap;
  138. io.size = size;
  139. error = ntfs_read_attr(walk->dir, vol->at_bitmap, I30, 0, &io);
  140. if (error || (io.size != size && (error = -EIO, 1)))
  141. goto err_fb_out;
  142. /* Allocate a bit. */
  143. for (bit = i = 0; i < size; i++) {
  144. if (bmap[i] == 0xFF)
  145. continue;
  146. bit = ffz(bmap[i]);
  147. if (bit < 8)
  148. break;
  149. }
  150. if (i >= size) {
  151. /* FIXME: Extend bitmap. */
  152. error = -EOPNOTSUPP;
  153. goto err_fb_out;
  154. }
  155. /* Get the byte containing our bit again, now taking the BKL. */
  156. io.param = bmap;
  157. io.size = 1;
  158. lock_kernel();
  159. error = ntfs_read_attr(walk->dir, vol->at_bitmap, I30, i, &io);
  160. if (error || (io.size != 1 && (error = -EIO, 1)))
  161. goto err_unl_out;
  162. if (ntfs_test_and_set_bit(bmap, bit)) {
  163. unlock_kernel();
  164. /* Give other process(es) a chance to finish. */
  165. schedule();
  166. goto try_again;
  167. }
  168. walk->newblock = (i * 8 + bit) * walk->dir->u.index.clusters_per_record;
  169. io.param = bmap;
  170. error = ntfs_write_attr(walk->dir, vol->at_bitmap, I30, i, &io);
  171. if (error || (io.size != size && (error = -EIO, 1)))
  172. goto err_unl_out;
  173. /* Change inode on disk, required when bitmap is resident. */
  174. error = ntfs_update_inode(walk->dir);
  175. if (error)
  176. goto err_unl_out;
  177. unlock_kernel();
  178. ntfs_free(bmap);
  179. /* Check whether record is out of allocated range. */
  180. size = allocation->size;
  181. if (walk->newblock * vol->cluster_size >= size) {
  182. /* Build index record. */
  183. int hsize;
  184. int s1 = walk->dir->u.index.recordsize;
  185. int nr_fix = (s1 >> vol->sector_size) + 1;
  186. char *record = ntfs_malloc(s1);
  187. if (!record) {
  188. error = -ENOMEM;
  189. goto err_ret;
  190. }
  191. ntfs_bzero(record, s1);
  192. /* Magic */
  193. ntfs_memcpy(record, "INDX", 4);
  194. /* Offset to fixups */
  195. NTFS_PUTU16(record + 4, 0x28);
  196. /* Number of fixups. */
  197. NTFS_PUTU16(record + 6, nr_fix);
  198. /* Log file sequence number - We don't do journalling so we
  199.  * just set it to zero which should be the Right Thing. (AIA) */
  200. NTFS_PUTU64(record + 8, 0);
  201. /* VCN of buffer */
  202. NTFS_PUTU64(record + 0x10, walk->newblock);
  203. /* Header size. */
  204. hsize = 0x10 + 2 * nr_fix;
  205. hsize = (hsize + 7) & ~7; /* Align. */
  206. NTFS_PUTU16(record + 0x18, hsize);
  207. /* Total size of record. */
  208. NTFS_PUTU32(record + 0x20, s1 - 0x18);
  209. /* Writing the data will extend the attribute. */
  210. io.param = record;
  211. io.size = s1;
  212. io.do_read = 0;
  213. error = ntfs_readwrite_attr(walk->dir, allocation, size, &io);
  214. ntfs_free(record);
  215. if (error || (io.size != s1 && (error = -EIO, 1)))
  216. goto err_ret;
  217. error = ntfs_update_inode(walk->dir);
  218. if (error)
  219. goto err_ret;
  220. }
  221. return 0;
  222. err_unl_out:
  223. unlock_kernel();
  224. err_fb_out:
  225. ntfs_free(bmap);
  226. err_ret:
  227. return error;
  228. }
  229. /* Write an index block (root or allocation) back to storage.
  230.  * Used is the total number of bytes in buf, including all headers. */
  231. static int ntfs_index_writeback(ntfs_iterate_s *walk, ntfs_u8 *buf, int block,
  232. int used)
  233. {
  234. ntfs_io io;
  235. int error;
  236. ntfs_attribute *a;
  237. ntfs_volume *vol = walk->dir->vol;
  238. io.fn_put = 0;
  239. io.fn_get = ntfs_get;
  240. io.param = buf;
  241. if (block == -1) { /* Index root. */
  242. NTFS_PUTU16(buf + 0x14, used - 0x10);
  243. /* 0x18 is a copy thereof. */
  244. NTFS_PUTU16(buf + 0x18, used - 0x10);
  245. io.size = used;
  246. error = ntfs_write_attr(walk->dir, vol->at_index_root, I30, 0,
  247. &io);
  248. if (error || (io.size != used && (error = -EIO, 1)))
  249. return error;
  250. /* Shrink if necessary. */
  251. a = ntfs_find_attr(walk->dir, vol->at_index_root, I30);
  252. ntfs_resize_attr(walk->dir, a, used);
  253. } else {
  254. NTFS_PUTU16(buf + 0x1C, used - 0x18);
  255. io.size = walk->dir->u.index.recordsize;
  256. error = ntfs_insert_fixups(buf, io.size);
  257. if (error) {
  258. printk(KERN_ALERT "NTFS: ntfs_index_writeback() caught "
  259. "corrupt index record ntfs record "
  260. "header. Refusing to write corrupt "
  261. "data to disk. Unmount and run chkdsk "
  262. "immediately!n");
  263. return -EIO;
  264. }
  265. error = ntfs_write_attr(walk->dir, vol->at_index_allocation,
  266. I30, (__s64)block << vol->cluster_size_bits,
  267. &io);
  268. if (error || (io.size != walk->dir->u.index.recordsize &&
  269. (error = -EIO, 1)))
  270. return error;
  271. }
  272. return 0;
  273. }
  274. static int ntfs_split_record(ntfs_iterate_s *walk, char *start, int bsize,
  275.      int usize)
  276. {
  277. char *entry, *prev;
  278. ntfs_u8 *newbuf = 0, *middle = 0;
  279. int error, othersize, mlen;
  280. ntfs_io io;
  281. ntfs_volume *vol = walk->dir->vol;
  282. int oldblock;
  283. error = ntfs_allocate_index_block(walk);
  284. if (error)
  285. return error;
  286. /* This should not happen. */
  287. if (walk->block == -1) {
  288. ntfs_error("Trying to split root");
  289. return -EOPNOTSUPP;
  290. }
  291. entry = start + NTFS_GETU16(start + 0x18) + 0x18; 
  292. for (prev = entry; entry - start < usize / 2; 
  293.        entry += NTFS_GETU16(entry + 8))
  294. prev = entry;
  295. newbuf = ntfs_malloc(vol->index_record_size);
  296. if (!newbuf)
  297. return -ENOMEM;
  298. io.fn_put = ntfs_put;
  299. io.fn_get = ntfs_get;
  300. io.param = newbuf;
  301. io.size = vol->index_record_size;
  302. /* Read in old header. FIXME: Reading everything is overkill. */
  303. error = ntfs_read_attr(walk->dir, vol->at_index_allocation, I30,
  304. (__s64)walk->newblock << vol->cluster_size_bits, &io);
  305. if (error)
  306. goto out;
  307. if (io.size != vol->index_record_size) {
  308. error = -EIO;
  309. goto out;
  310. }
  311. /* FIXME: Adjust header. */
  312. /* Copy everything from entry to new block. */
  313. othersize = usize - (entry - start);
  314. ntfs_memcpy(newbuf + NTFS_GETU16(newbuf + 0x18) + 0x18, entry,
  315.     othersize);
  316. /* Copy flags. */
  317. NTFS_PUTU32(newbuf + 0x24, NTFS_GETU32(start + 0x24));
  318. error = ntfs_index_writeback(walk, newbuf, walk->newblock,
  319. othersize + NTFS_GETU16(newbuf + 0x18) + 0x18);
  320. if (error)
  321. goto out;
  322. /* Move prev to walk. */
  323. mlen = NTFS_GETU16(prev + 0x8);
  324. /* Remember old child node. */
  325. if (ntfs_entry_has_subnodes(prev))
  326. oldblock = NTFS_GETU32(prev + mlen - 8);
  327. else
  328. oldblock = -1;
  329. /* Allow for pointer to subnode. */
  330. middle = ntfs_malloc(ntfs_entry_has_subnodes(prev) ? mlen : mlen + 8);
  331. if (!middle){
  332. error = -ENOMEM;
  333. goto out;
  334. }
  335. ntfs_memcpy(middle, prev, mlen);
  336. /* Set has_subnodes flag. */
  337. NTFS_PUTU8(middle + 0xC, NTFS_GETU8(middle + 0xC) | 1);
  338. /* Middle entry points to block, parent entry will point to newblock. */
  339. NTFS_PUTU64(middle + mlen - 8, walk->block);
  340. if (walk->new_entry)
  341. ntfs_error("Entry not reset");
  342. walk->new_entry = middle;
  343. walk->u.flags |= ITERATE_SPLIT_DONE;
  344. /* Terminate old block. */
  345. othersize = usize - (prev-start);
  346. NTFS_PUTU64(prev, 0);
  347. if (oldblock == -1) {
  348. NTFS_PUTU32(prev + 8, 0x10);
  349. NTFS_PUTU32(prev + 0xC, 2);
  350. othersize += 0x10;
  351. } else {
  352. NTFS_PUTU32(prev + 8, 0x18);
  353. NTFS_PUTU32(prev + 0xC, 3);
  354. NTFS_PUTU64(prev + 0x10, oldblock);
  355. othersize += 0x18;
  356. }
  357. /* Write back original block. */
  358. error = ntfs_index_writeback(walk, start, walk->block, othersize);
  359.  out:
  360. if (newbuf)
  361. ntfs_free(newbuf);
  362. if (middle)
  363. ntfs_free(middle);
  364. return error;
  365. }
  366. static int ntfs_dir_insert(ntfs_iterate_s *walk, char *start, char* entry)
  367. {
  368. int blocksize, usedsize, error, offset;
  369. int do_split = 0;
  370. offset = entry - start;
  371. if (walk->block == -1) { /* index root */
  372. blocksize = walk->dir->vol->mft_record_size;
  373. usedsize = NTFS_GETU16(start + 0x14) + 0x10;
  374. } else {
  375. blocksize = walk->dir->u.index.recordsize;
  376. usedsize = NTFS_GETU16(start + 0x1C) + 0x18;
  377. }
  378. if (usedsize + walk->new_entry_size > blocksize) {
  379. char* s1 = ntfs_malloc(blocksize + walk->new_entry_size);
  380. if (!s1)
  381. return -ENOMEM;
  382. ntfs_memcpy(s1, start, usedsize);
  383. do_split = 1;
  384. /* Adjust entry to s1. */
  385. entry = s1 + (entry - start);
  386. start = s1;
  387. }
  388. ntfs_memmove(entry + walk->new_entry_size, entry, usedsize - offset);
  389. ntfs_memcpy(entry, walk->new_entry, walk->new_entry_size);
  390. usedsize += walk->new_entry_size;
  391. ntfs_free(walk->new_entry);
  392. walk->new_entry = 0;
  393. if (do_split) {
  394. error = ntfs_split_record(walk, start, blocksize, usedsize);
  395. ntfs_free(start);
  396. } else {
  397. error = ntfs_index_writeback(walk, start, walk->block,usedsize);
  398. if (error)
  399. return error;
  400. }
  401. return 0;
  402. }
  403. /* Try to split INDEX_ROOT attributes. Return -E2BIG if nothing changed. */
  404. int ntfs_split_indexroot(ntfs_inode *ino)
  405. {
  406. ntfs_attribute *ra;
  407. ntfs_u8 *root = 0, *index = 0;
  408. ntfs_io io;
  409. int error, off, i, bsize, isize;
  410. ntfs_iterate_s walk;
  411. ra = ntfs_find_attr(ino, ino->vol->at_index_root, I30);
  412. if (!ra)
  413. return -ENOTDIR;
  414. bsize = ino->vol->mft_record_size;
  415. root = ntfs_malloc(bsize);
  416. if (!root)
  417. return -E2BIG;
  418. io.fn_put = ntfs_put;
  419. io.param = root;
  420. io.size = bsize;
  421. error = ntfs_read_attr(ino, ino->vol->at_index_root, I30, 0, &io);
  422. if (error)
  423. goto out;
  424. off = 0x20;
  425. /* Count number of entries. */
  426. for (i = 0; ntfs_entry_is_used(root + off); i++)
  427. off += NTFS_GETU16(root + off + 8);
  428. if (i <= 2) {
  429. /* We don't split small index roots. */
  430. error = -E2BIG;
  431. goto out;
  432. }
  433. index = ntfs_malloc(ino->vol->index_record_size);
  434. if (!index) {
  435. error = -ENOMEM;
  436. goto out;
  437. }
  438. walk.dir = ino;
  439. walk.block = -1;
  440. walk.result = walk.new_entry = 0;
  441. walk.name = 0;
  442. error = ntfs_allocate_index_block(&walk);
  443. if (error)
  444. goto out;
  445. /* Write old root to new index block. */
  446. io.param = index;
  447. io.size = ino->vol->index_record_size;
  448. error = ntfs_read_attr(ino, ino->vol->at_index_allocation, I30,
  449. (__s64)walk.newblock << ino->vol->cluster_size_bits, &io);
  450. if (error)
  451. goto out;
  452. isize = NTFS_GETU16(root + 0x18) - 0x10;
  453. ntfs_memcpy(index + NTFS_GETU16(index + 0x18) + 0x18, root+0x20, isize);
  454. /* Copy flags. */
  455. NTFS_PUTU32(index + 0x24, NTFS_GETU32(root + 0x1C));
  456. error = ntfs_index_writeback(&walk, index, walk.newblock, 
  457.      isize + NTFS_GETU16(index + 0x18) + 0x18);
  458. if (error)
  459. goto out;
  460. /* Mark root as split. */
  461. NTFS_PUTU32(root + 0x1C, 1);
  462. /* Truncate index root. */
  463. NTFS_PUTU64(root + 0x20, 0);
  464. NTFS_PUTU32(root + 0x28, 0x18);
  465. NTFS_PUTU32(root + 0x2C, 3);
  466. NTFS_PUTU64(root + 0x30, walk.newblock);
  467. error = ntfs_index_writeback(&walk, root, -1, 0x38);
  468.  out:
  469. ntfs_free(root);
  470. ntfs_free(index);
  471. return error;
  472. }
  473. /* The entry has been found. Copy the result in the caller's buffer */
  474. static int ntfs_copyresult(char *dest, char *source)
  475. {
  476. int length = NTFS_GETU16(source + 8);
  477. ntfs_memcpy(dest, source, length);
  478. return 1;
  479. }
  480. /* Use $UpCase some day. */
  481. static inline unsigned short ntfs_my_toupper(ntfs_volume *vol, ntfs_u16 x)
  482. {
  483. /* We should read any pending rest of $UpCase here. */
  484. if (x >= vol->upcase_length)
  485. return x;
  486. return vol->upcase[x];
  487. }
  488. /* Everything passed in walk and entry. */
  489. static int ntfs_my_strcmp(ntfs_iterate_s *walk, const unsigned char *entry)
  490. {
  491. int lu = *(entry + 0x50);
  492. int i;
  493. ntfs_u16* name = (ntfs_u16*)(entry + 0x52);
  494. ntfs_volume *vol = walk->dir->vol;
  495. for (i = 0; i < lu && i < walk->namelen; i++)
  496. if (ntfs_my_toupper(vol, NTFS_GETU16(name + i)) != 
  497.      ntfs_my_toupper(vol, NTFS_GETU16(walk->name + i)))
  498. break;
  499. if (i == lu && i == walk->namelen)
  500. return 0;
  501. if (i == lu)
  502. return 1;
  503. if (i == walk->namelen)
  504. return -1;
  505. if (ntfs_my_toupper(vol, NTFS_GETU16(name + i)) < 
  506.     ntfs_my_toupper(vol, NTFS_GETU16(walk->name + i)))
  507. return 1;
  508. return -1;
  509. }
  510. /* Necessary forward declaration. */
  511. static int ntfs_getdir_iterate(ntfs_iterate_s *walk, char *start, char *entry);
  512. /* Parse a block of entries. Load the block, fix it up, and iterate over the
  513.  * entries. The block is given as virtual cluster number. */
  514. static int ntfs_getdir_record(ntfs_iterate_s *walk, int block)
  515. {
  516. int length = walk->dir->u.index.recordsize;
  517. char *record = (char*)ntfs_malloc(length);
  518. char *offset;
  519. int retval,error;
  520. int oldblock;
  521. ntfs_io io;
  522. if (!record)
  523. return -ENOMEM;
  524. io.fn_put = ntfs_put;
  525. io.param = record;
  526. io.size = length;
  527. /* Read the block from the index allocation attribute. */
  528. error = ntfs_read_attr(walk->dir, walk->dir->vol->at_index_allocation,
  529. I30, (__s64)block << walk->dir->vol->cluster_size_bits, &io);
  530. if (error || io.size != length) {
  531. ntfs_error("read failedn");
  532. ntfs_free(record);
  533. return 0;
  534. }
  535. if (!ntfs_check_index_record(walk->dir, record)) {
  536. ntfs_error("%x is not an index recordn", block);
  537. ntfs_free(record);
  538. return 0;
  539. }
  540. offset = record + NTFS_GETU16(record + 0x18) + 0x18;
  541. oldblock = walk->block;
  542. walk->block = block;
  543. retval = ntfs_getdir_iterate(walk, record, offset);
  544. walk->block = oldblock;
  545. ntfs_free(record);
  546. return retval;
  547. }
  548. /* Go down to the next block of entries. These collate before the current
  549.  * entry. */
  550. static int ntfs_descend(ntfs_iterate_s *walk, ntfs_u8 *start, ntfs_u8 *entry)
  551. {
  552. int length = NTFS_GETU16(entry + 8);
  553. int nextblock = NTFS_GETU32(entry + length - 8);
  554. int error;
  555. if (!ntfs_entry_has_subnodes(entry)) {
  556. ntfs_error("illegal ntfs_descend calln");
  557. return 0;
  558. }
  559. error = ntfs_getdir_record(walk, nextblock);
  560. if (!error && walk->type == DIR_INSERT && 
  561.     (walk->u.flags & ITERATE_SPLIT_DONE)) {
  562. /* Split has occurred. Adjust entry, insert new_entry. */
  563. NTFS_PUTU32(entry + length - 8, walk->newblock);
  564. /* Reset flags, as the current block might be split again. */
  565. walk->u.flags &= ~ITERATE_SPLIT_DONE;
  566. error = ntfs_dir_insert(walk, start, entry);
  567. }
  568. return error;
  569. }
  570. static int ntfs_getdir_iterate_byposition(ntfs_iterate_s *walk, char* start,
  571.   char *entry)
  572. {
  573. int retval = 0;
  574. int curpos = 0, destpos = 0;
  575. int length;
  576. if (walk->u.pos != 0) {
  577. if (ntfs_is_top(walk->u.pos))
  578. return 0;
  579. destpos = ntfs_pop(&walk->u.pos);
  580. }
  581. while (1) {
  582. if (walk->u.pos == 0) {
  583. if (ntfs_entry_has_subnodes(entry))
  584. ntfs_descend(walk, start, entry);
  585. else
  586. walk->u.pos = ntfs_top();
  587. if (ntfs_is_top(walk->u.pos) && 
  588.     !ntfs_entry_is_used(entry))
  589. return 1;
  590. walk->u.pos = ntfs_push(walk->u.pos, curpos);
  591. return 1;
  592. }
  593. if (curpos == destpos) {
  594. if (!ntfs_is_top(walk->u.pos) && 
  595.     ntfs_entry_has_subnodes(entry)) {
  596. retval = ntfs_descend(walk, start, entry);
  597. if (retval) {
  598. walk->u.pos = ntfs_push(walk->u.pos,
  599. curpos);
  600. return retval;
  601. }
  602. if (!ntfs_entry_is_used(entry))
  603. return 0;
  604. walk->u.pos = 0;
  605. }
  606. if (ntfs_entry_is_used(entry)) {
  607. retval = ntfs_copyresult(walk->result, entry);
  608. walk->u.pos = 0;
  609. } else {
  610. walk->u.pos = ntfs_top();
  611. return 0;
  612. }
  613. }
  614. curpos++;
  615. if (!ntfs_entry_is_used(entry))
  616. break;
  617. length = NTFS_GETU16(entry + 8);
  618. if (!length) {
  619. ntfs_error("infinite loopn");
  620. break;
  621. }
  622. entry += length;
  623. }
  624. return -1;
  625. }
  626. /* Iterate over a list of entries, either from an index block, or from the
  627.  * index root.
  628.  * If searching BY_POSITION, pop the top index from the position. If the
  629.  * position stack is empty then, return the item at the index and set the
  630.  * position to the next entry. If the position stack is not empty, 
  631.  * recursively proceed for subnodes. If the entry at the position is the
  632.  * 'end of dir' entry, return 'not found' and the empty stack.
  633.  * If searching BY_NAME, walk through the items until found or until
  634.  * one item is collated after the requested item. In the former case, return
  635.  * the result. In the latter case, recursively proceed to the subnodes.
  636.  * If 'end of dir' is reached, the name is not in the directory */
  637. static int ntfs_getdir_iterate(ntfs_iterate_s *walk, char *start, char *entry)
  638. {
  639. int length;
  640. int cmp;
  641. if (walk->type == BY_POSITION)
  642. return ntfs_getdir_iterate_byposition(walk, start, entry);
  643. do {
  644. /* If the current entry is a real one, compare with the
  645.  * requested item. If the current entry is the last item, it
  646.  * is always larger than the requested item. */
  647. cmp = ntfs_entry_is_used(entry) ? 
  648. ntfs_my_strcmp(walk,entry) : -1;
  649. switch (walk->type) {
  650. case BY_NAME:
  651. switch (cmp) {
  652. case -1:
  653. return ntfs_entry_has_subnodes(entry) ?
  654. ntfs_descend(walk, start, entry) : 0;
  655. case  0:
  656. return ntfs_copyresult(walk->result, entry);
  657. case  1:
  658. break;
  659. }
  660. break;
  661. case DIR_INSERT:
  662. switch (cmp) {
  663. case -1:
  664. return ntfs_entry_has_subnodes(entry) ?
  665. ntfs_descend(walk, start, entry) :
  666. ntfs_dir_insert(walk, start, entry);
  667. case  0:
  668. return -EEXIST;
  669. case  1:
  670. break;
  671. }
  672. break;
  673. default:
  674. ntfs_error("TODOn"); /* FIXME: ? */
  675. }
  676. if (!ntfs_entry_is_used(entry))
  677. break;
  678. length = NTFS_GETU16(entry + 8);
  679. if (!length) {
  680. ntfs_error("infinite loopn");
  681. break;
  682. }
  683. entry += length;
  684. } while (1);
  685. return 0;
  686. }
  687. /*  Tree walking is done using position numbers. The following numbers have a
  688.  *  special meaning:
  689.  *       0   start (.)
  690.  *      -1   no more entries
  691.  *      -2   ..
  692.  *  All other numbers encode sequences of indices. The sequence a, b, c is 
  693.  *  encoded as <stop><c><b><a>, where <foo> is the encoding of foo. The
  694.  *  first few integers are encoded as follows:
  695.  *      0:    0000    1:    0010    2:    0100    3:    0110
  696.  *      4:    1000    5:    1010    6:    1100 stop:    1110
  697.  *      7:  000001    8:  000101    9:  001001   10:  001101
  698.  *  The least significant bits give the width of this encoding, the other bits
  699.  *  encode the value, starting from the first value of the interval.
  700.  *   tag     width  first value  last value
  701.  *   0       3      0            6
  702.  *   01      4      7            22
  703.  *   011     5      23           54
  704.  *   0111    6      55           119
  705.  *   More values are hopefully not needed, as the file position has currently
  706.  *   64 bits in total. */
  707. /* Find an entry in the directory. Return 0 if not found, otherwise copy the
  708.  * entry to the result buffer. */
  709. int ntfs_getdir(ntfs_iterate_s *walk)
  710. {
  711. int length = walk->dir->vol->mft_record_size;
  712. int retval, error;
  713. /* Start at the index root. */
  714. char *root = ntfs_malloc(length);
  715. ntfs_io io;
  716. if (!root)
  717. return -ENOMEM;
  718. io.fn_put = ntfs_put;
  719. io.param = root;
  720. io.size = length;
  721. error = ntfs_read_attr(walk->dir, walk->dir->vol->at_index_root, I30,
  722.        0, &io);
  723. if (error) {
  724. ntfs_error("Not a directoryn");
  725. return 0;
  726. }
  727. walk->block = -1;
  728. /* FIXME: Move these to walk. */
  729. walk->dir->u.index.recordsize = NTFS_GETU32(root + 0x8);
  730. walk->dir->u.index.clusters_per_record = NTFS_GETU32(root + 0xC);
  731. /* FIXME: Consistency check. */
  732. /* Skip header. */
  733. retval = ntfs_getdir_iterate(walk, root, root + 0x20);
  734. ntfs_free(root);
  735. return retval;
  736. }
  737. /* Find an entry in the directory by its position stack. Iteration starts
  738.  * if the stack is 0, in which case the position is set to the first item
  739.  * in the directory. If the position is nonzero, return the item at the
  740.  * position and change the position to the next item. The position is -1
  741.  * if there are no more items. */
  742. int ntfs_getdir_byposition(ntfs_iterate_s *walk)
  743. {
  744. walk->type = BY_POSITION;
  745. return ntfs_getdir(walk);
  746. }
  747. /* Find an entry in the directory by its name. Return 0 if not found. */
  748. int ntfs_getdir_byname(ntfs_iterate_s *walk)
  749. {
  750. walk->type = BY_NAME;
  751. return ntfs_getdir(walk);
  752. }
  753. int ntfs_getdir_unsorted(ntfs_inode *ino, u32 *p_high, u32 *p_low,
  754. int (*cb)(ntfs_u8 *, void *), void *param)
  755. {
  756. s64 ib_ofs;
  757. char *buf = 0, *entry = 0;
  758. ntfs_attribute *attr;
  759. ntfs_volume *vol;
  760. int byte, bit, err = 0;
  761. u32 start, finish, ibs, max_size;
  762. ntfs_io io;
  763. u8 ibs_bits;
  764. if (!ino) {
  765. ntfs_error(__FUNCTION__ "(): No inode! Returning -EINVAL.n");
  766. return -EINVAL;
  767. }
  768. vol = ino->vol;
  769. if (!vol) {
  770. ntfs_error(__FUNCTION__ "(): Inode 0x%lx has no volume. "
  771. "Returning -EINVAL.n", ino->i_number);
  772. return -EINVAL;
  773. }
  774. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 1: Entering for "
  775. "inode 0x%lx, p_high = 0x%x, p_low = 0x%x.n",
  776. ino->i_number, *p_high, *p_low);
  777. if (!*p_high) {
  778. /* We are still in the index root. */
  779. buf = ntfs_malloc(io.size = vol->mft_record_size);
  780. if (!buf)
  781. return -ENOMEM;
  782. io.fn_put = ntfs_put;
  783. io.param = buf;
  784. err = ntfs_read_attr(ino, vol->at_index_root, I30, 0, &io);
  785. if (err || !io.size)
  786. goto read_err_ret;
  787. ino->u.index.recordsize = ibs = NTFS_GETU32(buf + 0x8);
  788. ino->u.index.clusters_per_record = NTFS_GETU32(buf + 0xC);
  789. entry = buf + 0x20;
  790. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 2: In index "
  791. "root.n");
  792. ibs_bits = ffs(ibs) - 1;
  793. /* Compensate for faked "." and "..". */
  794. start = 2;
  795. } else { /* We are in an index record. */
  796. io.size = ibs = ino->u.index.recordsize;
  797. buf = ntfs_malloc(ibs);
  798. if (!buf)
  799. return -ENOMEM;
  800. ibs_bits = ffs(ibs) - 1;
  801. io.fn_put = ntfs_put;
  802. io.param = buf;
  803. /*
  804.  * 0 is index root, index allocation starts at 1 and works in
  805.  * units of index block size (ibs).
  806.  */
  807. ib_ofs = (s64)(*p_high - 1) << ibs_bits;
  808. err = ntfs_read_attr(ino, vol->at_index_allocation, I30, ib_ofs,
  809. &io);
  810. if (err || io.size != ibs)
  811. goto read_err_ret;
  812. if (!ntfs_check_index_record(ino, buf)) {
  813. ntfs_error(__FUNCTION__ "(): Index block 0x%x is not "
  814. "an index record. Returning "
  815. "-ENOTDIR.n", *p_high - 1);
  816. ntfs_free(buf);
  817. return -ENOTDIR;
  818. }
  819. entry = buf + 0x18 + NTFS_GETU16(buf + 0x18);
  820. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 3: In index "
  821. "allocation.n");
  822. start = 0;
  823. }
  824. /* Process the entries. */
  825. finish = *p_low;
  826. for (; entry < (buf + ibs) && ntfs_entry_is_used(entry);
  827. entry += NTFS_GETU16(entry + 8)) {
  828. if (start < finish) {
  829. /* Skip entries that were already processed. */
  830. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 4: "
  831. "Skipping already processed entry "
  832. "p_high 0x%x, p_low 0x%x.n", *p_high,
  833. start);
  834. start++;
  835. continue;
  836. }
  837. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 5: "
  838. "Processing entry p_high 0x%x, p_low 0x%x.n",
  839. *p_high, *p_low);
  840. if ((err = cb(entry, param))) {
  841. /* filldir signalled us to stop. */
  842. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): "
  843. "Unsorted 6: cb returned %i, "
  844. "returning 0, p_high 0x%x, p_low 0x%x."
  845. "n", *p_high, *p_low);
  846. ntfs_free(buf);
  847. return 0;
  848. }
  849. ++*p_low;
  850. }
  851. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 7: After processing "
  852. "entries, p_high 0x%x, p_low 0x%x.n", *p_high, *p_low);
  853. /* We have to locate the next record. */
  854. ntfs_free(buf);
  855. buf = 0;
  856. *p_low = 0;
  857. attr = ntfs_find_attr(ino, vol->at_bitmap, I30);
  858. if (!attr) {
  859. /* Directory does not have index bitmap and index allocation. */
  860. *p_high = 0x7fff;
  861. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 8: No index "
  862. "allocation. Returning 0, p_high 0x7fff, "
  863. "p_low 0x0.n");
  864. return 0;
  865. }
  866. max_size = attr->size;
  867. if (max_size > 0x7fff >> 3) {
  868. ntfs_error(__FUNCTION__ "(): Directory too large. Visible "
  869. "length is truncated.n");
  870. max_size = 0x7fff >> 3;
  871. }
  872. buf = ntfs_malloc(max_size);
  873. if (!buf)
  874. return -ENOMEM;
  875. io.param = buf;
  876. io.size = max_size;
  877. err = ntfs_read_attr(ino, vol->at_bitmap, I30, 0, &io);
  878. if (err || io.size != max_size)
  879. goto read_err_ret;
  880. attr = ntfs_find_attr(ino, vol->at_index_allocation, I30);
  881. if (!attr) {
  882. ntfs_free(buf);
  883. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 9: Find "
  884. "attr failed. Returning -EIO.n");
  885. return -EIO;
  886. }
  887. if (attr->resident) {
  888. ntfs_free(buf);
  889. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 9.5: IA is "
  890. "resident. Not allowed. Returning EINVAL.n");
  891. return -EINVAL;
  892. }
  893. /* Loop while going through non-allocated index records. */
  894. max_size <<= 3;
  895. while (1) {
  896. if (++*p_high >= 0x7fff) {
  897. ntfs_error(__FUNCTION__ "(): Unsorted 10: Directory "
  898. "inode 0x%lx overflowed the maximum "
  899. "number of index allocation buffers "
  900. "the driver can cope with. Pretending "
  901. "to be at end of directory.n",
  902. ino->i_number);
  903. goto fake_eod;
  904. }
  905. if (*p_high > max_size || (s64)*p_high << ibs_bits >
  906. attr->initialized) {
  907. fake_eod:
  908. /* No more index records. */
  909. *p_high = 0x7fff;
  910. *p_low = 0;
  911. ntfs_free(buf);
  912. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted "
  913. "10.5: No more index records. "
  914. "Returning 0, p_high 0x7fff, p_low "
  915. "0.n");
  916. return 0;
  917. }
  918. byte = (ntfs_cluster_t)(*p_high - 1);
  919. bit = 1 << (byte & 7);
  920. byte >>= 3;
  921. if ((buf[byte] & bit))
  922. break;
  923. };
  924. ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 11: Done. "
  925. "Returning 0, p_high 0x%x, p_low 0x%x.n", *p_high,
  926. *p_low);
  927. ntfs_free(buf);
  928. return 0;
  929. read_err_ret:
  930. if (!err)
  931. err = -EIO;
  932. ntfs_error(__FUNCTION__ "(): Read failed. Returning error code %i.n",
  933. err);
  934. ntfs_free(buf);
  935. return err;
  936. }
  937. int ntfs_dir_add(ntfs_inode *dir, ntfs_inode *new, ntfs_attribute *name)
  938. {
  939. ntfs_iterate_s walk;
  940. int nsize, esize;
  941. ntfs_u8* entry, *ndata;
  942. int error;
  943. walk.type = DIR_INSERT;
  944. walk.dir = dir;
  945. walk.u.flags = 0;
  946. nsize = name->size;
  947. ndata = name->d.data;
  948. walk.name = (ntfs_u16*)(ndata + 0x42);
  949. walk.namelen = NTFS_GETU8(ndata + 0x40);
  950. walk.new_entry_size = esize = (nsize + 0x10 + 7) & ~7;
  951. walk.new_entry = entry = ntfs_malloc(esize);
  952. if (!entry)
  953. return -ENOMEM;
  954. NTFS_PUTINUM(entry, new);
  955. NTFS_PUTU16(entry + 0x8, esize); /* Size of entry. */
  956. NTFS_PUTU16(entry + 0xA, nsize); /* Size of original name attribute. */
  957. NTFS_PUTU16(entry + 0xC, 0);     /* Flags. */
  958. NTFS_PUTU16(entry + 0xE, 0);  /* Reserved. */
  959. ntfs_memcpy(entry + 0x10, ndata, nsize);
  960. ntfs_bzero(entry + 0x10 + nsize, esize - 0x10 - nsize);
  961. error = ntfs_getdir(&walk);
  962. if (walk.new_entry)
  963. ntfs_free(walk.new_entry);
  964. return error;
  965. }
  966. #if 0
  967. int ntfs_dir_add1(ntfs_inode *dir, const char* name, int namelen,
  968.   ntfs_inode *ino)
  969. {
  970. ntfs_iterate_s walk;
  971. int error;
  972. int nsize;
  973. char *entry;
  974. ntfs_attribute *name_attr;
  975. error = ntfs_decodeuni(dir->vol, name, namelen, &walk.name,
  976.        &walk.namelen);
  977. if (error)
  978. return error;
  979. /* FIXME: Set flags. */
  980. walk.type = DIR_INSERT;
  981. walk.dir = dir;
  982. /* walk.new = ino; */
  983. /* Prepare new entry. */
  984. /* Round up to a multiple of 8. */
  985. walk.new_entry_size = nsize = ((0x52 + 2 * walk.namelen + 7) / 8) * 8;
  986. walk.new_entry = entry = ntfs_malloc(nsize);
  987. if (!entry)
  988. return -ENOMEM;
  989. ntfs_bzero(entry, nsize);
  990. NTFS_PUTINUM(entry, ino);
  991. NTFS_PUTU16(entry + 8, nsize);
  992. NTFS_PUTU16(entry + 0xA, 0x42 + 2 * namelen); /* FIXME: Size of name 
  993.        * attribute. */
  994. NTFS_PUTU32(entry + 0xC, 0); /* FIXME: D-F? */
  995. name_attr = ntfs_find_attr(ino, vol->at_file_name, 0);
  996.     /* FIXME: multiple names */
  997. if (!name_attr || !name_attr->resident)
  998. return -EIDRM;
  999. /* Directory, file stamps, sizes, filename. */
  1000. ntfs_memcpy(entry + 0x10, name_attr->d.data, 0x42 + 2 * namelen);
  1001. error = ntfs_getdir(&walk);
  1002. ntfs_free(walk.name);
  1003. return error;
  1004. }
  1005. #endif
  1006. /* Fills out and creates an INDEX_ROOT attribute. */
  1007. int ntfs_add_index_root(ntfs_inode *ino, int type)
  1008. {
  1009. ntfs_attribute *da;
  1010. ntfs_u8 data[0x30]; /* 0x20 header, 0x10 last entry. */
  1011. char name[10];
  1012. NTFS_PUTU32(data, type);
  1013. /* Collation rule. 1 == COLLATION_FILENAME */
  1014. NTFS_PUTU32(data + 4, 1);
  1015. NTFS_PUTU32(data + 8, ino->vol->index_record_size);
  1016. NTFS_PUTU32(data + 0xC, ino->vol->index_clusters_per_record);
  1017. /* Byte offset to first INDEX_ENTRY. */
  1018. NTFS_PUTU32(data + 0x10, 0x10);
  1019. /* Size of entries, including header. */
  1020. NTFS_PUTU32(data + 0x14, 0x20);
  1021. NTFS_PUTU32(data + 0x18, 0x20);
  1022. /* No index allocation, yet. */
  1023. NTFS_PUTU32(data + 0x1C, 0);
  1024. /* Add last entry. */
  1025. /* Indexed MFT record. */
  1026. NTFS_PUTU64(data + 0x20, 0);
  1027. /* Size of entry. */
  1028. NTFS_PUTU32(data + 0x28, 0x10);
  1029. /* Flags: Last entry, no child nodes. */
  1030. NTFS_PUTU32(data + 0x2C, 2);
  1031. /* Compute name. */
  1032. ntfs_indexname(name, type);
  1033. return ntfs_create_attr(ino, ino->vol->at_index_root, name,
  1034. data, sizeof(data), &da);
  1035. }
  1036. int ntfs_mkdir(ntfs_inode *dir, const char *name, int namelen,
  1037.        ntfs_inode *result)
  1038. {
  1039. int error;
  1040. error = ntfs_alloc_inode(dir, result, name, namelen, NTFS_AFLAG_DIR);
  1041. if (error)
  1042. goto out;
  1043. error = ntfs_add_index_root(result, 0x30);
  1044. if (error)
  1045. goto out;
  1046. /* Set directory bit. */
  1047. result->attr[0x16] |= 2;
  1048. error = ntfs_update_inode(dir);
  1049. if (error)
  1050. goto out;
  1051. error = ntfs_update_inode(result);
  1052. if (error)
  1053. goto out;
  1054.  out:
  1055. return error;
  1056. }