2 * dir.c - Directory handling code. Part of the Linux-NTFS project.
4 * Copyright (c) 2002-2003 Anton Altaparmakov
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (in the main directory of the Linux-NTFS
18 * distribution in the file COPYING); if not, write to the Free Software
19 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 * The little endian Unicode string "$I30" as a global constant.
36 uchar_t I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'),
37 const_cpu_to_le16('3'), const_cpu_to_le16('0'),
38 const_cpu_to_le16('\0') };
41 * ntfs_inode_lookup_by_name - find an inode in a directory given its name
42 * @dir_ni: ntfs inode of the directory in which to search for the name
43 * @uname: Unicode name for which to search in the directory
44 * @uname_len: length of the name @uname in Unicode characters
46 * Look for an inode with name @uname in the directory with inode @dir_ni.
47 * ntfs_inode_lookup_by_name() walks the contents of the directory looking for
48 * the Unicode name. If the name is found in the directory, the corresponding
49 * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it
50 * is a 64-bit number containing the sequence number.
52 * On error, return -1 with errno set to the error code. If the inode is is not
53 * found errno is ENOENT.
55 * Note, @uname_len does not include the (optional) terminating NULL character.
57 * Note, we look for a case sensitive match first but we also look for a case
58 * insensitive match at the same time. If we find a case insensitive match, we
59 * save that for the case that we don't find an exact match, where we return
60 * the mft reference of the case insensitive match.
62 * If the volume is mounted with the case sensitive flag set, then we only
63 * allow exact matches.
65 u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
71 ntfs_volume *vol = dir_ni->vol;
72 ntfs_attr_search_ctx *ctx;
79 u32 index_block_size, index_vcn_size;
80 u8 index_vcn_size_bits;
82 if (!dir_ni || !dir_ni->mrec || !uname || uname_len <= 0) {
87 ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);
91 /* Find the index root attribute in the mft record. */
92 if (ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
94 Dprintf("Index root attribute missing in directory inode "
96 (unsigned long long)dir_ni->mft_no,
100 /* Get to the index root value. */
101 ir = (INDEX_ROOT*)((u8*)ctx->attr +
102 le16_to_cpu(ctx->attr->value_offset));
103 index_block_size = le32_to_cpu(ir->index_block_size);
104 if (index_block_size < NTFS_SECTOR_SIZE ||
105 index_block_size & (index_block_size - 1)) {
106 Dprintf("Index block size %u is invalid.\n", index_block_size);
109 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
110 /* The first index entry. */
111 ie = (INDEX_ENTRY*)((u8*)&ir->index +
112 le32_to_cpu(ir->index.entries_offset));
114 * Loop until we exceed valid memory (corruption case) or until we
115 * reach the last entry.
117 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
119 if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
120 sizeof(INDEX_ENTRY_HEADER) > index_end ||
121 (u8*)ie + le16_to_cpu(ie->key_length) >
125 * The last entry cannot contain a name. It can however contain
126 * a pointer to a child node in the B+tree so we just break out.
128 if (ie->flags & INDEX_ENTRY_END)
131 * We perform a case sensitive comparison and if that matches
132 * we are done and return the mft reference of the inode (i.e.
133 * the inode number together with the sequence number for
134 * consistency checking). We convert it to cpu format before
137 if (ntfs_names_are_equal(uname, uname_len,
138 (uchar_t*)&ie->key.file_name.file_name,
139 ie->key.file_name.file_name_length,
140 CASE_SENSITIVE, vol->upcase, vol->upcase_len)) {
143 * We have a perfect match, so we don't need to care
144 * about having matched imperfectly before.
146 mref = le64_to_cpu(ie->indexed_file);
147 ntfs_attr_put_search_ctx(ctx);
151 * For a case insensitive mount, we also perform a case
152 * insensitive comparison (provided the file name is not in the
153 * POSIX namespace). If the comparison matches, we cache the
154 * mft reference in mref.
156 if (!NVolCaseSensitive(vol) &&
157 ie->key.file_name.file_name_type &&
158 ntfs_names_are_equal(uname, uname_len,
159 (uchar_t*)&ie->key.file_name.file_name,
160 ie->key.file_name.file_name_length,
161 IGNORE_CASE, vol->upcase, vol->upcase_len)) {
162 /* Only one case insensitive matching name allowed. */
164 Dputs("Found already cached mft reference in "
165 "phase 1. Please run chkdsk "
166 "and if that doesn't find any "
167 "errors please report you saw "
169 "linux-ntfs-dev@lists.sf.net.");
172 mref = le64_to_cpu(ie->indexed_file);
175 * Not a perfect match, need to do full blown collation so we
176 * know which way in the B+tree we have to go.
178 rc = ntfs_names_collate(uname, uname_len,
179 (uchar_t*)&ie->key.file_name.file_name,
180 ie->key.file_name.file_name_length, 1,
181 IGNORE_CASE, vol->upcase, vol->upcase_len);
183 * If uname collates before the name of the current entry, there
184 * is definitely no such name in this index but we might need to
185 * descend into the B+tree so we just break out of the loop.
189 /* The names are not equal, continue the search. */
193 * Names match with case insensitive comparison, now try the
194 * case sensitive comparison, which is required for proper
197 rc = ntfs_names_collate(uname, uname_len,
198 (uchar_t*)&ie->key.file_name.file_name,
199 ie->key.file_name.file_name_length, 1,
200 CASE_SENSITIVE, vol->upcase, vol->upcase_len);
206 * Perfect match, this will never happen as the
207 * ntfs_are_names_equal() call will have gotten a match but we
208 * still treat it correctly.
213 * We have finished with this index without success. Check for the
214 * presence of a child node and if not present return error code
215 * ENOENT, unless we have got the mft reference of a matching name
216 * cached in mref in which case return mref.
218 if (!(ie->flags & INDEX_ENTRY_NODE)) {
219 ntfs_attr_put_search_ctx(ctx);
222 Dputs("Entry not found.");
225 } /* Child node present, descend into it. */
227 /* Open the index allocation attribute. */
228 ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, I30, 4);
230 Dprintf("Failed to open index allocation attribute. Directory "
231 "inode 0x%Lx is corrupt or driver bug: %s\n",
232 (unsigned long long)dir_ni->mft_no,
237 /* Allocate a buffer for the current index block. */
238 ia = (INDEX_ALLOCATION*)malloc(index_block_size);
240 Dperror("Failed to allocate buffer for index block");
244 /* Determine the size of a vcn in the directory index. */
245 if (vol->cluster_size <= index_block_size) {
246 index_vcn_size = vol->cluster_size;
247 index_vcn_size_bits = vol->cluster_size_bits;
249 index_vcn_size = vol->sector_size;
250 index_vcn_size_bits = vol->sector_size_bits;
253 /* Get the starting vcn of the index_block holding the child node. */
254 vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
256 descend_into_child_node:
258 /* Read the index block starting at vcn. */
259 br = ntfs_attr_mst_pread(ia_na, vcn << index_vcn_size_bits, 1,
260 index_block_size, ia);
264 Dprintf("Failed to read vcn 0x%Lx: %s\n", vcn, strerror(errno));
268 if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
269 Dprintf("Actual VCN (0x%Lx) of index buffer is different from "
270 "expected VCN (0x%Lx).\n",
271 (long long)sle64_to_cpu(ia->index_block_vcn),
276 if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) {
277 Dprintf("Index buffer (VCN 0x%Lx) of directory inode 0x%Lx "
278 "has a size (%u) differing from the directory "
279 "specified size (%u).\n", (long long)vcn,
280 (unsigned long long)dir_ni->mft_no,
281 le32_to_cpu(ia->index.allocated_size) + 0x18,
286 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
287 if (index_end > (u8*)ia + index_block_size) {
288 Dprintf("Size of index buffer (VCN 0x%Lx) of directory inode "
289 "0x%Lx exceeds maximum size.\n", (long long)vcn,
290 (unsigned long long)dir_ni->mft_no);
295 /* The first index entry. */
296 ie = (INDEX_ENTRY*)((u8*)&ia->index +
297 le32_to_cpu(ia->index.entries_offset));
299 * Iterate similar to above big loop but applied to index buffer, thus
300 * loop until we exceed valid memory (corruption case) or until we
301 * reach the last entry.
303 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
305 if ((u8*)ie < (u8*)ia || (u8*)ie +
306 sizeof(INDEX_ENTRY_HEADER) > index_end ||
307 (u8*)ie + le16_to_cpu(ie->key_length) >
309 Dprintf("Index entry out of bounds in directory inode "
311 (unsigned long long)dir_ni->mft_no);
316 * The last entry cannot contain a name. It can however contain
317 * a pointer to a child node in the B+tree so we just break out.
319 if (ie->flags & INDEX_ENTRY_END)
322 * We perform a case sensitive comparison and if that matches
323 * we are done and return the mft reference of the inode (i.e.
324 * the inode number together with the sequence number for
325 * consistency checking). We convert it to cpu format before
328 if (ntfs_names_are_equal(uname, uname_len,
329 (uchar_t*)&ie->key.file_name.file_name,
330 ie->key.file_name.file_name_length,
331 CASE_SENSITIVE, vol->upcase, vol->upcase_len)) {
334 * We have a perfect match, so we don't need to care
335 * about having matched imperfectly before.
337 mref = le64_to_cpu(ie->indexed_file);
338 ntfs_attr_close(ia_na);
339 ntfs_attr_put_search_ctx(ctx);
343 * For a case insensitive mount, we also perform a case
344 * insensitive comparison (provided the file name is not in the
345 * POSIX namespace). If the comparison matches, we cache the
346 * mft reference in mref.
348 if (!NVolCaseSensitive(vol) &&
349 ie->key.file_name.file_name_type &&
350 ntfs_names_are_equal(uname, uname_len,
351 (uchar_t*)&ie->key.file_name.file_name,
352 ie->key.file_name.file_name_length,
353 IGNORE_CASE, vol->upcase, vol->upcase_len)) {
354 /* Only one case insensitive matching name allowed. */
356 Dputs("Found already cached mft reference in "
357 "phase 2. Please run chkdsk "
358 "and if that doesn't find any "
359 "errors please report you saw "
361 "linux-ntfs-dev@lists.sf.net.");
364 mref = le64_to_cpu(ie->indexed_file);
367 * Not a perfect match, need to do full blown collation so we
368 * know which way in the B+tree we have to go.
370 rc = ntfs_names_collate(uname, uname_len,
371 (uchar_t*)&ie->key.file_name.file_name,
372 ie->key.file_name.file_name_length, 1,
373 IGNORE_CASE, vol->upcase, vol->upcase_len);
375 * If uname collates before the name of the current entry, there
376 * is definitely no such name in this index but we might need to
377 * descend into the B+tree so we just break out of the loop.
381 /* The names are not equal, continue the search. */
385 * Names match with case insensitive comparison, now try the
386 * case sensitive comparison, which is required for proper
389 rc = ntfs_names_collate(uname, uname_len,
390 (uchar_t*)&ie->key.file_name.file_name,
391 ie->key.file_name.file_name_length, 1,
392 CASE_SENSITIVE, vol->upcase, vol->upcase_len);
398 * Perfect match, this will never happen as the
399 * ntfs_are_names_equal() call will have gotten a match but we
400 * still treat it correctly.
405 * We have finished with this index buffer without success. Check for
406 * the presence of a child node.
408 if (ie->flags & INDEX_ENTRY_NODE) {
409 if ((ia->index.flags & NODE_MASK) == LEAF_NODE) {
410 Dprintf("Index entry with child node found in a leaf "
411 "node in directory inode 0x%Lx.\n",
412 (unsigned long long)dir_ni->mft_no);
416 /* Child node present, descend into it. */
417 vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
419 goto descend_into_child_node;
420 Dprintf("Negative child node vcn in directory inode 0x%Lx.\n",
421 (unsigned long long)dir_ni->mft_no);
425 ntfs_attr_close(ia_na);
426 ntfs_attr_put_search_ctx(ctx);
428 * No child node present, return error code ENOENT, unless we have got
429 * the mft reference of a matching name cached in mref in which case
434 Dputs("Entry not found.");
439 Dputs("Corrupt directory. Aborting lookup.");
441 ntfs_attr_put_search_ctx(ctx);
447 ntfs_attr_close(ia_na);
452 * The little endian Unicode string ".." for ntfs_readdir().
454 static const uchar_t dotdot[3] = { const_cpu_to_le16('.'),
455 const_cpu_to_le16('.'),
456 const_cpu_to_le16('\0') };
459 * More helpers for ntfs_readdir().
463 INDEX_ALLOCATION *ia;
464 } index_union __attribute__ ((__transparent_union__));
467 INDEX_TYPE_ROOT, /* index root */
468 INDEX_TYPE_ALLOCATION, /* index allocation */
474 * ntfs_filldir - ntfs specific filldir method
475 * @dir_ni: ntfs inode of current directory
476 * @pos: current position in directory
477 * @ivcn_bits: log(2) of index vcn size
478 * @index_type: specifies whether @iu is an index root or an index allocation
479 * @iu: index root or index block to which @ie belongs
480 * @ie: current index entry
481 * @dirent: context for filldir callback supplied by the caller
482 * @filldir: filldir callback supplied by the caller
484 * Pass information specifying the current directory entry @ie to the @filldir
487 static inline int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
488 const INDEX_TYPE index_type, index_union iu, INDEX_ENTRY *ie,
489 void *dirent, ntfs_filldir_t filldir)
491 FILE_NAME_ATTR *fn = &ie->key.file_name;
494 /* Advance the position even if going to skip the entry. */
495 if (index_type == INDEX_TYPE_ALLOCATION)
496 *pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(
497 iu.ia->index_block_vcn) << ivcn_bits) +
498 dir_ni->vol->mft_record_size;
499 else /* if (index_type == INDEX_TYPE_ROOT) */
500 *pos = (u8*)ie - (u8*)iu.ir;
501 /* Skip root directory self reference entry. */
502 if (MREF_LE(ie->indexed_file) == FILE_root)
504 if (ie->key.file_name.file_attributes &
505 FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT)
506 dt_type = NTFS_DT_DIR;
508 dt_type = NTFS_DT_REG;
509 return filldir(dirent, fn->file_name, fn->file_name_length,
510 fn->file_name_type, *pos,
511 le64_to_cpu(ie->indexed_file), dt_type);
517 * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode
518 * @ni: ntfs inode whose parent directory to find
520 * Find the parent directory of the ntfs inode @ni. To do this, find the first
521 * file name attribute in the mft record of @ni and return the parent mft
522 * reference from that.
524 * Note this only makes sense for directories, since files can be hard linked
525 * from multiple directories and there is no way for us to tell which one is
528 * Technically directories can have hard links, too, but we consider that as
529 * illegal as Linux/UNIX do not support directory hard links.
531 * Return the mft reference of the parent directory on success or -1 on error
532 * with errno set to the error code.
534 static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
537 ntfs_attr_search_ctx *ctx;
546 ctx = ntfs_attr_get_search_ctx(ni, NULL);
549 if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
550 Dprintf("No file name found in inode 0x%Lx. Corrupt inode.\n",
551 (unsigned long long)ni->mft_no);
554 if (ctx->attr->non_resident) {
555 Dprintf("File name attribute must be resident. Corrupt inode "
556 "0x%Lx.\n", (unsigned long long)ni->mft_no);
559 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
560 le16_to_cpu(ctx->attr->value_offset));
561 if ((u8*)fn + le32_to_cpu(ctx->attr->value_length) >
562 (u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) {
563 Dprintf("Corrupt file name attribute in inode 0x%Lx.\n",
564 (unsigned long long)ni->mft_no);
567 mref = le64_to_cpu(fn->parent_directory);
568 ntfs_attr_put_search_ctx(ctx);
574 ntfs_attr_put_search_ctx(ctx);
580 * ntfs_readdir - read the contents of an ntfs directory
581 * @dir_ni: ntfs inode of current directory
582 * @pos: current position in directory
583 * @dirent: context for filldir callback supplied by the caller
584 * @filldir: filldir callback supplied by the caller
586 * Parse the index root and the index blocks that are marked in use in the
587 * index bitmap and hand each found directory entry to the @filldir callback
588 * supplied by the caller.
590 * Return 0 on success or -1 on error with errno set to the error code.
592 * Note: Index blocks are parsed in ascending vcn order, from which follows
593 * that the directory entries are not returned sorted.
595 int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
596 void *dirent, ntfs_filldir_t filldir)
598 s64 i_size, br, ia_pos, bmp_pos, ia_start;
600 ntfs_attr *ia_na, *bmp_na = NULL;
601 ntfs_attr_search_ctx *ctx = NULL;
605 INDEX_ALLOCATION *ia;
606 int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;
607 u32 index_block_size, index_vcn_size;
608 u8 index_block_size_bits, index_vcn_size_bits;
610 if (!dir_ni || !pos || !filldir) {
615 if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
622 Dprintf("Entering for inode 0x%Lx, *pos 0x%Lx.\n",
623 (unsigned long long)dir_ni->mft_no, (long long)*pos);
625 /* Open the index allocation attribute. */
626 ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, I30, 4);
628 if (errno != ENOENT) {
629 Dprintf("Failed to open index allocation attribute. "
630 "Directory inode 0x%Lx is corrupt or "
632 (unsigned long long)dir_ni->mft_no,
638 i_size = ia_na->data_size;
642 /* Are we at end of dir yet? */
643 if (*pos >= i_size + vol->mft_record_size)
646 /* Emulate . and .. for all directories. */
648 rc = filldir(dirent, dotdot, 1, FILE_NAME_POSIX, *pos,
649 MK_MREF(dir_ni->mft_no,
650 le16_to_cpu(dir_ni->mrec->sequence_number)),
659 parent_mref = ntfs_mft_get_parent_ref(dir_ni);
660 if (parent_mref == -1) {
661 Dprintf("Parent directory not found: %s\n", errno);
665 rc = filldir(dirent, dotdot, 2, FILE_NAME_POSIX, *pos,
666 parent_mref, NTFS_DT_DIR);
672 ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);
676 /* Get the offset into the index root attribute. */
678 /* Find the index root attribute in the mft record. */
679 if (ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
681 Dprintf("Index root attribute missing in directory inode "
682 "0x%Lx.\n", (unsigned long long)dir_ni->mft_no);
685 /* Get to the index root value. */
686 ir = (INDEX_ROOT*)((u8*)ctx->attr +
687 le16_to_cpu(ctx->attr->value_offset));
689 /* Determine the size of a vcn in the directory index. */
690 index_block_size = le32_to_cpu(ir->index_block_size);
691 if (index_block_size < NTFS_SECTOR_SIZE ||
692 index_block_size & (index_block_size - 1)) {
693 Dprintf("Index block size %u is invalid.\n", index_block_size);
696 index_block_size_bits = ffs(index_block_size) - 1;
697 if (vol->cluster_size <= index_block_size) {
698 index_vcn_size = vol->cluster_size;
699 index_vcn_size_bits = vol->cluster_size_bits;
701 index_vcn_size = vol->sector_size;
702 index_vcn_size_bits = vol->sector_size_bits;
705 /* Are we jumping straight into the index allocation attribute? */
706 if (*pos >= vol->mft_record_size) {
707 ntfs_attr_put_search_ctx(ctx);
709 goto skip_index_root;
712 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
713 /* The first index entry. */
714 ie = (INDEX_ENTRY*)((u8*)&ir->index +
715 le32_to_cpu(ir->index.entries_offset));
717 * Loop until we exceed valid memory (corruption case) or until we
718 * reach the last entry or until filldir tells us it has had enough
719 * or signals an error (both covered by the rc test).
721 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
722 Dprintf("In index root, offset 0x%x.\n", (u8*)ie - (u8*)ir);
724 if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
725 sizeof(INDEX_ENTRY_HEADER) > index_end ||
726 (u8*)ie + le16_to_cpu(ie->key_length) >
729 /* The last entry cannot contain a name. */
730 if (ie->flags & INDEX_ENTRY_END)
732 /* Skip index root entry if continuing previous readdir. */
733 if (ir_pos > (u8*)ie - (u8*)ir)
736 * Submit the directory entry to ntfs_filldir(), which will
737 * invoke the filldir() callback as appropriate.
739 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
740 INDEX_TYPE_ROOT, ir, ie, dirent, filldir);
742 ntfs_attr_put_search_ctx(ctx);
747 ntfs_attr_put_search_ctx(ctx);
750 /* If there is no index allocation attribute we are finished. */
754 /* Advance *pos to the beginning of the index allocation. */
755 *pos = vol->mft_record_size;
762 /* Allocate a buffer for the current index block. */
763 ia = (INDEX_ALLOCATION*)malloc(index_block_size);
765 Dperror("Failed to allocate buffer for index block");
769 bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, I30, 4);
771 Dperror("Failed to open index bitmap attribute");
775 /* Get the offset into the index allocation attribute. */
776 ia_pos = *pos - vol->mft_record_size;
778 bmp_pos = ia_pos >> index_block_size_bits;
779 if (bmp_pos >> 3 >= bmp_na->data_size) {
780 Dputs("Current index position exceeds index bitmap size.");
784 bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096);
785 bmp = (u8*)malloc(bmp_buf_size);
787 Dperror("Failed to allocate bitmap buffer");
791 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
792 if (br != bmp_buf_size) {
795 Dperror("Failed to read from inde bitmap attribute");
800 /* If the index block is not in use find the next one that is. */
801 while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) {
802 find_next_index_buffer:
805 /* If we have reached the end of the bitmap, we are done. */
806 if (bmp_pos >> 3 >= bmp_na->data_size)
808 ia_pos = bmp_pos << index_block_size_bits;
809 if (bmp_buf_pos >> 3 < bmp_buf_size)
811 /* Read next chunk from the index bitmap. */
812 if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size)
813 bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3);
814 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
815 if (br != bmp_buf_size) {
818 Dperror("Failed to read from inde bitmap attribute");
823 Dprintf("Handling index block 0x%Lx.", (long long)bmp_pos);
825 /* Read the index block starting at bmp_pos. */
826 br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1,
827 index_block_size, ia);
831 Dperror("Failed to read index block");
835 ia_start = ia_pos & ~(s64)(index_block_size - 1);
836 if (sle64_to_cpu(ia->index_block_vcn) != ia_start >>
837 index_vcn_size_bits) {
838 Dprintf("Actual VCN (0x%Lx) of index buffer is different from "
839 "expected VCN (0x%Lx) in inode 0x%Lx.\n",
840 (long long)sle64_to_cpu(ia->index_block_vcn),
841 (long long)ia_start >> index_vcn_size_bits,
842 (unsigned long long)dir_ni->mft_no);
845 if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) {
846 Dprintf("Index buffer (VCN 0x%Lx) of directory inode 0x%Lx "
847 "has a size (%u) differing from the directory "
848 "specified size (%u).\n",
849 (long long)ia_start >> index_vcn_size_bits,
850 (unsigned long long)dir_ni->mft_no,
851 le32_to_cpu(ia->index.allocated_size) + 0x18,
855 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
856 if (index_end > (u8*)ia + index_block_size) {
857 Dprintf("Size of index buffer (VCN 0x%Lx) of directory inode "
858 "0x%Lx exceeds maximum size.\n",
859 (long long)ia_start >> index_vcn_size_bits,
860 (unsigned long long)dir_ni->mft_no);
863 /* The first index entry. */
864 ie = (INDEX_ENTRY*)((u8*)&ia->index +
865 le32_to_cpu(ia->index.entries_offset));
867 * Loop until we exceed valid memory (corruption case) or until we
868 * reach the last entry or until ntfs_filldir tells us it has had
869 * enough or signals an error (both covered by the rc test).
871 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
872 Dprintf("In index allocation, offset 0x%Lx.\n",
873 (long long)ia_start + ((u8*)ie - (u8*)ia));
875 if ((u8*)ie < (u8*)ia || (u8*)ie +
876 sizeof(INDEX_ENTRY_HEADER) > index_end ||
877 (u8*)ie + le16_to_cpu(ie->key_length) >
879 Dprintf("Index entry out of bounds in directory inode "
881 (unsigned long long)dir_ni->mft_no);
884 /* The last entry cannot contain a name. */
885 if (ie->flags & INDEX_ENTRY_END)
887 /* Skip index entry if continuing previous readdir. */
888 if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
891 * Submit the directory entry to ntfs_filldir(), which will
892 * invoke the filldir() callback as appropriate.
894 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
895 INDEX_TYPE_ALLOCATION, ia, ie, dirent, filldir);
899 goto find_next_index_buffer;
901 /* We are finished, set *pos to EOD. */
902 *pos = i_size + vol->mft_record_size;
905 ntfs_attr_close(bmp_na);
907 ntfs_attr_close(ia_na);
910 Dprintf("EOD, *pos 0x%Lx, returning 0.\n", (long long)*pos);
912 Dprintf("filldir returned %i, *pos 0x%Lx, returning 0.\n",
913 rc, (long long)*pos);
920 Dprintf("%s() failed.\n", __FUNCTION__);
922 ntfs_attr_put_search_ctx(ctx);
924 ntfs_attr_close(bmp_na);
926 ntfs_attr_close(ia_na);