1
2
3
4
5
6
7
8
9
10#include "ntfstypes.h"
11#include "struct.h"
12#include "dir.h"
13#include "macros.h"
14
15#include <linux/errno.h>
16#include "super.h"
17#include "inode.h"
18#include "attr.h"
19#include "support.h"
20#include "util.h"
21#include <linux/smp_lock.h>
22#include <linux/bitops.h>
23
24static char I30[] = "$I30";
25
26
27
28
29int ntfs_check_index_record(ntfs_inode *ino, char *record)
30{
31 return ntfs_fixup_record(record, "INDX", ino->u.index.recordsize);
32}
33
34static inline int ntfs_is_top(ntfs_u64 stack)
35{
36 return stack == 14;
37}
38
39static int ntfs_pop(ntfs_u64 *stack)
40{
41 static int width[16] = {1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,-1};
42 int res = -1;
43
44 switch (width[*stack & 15]) {
45 case 1:
46 res = (int)((*stack & 15) >> 1);
47 *stack >>= 4;
48 break;
49 case 2:
50 res = (int)(((*stack & 63) >> 2) + 7);
51 *stack >>= 6;
52 break;
53 case 3:
54 res = (int)(((*stack & 255) >> 3) + 23);
55 *stack >>= 8;
56 break;
57 case 4:
58 res = (int)(((*stack & 1023) >> 4) + 55);
59 *stack >>= 10;
60 break;
61 default:
62 ntfs_error("Unknown encoding\n");
63 }
64 return res;
65}
66
67static inline unsigned int ntfs_top(void)
68{
69 return 14;
70}
71
72static ntfs_u64 ntfs_push(ntfs_u64 stack, int i)
73{
74 if (i < 7)
75 return (stack << 4) | (i << 1);
76 if (i < 23)
77 return (stack << 6) | ((i - 7) << 2) | 1;
78 if (i < 55)
79 return (stack << 8) | ((i - 23) << 3) | 3;
80 if (i < 120)
81 return (stack << 10) | ((i - 55) << 4) | 7;
82 ntfs_error("Too many entries\n");
83 return ~((ntfs_u64)0);
84}
85
86#if 0
87static void ntfs_display_stack(ntfs_u64 stack)
88{
89 while(!ntfs_is_top(stack))
90 {
91 printf("%d ", ntfs_pop(&stack));
92 }
93 printf("\n");
94}
95#endif
96
97
98static inline int ntfs_entry_has_subnodes(char *entry)
99{
100 return (NTFS_GETU16(entry + 0xc) & 1);
101}
102
103
104static inline int ntfs_entry_is_used(char *entry)
105{
106 return !(NTFS_GETU16(entry + 0xc) & 2);
107}
108
109
110
111
112
113static int ntfs_allocate_index_block(ntfs_iterate_s *walk)
114{
115 ntfs_attribute *allocation, *bitmap = 0;
116 int error, size, i, bit;
117 ntfs_u8 *bmap;
118 ntfs_io io;
119 ntfs_volume *vol = walk->dir->vol;
120
121
122 allocation = ntfs_find_attr(walk->dir, vol->at_index_allocation, I30);
123 if (!allocation) {
124 ntfs_u8 bmp[8];
125
126 error = ntfs_create_attr(walk->dir, vol->at_index_allocation,
127 I30, 0, 0, &allocation);
128 if (error)
129 goto err_ret;
130 ntfs_bzero(bmp, sizeof(bmp));
131 error = ntfs_create_attr(walk->dir, vol->at_bitmap, I30, bmp,
132 sizeof(bmp), &bitmap);
133 if (error)
134 goto err_ret;
135 } else
136 bitmap = ntfs_find_attr(walk->dir, vol->at_bitmap, I30);
137 if (!bitmap) {
138 ntfs_error("Directory w/o bitmap\n");
139 error = -EINVAL;
140 goto err_ret;
141 }
142 size = bitmap->size;
143 bmap = ntfs_malloc(size);
144 if (!bmap) {
145 error = -ENOMEM;
146 goto err_ret;
147 }
148 io.fn_put = ntfs_put;
149 io.fn_get = ntfs_get;
150try_again:
151 io.param = bmap;
152 io.size = size;
153 error = ntfs_read_attr(walk->dir, vol->at_bitmap, I30, 0, &io);
154 if (error || (io.size != size && (error = -EIO, 1)))
155 goto err_fb_out;
156
157 for (bit = i = 0; i < size; i++) {
158 if (bmap[i] == 0xFF)
159 continue;
160 bit = ffz(bmap[i]);
161 if (bit < 8)
162 break;
163 }
164 if (i >= size) {
165
166 error = -EOPNOTSUPP;
167 goto err_fb_out;
168 }
169
170 io.param = bmap;
171 io.size = 1;
172 lock_kernel();
173 error = ntfs_read_attr(walk->dir, vol->at_bitmap, I30, i, &io);
174 if (error || (io.size != 1 && (error = -EIO, 1)))
175 goto err_unl_out;
176 if (ntfs_test_and_set_bit(bmap, bit)) {
177 unlock_kernel();
178
179 schedule();
180 goto try_again;
181 }
182 walk->newblock = (i * 8 + bit) * walk->dir->u.index.clusters_per_record;
183 io.param = bmap;
184 error = ntfs_write_attr(walk->dir, vol->at_bitmap, I30, i, &io);
185 if (error || (io.size != size && (error = -EIO, 1)))
186 goto err_unl_out;
187
188 error = ntfs_update_inode(walk->dir);
189 if (error)
190 goto err_unl_out;
191 unlock_kernel();
192 ntfs_free(bmap);
193
194 size = allocation->size;
195 if (walk->newblock * vol->cluster_size >= size) {
196
197 int hsize;
198 int s1 = walk->dir->u.index.recordsize;
199 int nr_fix = (s1 >> vol->sector_size) + 1;
200 char *record = ntfs_malloc(s1);
201 if (!record) {
202 error = -ENOMEM;
203 goto err_ret;
204 }
205 ntfs_bzero(record, s1);
206
207 ntfs_memcpy(record, "INDX", 4);
208
209 NTFS_PUTU16(record + 4, 0x28);
210
211 NTFS_PUTU16(record + 6, nr_fix);
212
213
214 NTFS_PUTU64(record + 8, 0);
215
216 NTFS_PUTU64(record + 0x10, walk->newblock);
217
218 hsize = 0x10 + 2 * nr_fix;
219 hsize = (hsize + 7) & ~7;
220 NTFS_PUTU16(record + 0x18, hsize);
221
222 NTFS_PUTU32(record + 0x20, s1 - 0x18);
223
224 io.param = record;
225 io.size = s1;
226 io.do_read = 0;
227 error = ntfs_readwrite_attr(walk->dir, allocation, size, &io);
228 ntfs_free(record);
229 if (error || (io.size != s1 && (error = -EIO, 1)))
230 goto err_ret;
231 error = ntfs_update_inode(walk->dir);
232 if (error)
233 goto err_ret;
234 }
235 return 0;
236err_unl_out:
237 unlock_kernel();
238err_fb_out:
239 ntfs_free(bmap);
240err_ret:
241 return error;
242}
243
244
245
246static int ntfs_index_writeback(ntfs_iterate_s *walk, ntfs_u8 *buf, int block,
247 int used)
248{
249 ntfs_io io;
250 int error;
251 ntfs_attribute *a;
252 ntfs_volume *vol = walk->dir->vol;
253
254 io.fn_put = 0;
255 io.fn_get = ntfs_get;
256 io.param = buf;
257 if (block == -1) {
258 NTFS_PUTU16(buf + 0x14, used - 0x10);
259
260 NTFS_PUTU16(buf + 0x18, used - 0x10);
261 io.size = used;
262 error = ntfs_write_attr(walk->dir, vol->at_index_root, I30, 0,
263 &io);
264 if (error || (io.size != used && (error = -EIO, 1)))
265 return error;
266
267 a = ntfs_find_attr(walk->dir, vol->at_index_root, I30);
268 ntfs_resize_attr(walk->dir, a, used);
269 } else {
270 NTFS_PUTU16(buf + 0x1C, used - 0x18);
271 io.size = walk->dir->u.index.recordsize;
272 error = ntfs_insert_fixups(buf, io.size);
273 if (error) {
274 printk(KERN_ALERT "NTFS: ntfs_index_writeback() caught "
275 "corrupt index record ntfs record "
276 "header. Refusing to write corrupt "
277 "data to disk. Unmount and run chkdsk "
278 "immediately!\n");
279 return -EIO;
280 }
281 error = ntfs_write_attr(walk->dir, vol->at_index_allocation,
282 I30, (__s64)block << vol->cluster_size_bits,
283 &io);
284 if (error || (io.size != walk->dir->u.index.recordsize &&
285 (error = -EIO, 1)))
286 return error;
287 }
288 return 0;
289}
290
291static int ntfs_split_record(ntfs_iterate_s *walk, char *start, int bsize,
292 int usize)
293{
294 char *entry, *prev;
295 ntfs_u8 *newbuf = 0, *middle = 0;
296 int error, othersize, mlen;
297 ntfs_io io;
298 ntfs_volume *vol = walk->dir->vol;
299 int oldblock;
300
301 error = ntfs_allocate_index_block(walk);
302 if (error)
303 return error;
304
305 if (walk->block == -1) {
306 ntfs_error("Trying to split root");
307 return -EOPNOTSUPP;
308 }
309 entry = start + NTFS_GETU16(start + 0x18) + 0x18;
310 for (prev = entry; entry - start < usize / 2;
311 entry += NTFS_GETU16(entry + 8))
312 prev = entry;
313 newbuf = ntfs_malloc(vol->index_record_size);
314 if (!newbuf)
315 return -ENOMEM;
316 io.fn_put = ntfs_put;
317 io.fn_get = ntfs_get;
318 io.param = newbuf;
319 io.size = vol->index_record_size;
320
321 error = ntfs_read_attr(walk->dir, vol->at_index_allocation, I30,
322 (__s64)walk->newblock << vol->cluster_size_bits, &io);
323 if (error)
324 goto out;
325 if (io.size != vol->index_record_size) {
326 error = -EIO;
327 goto out;
328 }
329
330
331 othersize = usize - (entry - start);
332 ntfs_memcpy(newbuf + NTFS_GETU16(newbuf + 0x18) + 0x18, entry,
333 othersize);
334
335 NTFS_PUTU32(newbuf + 0x24, NTFS_GETU32(start + 0x24));
336 error = ntfs_index_writeback(walk, newbuf, walk->newblock,
337 othersize + NTFS_GETU16(newbuf + 0x18) + 0x18);
338 if (error)
339 goto out;
340
341 mlen = NTFS_GETU16(prev + 0x8);
342
343 if (ntfs_entry_has_subnodes(prev))
344 oldblock = NTFS_GETU32(prev + mlen - 8);
345 else
346 oldblock = -1;
347
348 middle = ntfs_malloc(ntfs_entry_has_subnodes(prev) ? mlen : mlen + 8);
349 if (!middle){
350 error = -ENOMEM;
351 goto out;
352 }
353 ntfs_memcpy(middle, prev, mlen);
354
355 NTFS_PUTU8(middle + 0xC, NTFS_GETU8(middle + 0xC) | 1);
356
357 NTFS_PUTU64(middle + mlen - 8, walk->block);
358 if (walk->new_entry)
359 ntfs_error("Entry not reset");
360 walk->new_entry = middle;
361 walk->u.flags |= ITERATE_SPLIT_DONE;
362
363 othersize = usize - (prev-start);
364 NTFS_PUTU64(prev, 0);
365 if (oldblock == -1) {
366 NTFS_PUTU32(prev + 8, 0x10);
367 NTFS_PUTU32(prev + 0xC, 2);
368 othersize += 0x10;
369 } else {
370 NTFS_PUTU32(prev + 8, 0x18);
371 NTFS_PUTU32(prev + 0xC, 3);
372 NTFS_PUTU64(prev + 0x10, oldblock);
373 othersize += 0x18;
374 }
375
376 error = ntfs_index_writeback(walk, start, walk->block, othersize);
377 out:
378 if (newbuf)
379 ntfs_free(newbuf);
380 if (middle)
381 ntfs_free(middle);
382 return error;
383}
384
385static int ntfs_dir_insert(ntfs_iterate_s *walk, char *start, char* entry)
386{
387 int blocksize, usedsize, error, offset;
388 int do_split = 0;
389 offset = entry - start;
390 if (walk->block == -1) {
391 blocksize = walk->dir->vol->mft_record_size;
392 usedsize = NTFS_GETU16(start + 0x14) + 0x10;
393 } else {
394 blocksize = walk->dir->u.index.recordsize;
395 usedsize = NTFS_GETU16(start + 0x1C) + 0x18;
396 }
397 if (usedsize + walk->new_entry_size > blocksize) {
398 char* s1 = ntfs_malloc(blocksize + walk->new_entry_size);
399 if (!s1)
400 return -ENOMEM;
401 ntfs_memcpy(s1, start, usedsize);
402 do_split = 1;
403
404 entry = s1 + (entry - start);
405 start = s1;
406 }
407 ntfs_memmove(entry + walk->new_entry_size, entry, usedsize - offset);
408 ntfs_memcpy(entry, walk->new_entry, walk->new_entry_size);
409 usedsize += walk->new_entry_size;
410 ntfs_free(walk->new_entry);
411 walk->new_entry = 0;
412 if (do_split) {
413 error = ntfs_split_record(walk, start, blocksize, usedsize);
414 ntfs_free(start);
415 } else {
416 error = ntfs_index_writeback(walk, start, walk->block,usedsize);
417 if (error)
418 return error;
419 }
420 return 0;
421}
422
423
424int ntfs_split_indexroot(ntfs_inode *ino)
425{
426 ntfs_attribute *ra;
427 ntfs_u8 *root = 0, *index = 0;
428 ntfs_io io;
429 int error, off, i, bsize, isize;
430 ntfs_iterate_s walk;
431
432 ra = ntfs_find_attr(ino, ino->vol->at_index_root, I30);
433 if (!ra)
434 return -ENOTDIR;
435 bsize = ino->vol->mft_record_size;
436 root = ntfs_malloc(bsize);
437 if (!root)
438 return -E2BIG;
439 io.fn_put = ntfs_put;
440 io.param = root;
441 io.size = bsize;
442 error = ntfs_read_attr(ino, ino->vol->at_index_root, I30, 0, &io);
443 if (error)
444 goto out;
445 off = 0x20;
446
447 for (i = 0; ntfs_entry_is_used(root + off); i++)
448 off += NTFS_GETU16(root + off + 8);
449 if (i <= 2) {
450
451 error = -E2BIG;
452 goto out;
453 }
454 index = ntfs_malloc(ino->vol->index_record_size);
455 if (!index) {
456 error = -ENOMEM;
457 goto out;
458 }
459 walk.dir = ino;
460 walk.block = -1;
461 walk.result = walk.new_entry = 0;
462 walk.name = 0;
463 error = ntfs_allocate_index_block(&walk);
464 if (error)
465 goto out;
466
467 io.param = index;
468 io.size = ino->vol->index_record_size;
469 error = ntfs_read_attr(ino, ino->vol->at_index_allocation, I30,
470 (__s64)walk.newblock << ino->vol->cluster_size_bits, &io);
471 if (error)
472 goto out;
473 isize = NTFS_GETU16(root + 0x18) - 0x10;
474 ntfs_memcpy(index + NTFS_GETU16(index + 0x18) + 0x18, root+0x20, isize);
475
476 NTFS_PUTU32(index + 0x24, NTFS_GETU32(root + 0x1C));
477 error = ntfs_index_writeback(&walk, index, walk.newblock,
478 isize + NTFS_GETU16(index + 0x18) + 0x18);
479 if (error)
480 goto out;
481
482 NTFS_PUTU32(root + 0x1C, 1);
483
484 NTFS_PUTU64(root + 0x20, 0);
485 NTFS_PUTU32(root + 0x28, 0x18);
486 NTFS_PUTU32(root + 0x2C, 3);
487 NTFS_PUTU64(root + 0x30, walk.newblock);
488 error = ntfs_index_writeback(&walk, root, -1, 0x38);
489 out:
490 ntfs_free(root);
491 ntfs_free(index);
492 return error;
493}
494
495
496static int ntfs_copyresult(char *dest, char *source)
497{
498 int length = NTFS_GETU16(source + 8);
499 ntfs_memcpy(dest, source, length);
500 return 1;
501}
502
503
504static inline unsigned short ntfs_my_toupper(ntfs_volume *vol, ntfs_u16 x)
505{
506
507 if (x >= vol->upcase_length)
508 return x;
509 return vol->upcase[x];
510}
511
512
513static int ntfs_my_strcmp(ntfs_iterate_s *walk, const unsigned char *entry)
514{
515 int lu = *(entry + 0x50);
516 int i;
517
518 ntfs_u16* name = (ntfs_u16*)(entry + 0x52);
519 ntfs_volume *vol = walk->dir->vol;
520 for (i = 0; i < lu && i < walk->namelen; i++)
521 if (ntfs_my_toupper(vol, NTFS_GETU16(name + i)) !=
522 ntfs_my_toupper(vol, NTFS_GETU16(walk->name + i)))
523 break;
524 if (i == lu && i == walk->namelen)
525 return 0;
526 if (i == lu)
527 return 1;
528 if (i == walk->namelen)
529 return -1;
530 if (ntfs_my_toupper(vol, NTFS_GETU16(name + i)) <
531 ntfs_my_toupper(vol, NTFS_GETU16(walk->name + i)))
532 return 1;
533 return -1;
534}
535
536
537static int ntfs_getdir_iterate(ntfs_iterate_s *walk, char *start, char *entry);
538
539
540
541static int ntfs_getdir_record(ntfs_iterate_s *walk, int block)
542{
543 int length = walk->dir->u.index.recordsize;
544 char *record = (char*)ntfs_malloc(length);
545 char *offset;
546 int retval,error;
547 int oldblock;
548 ntfs_io io;
549
550 if (!record)
551 return -ENOMEM;
552 io.fn_put = ntfs_put;
553 io.param = record;
554 io.size = length;
555
556 error = ntfs_read_attr(walk->dir, walk->dir->vol->at_index_allocation,
557 I30, (__s64)block << walk->dir->vol->cluster_size_bits, &io);
558 if (error || io.size != length) {
559 ntfs_error("read failed\n");
560 ntfs_free(record);
561 return 0;
562 }
563 if (!ntfs_check_index_record(walk->dir, record)) {
564 ntfs_error("%x is not an index record\n", block);
565 ntfs_free(record);
566 return 0;
567 }
568 offset = record + NTFS_GETU16(record + 0x18) + 0x18;
569 oldblock = walk->block;
570 walk->block = block;
571 retval = ntfs_getdir_iterate(walk, record, offset);
572 walk->block = oldblock;
573 ntfs_free(record);
574 return retval;
575}
576
577
578
579static int ntfs_descend(ntfs_iterate_s *walk, ntfs_u8 *start, ntfs_u8 *entry)
580{
581 int length = NTFS_GETU16(entry + 8);
582 int nextblock = NTFS_GETU32(entry + length - 8);
583 int error;
584
585 if (!ntfs_entry_has_subnodes(entry)) {
586 ntfs_error("illegal ntfs_descend call\n");
587 return 0;
588 }
589 error = ntfs_getdir_record(walk, nextblock);
590 if (!error && walk->type == DIR_INSERT &&
591 (walk->u.flags & ITERATE_SPLIT_DONE)) {
592
593 NTFS_PUTU32(entry + length - 8, walk->newblock);
594
595 walk->u.flags &= ~ITERATE_SPLIT_DONE;
596 error = ntfs_dir_insert(walk, start, entry);
597 }
598 return error;
599}
600
601static int ntfs_getdir_iterate_byposition(ntfs_iterate_s *walk, char* start,
602 char *entry)
603{
604 int retval = 0;
605 int curpos = 0, destpos = 0;
606 int length;
607 if (walk->u.pos != 0) {
608 if (ntfs_is_top(walk->u.pos))
609 return 0;
610 destpos = ntfs_pop(&walk->u.pos);
611 }
612 while (1) {
613 if (walk->u.pos == 0) {
614 if (ntfs_entry_has_subnodes(entry))
615 ntfs_descend(walk, start, entry);
616 else
617 walk->u.pos = ntfs_top();
618 if (ntfs_is_top(walk->u.pos) &&
619 !ntfs_entry_is_used(entry))
620 return 1;
621 walk->u.pos = ntfs_push(walk->u.pos, curpos);
622 return 1;
623 }
624 if (curpos == destpos) {
625 if (!ntfs_is_top(walk->u.pos) &&
626 ntfs_entry_has_subnodes(entry)) {
627 retval = ntfs_descend(walk, start, entry);
628 if (retval) {
629 walk->u.pos = ntfs_push(walk->u.pos,
630 curpos);
631 return retval;
632 }
633 if (!ntfs_entry_is_used(entry))
634 return 0;
635 walk->u.pos = 0;
636 }
637 if (ntfs_entry_is_used(entry)) {
638 retval = ntfs_copyresult(walk->result, entry);
639 walk->u.pos = 0;
640 } else {
641 walk->u.pos = ntfs_top();
642 return 0;
643 }
644 }
645 curpos++;
646 if (!ntfs_entry_is_used(entry))
647 break;
648 length = NTFS_GETU16(entry + 8);
649 if (!length) {
650 ntfs_error("infinite loop\n");
651 break;
652 }
653 entry += length;
654 }
655 return -1;
656}
657
658
659
660
661
662
663
664
665
666
667
668
669static int ntfs_getdir_iterate(ntfs_iterate_s *walk, char *start, char *entry)
670{
671 int length;
672 int cmp;
673
674 if (walk->type == BY_POSITION)
675 return ntfs_getdir_iterate_byposition(walk, start, entry);
676 do {
677
678
679
680 cmp = ntfs_entry_is_used(entry) ?
681 ntfs_my_strcmp(walk,entry) : -1;
682 switch (walk->type) {
683 case BY_NAME:
684 switch (cmp) {
685 case -1:
686 return ntfs_entry_has_subnodes(entry) ?
687 ntfs_descend(walk, start, entry) : 0;
688 case 0:
689 return ntfs_copyresult(walk->result, entry);
690 case 1:
691 break;
692 }
693 break;
694 case DIR_INSERT:
695 switch (cmp) {
696 case -1:
697 return ntfs_entry_has_subnodes(entry) ?
698 ntfs_descend(walk, start, entry) :
699 ntfs_dir_insert(walk, start, entry);
700 case 0:
701 return -EEXIST;
702 case 1:
703 break;
704 }
705 break;
706 default:
707 ntfs_error("TODO\n");
708 }
709 if (!ntfs_entry_is_used(entry))
710 break;
711 length = NTFS_GETU16(entry + 8);
712 if (!length) {
713 ntfs_error("infinite loop\n");
714 break;
715 }
716 entry += length;
717 } while (1);
718 return 0;
719}
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744int ntfs_getdir(ntfs_iterate_s *walk)
745{
746 int length = walk->dir->vol->mft_record_size;
747 int retval, error;
748
749 char *root = ntfs_malloc(length);
750 ntfs_io io;
751
752 if (!root)
753 return -ENOMEM;
754 io.fn_put = ntfs_put;
755 io.param = root;
756 io.size = length;
757 error = ntfs_read_attr(walk->dir, walk->dir->vol->at_index_root, I30,
758 0, &io);
759 if (error) {
760 ntfs_error("Not a directory\n");
761 return 0;
762 }
763 walk->block = -1;
764
765 walk->dir->u.index.recordsize = NTFS_GETU32(root + 0x8);
766 walk->dir->u.index.clusters_per_record = NTFS_GETU32(root + 0xC);
767
768
769 retval = ntfs_getdir_iterate(walk, root, root + 0x20);
770 ntfs_free(root);
771 return retval;
772}
773
774
775
776
777
778
779int ntfs_getdir_byposition(ntfs_iterate_s *walk)
780{
781 walk->type = BY_POSITION;
782 return ntfs_getdir(walk);
783}
784
785
786int ntfs_getdir_byname(ntfs_iterate_s *walk)
787{
788 walk->type = BY_NAME;
789 return ntfs_getdir(walk);
790}
791
792int ntfs_getdir_unsorted(ntfs_inode *ino, u32 *p_high, u32 *p_low,
793 int (*cb)(ntfs_u8 *, void *), void *param)
794{
795 s64 ib_ofs;
796 char *buf = 0, *entry = 0;
797 ntfs_attribute *attr;
798 ntfs_volume *vol;
799 int byte, bit, err = 0;
800 u32 start, finish, ibs, max_size;
801 ntfs_io io;
802 u8 ibs_bits;
803
804 if (!ino) {
805 ntfs_error("%s(): No inode! Returning -EINVAL.\n",__FUNCTION__);
806 return -EINVAL;
807 }
808 vol = ino->vol;
809 if (!vol) {
810 ntfs_error("%s(): Inode 0x%lx has no volume. Returning "
811 "-EINVAL.\n", __FUNCTION__, ino->i_number);
812 return -EINVAL;
813 }
814 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 1: Entering for inode 0x%lx, "
815 "p_high = 0x%x, p_low = 0x%x.\n", __FUNCTION__,
816 ino->i_number, *p_high, *p_low);
817 if (!*p_high) {
818
819 buf = ntfs_malloc(io.size = vol->mft_record_size);
820 if (!buf)
821 return -ENOMEM;
822 io.fn_put = ntfs_put;
823 io.param = buf;
824 err = ntfs_read_attr(ino, vol->at_index_root, I30, 0, &io);
825 if (err || !io.size)
826 goto read_err_ret;
827 ino->u.index.recordsize = ibs = NTFS_GETU32(buf + 0x8);
828 ino->u.index.clusters_per_record = NTFS_GETU32(buf + 0xC);
829 entry = buf + 0x20;
830 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 2: In index root.\n",
831 __FUNCTION__);
832 ibs_bits = ffs(ibs) - 1;
833
834 start = 2;
835 } else {
836 io.size = ibs = ino->u.index.recordsize;
837 buf = ntfs_malloc(ibs);
838 if (!buf)
839 return -ENOMEM;
840 ibs_bits = ffs(ibs) - 1;
841 io.fn_put = ntfs_put;
842 io.param = buf;
843
844
845
846
847 ib_ofs = (s64)(*p_high - 1) << ibs_bits;
848 err = ntfs_read_attr(ino, vol->at_index_allocation, I30, ib_ofs,
849 &io);
850 if (err || io.size != ibs)
851 goto read_err_ret;
852 if (!ntfs_check_index_record(ino, buf)) {
853 ntfs_error("%s(): Index block 0x%x is not an index "
854 "record. Returning -ENOTDIR.\n",
855 __FUNCTION__, *p_high - 1);
856 ntfs_free(buf);
857 return -ENOTDIR;
858 }
859 entry = buf + 0x18 + NTFS_GETU16(buf + 0x18);
860 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 3: In index "
861 "allocation.\n", __FUNCTION__);
862 start = 0;
863 }
864
865 finish = *p_low;
866 for (; entry < (buf + ibs) && ntfs_entry_is_used(entry);
867 entry += NTFS_GETU16(entry + 8)) {
868 if (start < finish) {
869
870 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 4: Skipping "
871 "already processed entry p_high 0x%x, "
872 "p_low 0x%x.\n", __FUNCTION__, *p_high,
873 start);
874 start++;
875 continue;
876 }
877 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 5: Processing entry "
878 "p_high 0x%x, p_low 0x%x.\n", __FUNCTION__,
879 *p_high, *p_low);
880 if ((err = cb(entry, param))) {
881
882 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 6: cb returned "
883 "%i, returning 0, p_high 0x%x, "
884 "p_low 0x%x.\n", __FUNCTION__, err,
885 *p_high, *p_low);
886 ntfs_free(buf);
887 return 0;
888 }
889 ++*p_low;
890 }
891 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 7: After processing entries, "
892 "p_high 0x%x, p_low 0x%x.\n", __FUNCTION__, *p_high,
893 *p_low);
894
895 ntfs_free(buf);
896 buf = 0;
897 *p_low = 0;
898 attr = ntfs_find_attr(ino, vol->at_bitmap, I30);
899 if (!attr) {
900
901 *p_high = 0x7fff;
902 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 8: No index allocation. "
903 "Returning 0, p_high 0x7fff, p_low 0x0.\n",
904 __FUNCTION__);
905 return 0;
906 }
907 max_size = attr->size;
908 if (max_size > 0x7fff >> 3) {
909 ntfs_error("%s(): Directory too large. Visible "
910 "length is truncated.\n", __FUNCTION__);
911 max_size = 0x7fff >> 3;
912 }
913 buf = ntfs_malloc(max_size);
914 if (!buf)
915 return -ENOMEM;
916 io.param = buf;
917 io.size = max_size;
918 err = ntfs_read_attr(ino, vol->at_bitmap, I30, 0, &io);
919 if (err || io.size != max_size)
920 goto read_err_ret;
921 attr = ntfs_find_attr(ino, vol->at_index_allocation, I30);
922 if (!attr) {
923 ntfs_free(buf);
924 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 9: Find attr failed. "
925 "Returning -EIO.\n", __FUNCTION__);
926 return -EIO;
927 }
928 if (attr->resident) {
929 ntfs_free(buf);
930 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 9.5: IA is resident. Not"
931 " allowed. Returning EINVAL.\n", __FUNCTION__);
932 return -EINVAL;
933 }
934
935 max_size <<= 3;
936 while (1) {
937 if (++*p_high >= 0x7fff) {
938 ntfs_error("%s(): Unsorted 10: Directory "
939 "inode 0x%lx overflowed the maximum "
940 "number of index allocation buffers "
941 "the driver can cope with. Pretending "
942 "to be at end of directory.\n",
943 __FUNCTION__, ino->i_number);
944 goto fake_eod;
945 }
946 if (*p_high > max_size || (s64)*p_high << ibs_bits >
947 attr->initialized) {
948fake_eod:
949
950 *p_high = 0x7fff;
951 *p_low = 0;
952 ntfs_free(buf);
953 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 10.5: No more "
954 "index records. Returning 0, p_high "
955 "0x7fff, p_low 0.\n", __FUNCTION__);
956 return 0;
957 }
958 byte = (ntfs_cluster_t)(*p_high - 1);
959 bit = 1 << (byte & 7);
960 byte >>= 3;
961 if ((buf[byte] & bit))
962 break;
963 };
964 ntfs_debug(DEBUG_DIR3, "%s(): Unsorted 11: Done. Returning 0, p_high "
965 "0x%x, p_low 0x%x.\n", __FUNCTION__, *p_high, *p_low);
966 ntfs_free(buf);
967 return 0;
968read_err_ret:
969 if (!err)
970 err = -EIO;
971 ntfs_error("%s(): Read failed. Returning error code %i.\n",
972 __FUNCTION__, err);
973 ntfs_free(buf);
974 return err;
975}
976
977int ntfs_dir_add(ntfs_inode *dir, ntfs_inode *new, ntfs_attribute *name)
978{
979 ntfs_iterate_s walk;
980 int nsize, esize;
981 ntfs_u8* entry, *ndata;
982 int error;
983
984 walk.type = DIR_INSERT;
985 walk.dir = dir;
986 walk.u.flags = 0;
987 nsize = name->size;
988 ndata = name->d.data;
989 walk.name = (ntfs_u16*)(ndata + 0x42);
990 walk.namelen = NTFS_GETU8(ndata + 0x40);
991 walk.new_entry_size = esize = (nsize + 0x10 + 7) & ~7;
992 walk.new_entry = entry = ntfs_malloc(esize);
993 if (!entry)
994 return -ENOMEM;
995 NTFS_PUTINUM(entry, new);
996 NTFS_PUTU16(entry + 0x8, esize);
997 NTFS_PUTU16(entry + 0xA, nsize);
998 NTFS_PUTU16(entry + 0xC, 0);
999 NTFS_PUTU16(entry + 0xE, 0);
1000 ntfs_memcpy(entry + 0x10, ndata, nsize);
1001 ntfs_bzero(entry + 0x10 + nsize, esize - 0x10 - nsize);
1002 error = ntfs_getdir(&walk);
1003 if (walk.new_entry)
1004 ntfs_free(walk.new_entry);
1005 return error;
1006}
1007
1008#if 0
1009int ntfs_dir_add1(ntfs_inode *dir, const char* name, int namelen,
1010 ntfs_inode *ino)
1011{
1012 ntfs_iterate_s walk;
1013 int error;
1014 int nsize;
1015 char *entry;
1016 ntfs_attribute *name_attr;
1017 error = ntfs_decodeuni(dir->vol, name, namelen, &walk.name,
1018 &walk.namelen);
1019 if (error)
1020 return error;
1021
1022 walk.type = DIR_INSERT;
1023 walk.dir = dir;
1024
1025
1026
1027 walk.new_entry_size = nsize = ((0x52 + 2 * walk.namelen + 7) / 8) * 8;
1028 walk.new_entry = entry = ntfs_malloc(nsize);
1029 if (!entry)
1030 return -ENOMEM;
1031 ntfs_bzero(entry, nsize);
1032 NTFS_PUTINUM(entry, ino);
1033 NTFS_PUTU16(entry + 8, nsize);
1034 NTFS_PUTU16(entry + 0xA, 0x42 + 2 * namelen);
1035
1036 NTFS_PUTU32(entry + 0xC, 0);
1037 name_attr = ntfs_find_attr(ino, vol->at_file_name, 0);
1038
1039 if (!name_attr || !name_attr->resident)
1040 return -EIDRM;
1041
1042 ntfs_memcpy(entry + 0x10, name_attr->d.data, 0x42 + 2 * namelen);
1043 error = ntfs_getdir(&walk);
1044 ntfs_free(walk.name);
1045 return error;
1046}
1047#endif
1048
1049
1050int ntfs_add_index_root(ntfs_inode *ino, int type)
1051{
1052 ntfs_attribute *da;
1053 ntfs_u8 data[0x30];
1054 char name[10];
1055
1056 NTFS_PUTU32(data, type);
1057
1058 NTFS_PUTU32(data + 4, 1);
1059 NTFS_PUTU32(data + 8, ino->vol->index_record_size);
1060 NTFS_PUTU32(data + 0xC, ino->vol->index_clusters_per_record);
1061
1062 NTFS_PUTU32(data + 0x10, 0x10);
1063
1064 NTFS_PUTU32(data + 0x14, 0x20);
1065 NTFS_PUTU32(data + 0x18, 0x20);
1066
1067 NTFS_PUTU32(data + 0x1C, 0);
1068
1069
1070 NTFS_PUTU64(data + 0x20, 0);
1071
1072 NTFS_PUTU32(data + 0x28, 0x10);
1073
1074 NTFS_PUTU32(data + 0x2C, 2);
1075
1076 ntfs_indexname(name, type);
1077 return ntfs_create_attr(ino, ino->vol->at_index_root, name,
1078 data, sizeof(data), &da);
1079}
1080
1081int ntfs_mkdir(ntfs_inode *dir, const char *name, int namelen,
1082 ntfs_inode *result)
1083{
1084 int error;
1085
1086 error = ntfs_alloc_inode(dir, result, name, namelen, NTFS_AFLAG_DIR);
1087 if (error)
1088 goto out;
1089 error = ntfs_add_index_root(result, 0x30);
1090 if (error)
1091 goto out;
1092
1093 result->attr[0x16] |= 2;
1094 error = ntfs_update_inode(dir);
1095 if (error)
1096 goto out;
1097 error = ntfs_update_inode(result);
1098 if (error)
1099 goto out;
1100 out:
1101 return error;
1102}
1103
1104