diff options
author | Paulo Alcantara <pcacjr@gmail.com> | 2011-08-02 00:54:54 +0000 |
---|---|---|
committer | Paulo Alcantara <pcacjr@gmail.com> | 2011-09-11 04:09:58 +0000 |
commit | 927138a28973167ccd427e734b952e8f99fe7829 (patch) | |
tree | 9c228276ad21d7c11d930fa6fdb3f238db37ab21 | |
parent | 0b287553a124209d8759da0385d8e43f2c08dadb (diff) | |
download | syslinux-927138a28973167ccd427e734b952e8f99fe7829.tar.gz syslinux-927138a28973167ccd427e734b952e8f99fe7829.tar.xz syslinux-927138a28973167ccd427e734b952e8f99fe7829.zip |
ntfs: I think ntfs_readdir() is now fixed
gerth and sha0, you need to test it! :-)
Signed-off-by: Paulo Alcantara <pcacjr@gmail.com>
-rw-r--r-- | core/fs/ntfs/ntfs.c | 125 | ||||
-rw-r--r-- | core/fs/ntfs/ntfs.h | 3 |
2 files changed, 77 insertions, 51 deletions
diff --git a/core/fs/ntfs/ntfs.c b/core/fs/ntfs/ntfs.c index 71940d66..29e15052 100644 --- a/core/fs/ntfs/ntfs.c +++ b/core/fs/ntfs/ntfs.c @@ -334,6 +334,8 @@ static int index_inode_setup(struct fs_info *fs, block_t start_block, NTFS_PVT(inode)->itype.index.vcn_size = BLOCK_SIZE(fs); NTFS_PVT(inode)->itype.index.vcn_size_shift = BLOCK_SHIFT(fs); } + + NTFS_PVT(inode)->in_idx_root = true; } else if (d_type == DT_REG) { /* file stuff */ dprintf("Got a file.\n"); attr = attr_lookup(NTFS_AT_DATA, mrec); @@ -656,6 +658,7 @@ static int ntfs_readdir(struct file *file, struct dirent *dirent) block_t block; ATTR_RECORD *attr; INDEX_ROOT *ir; + uint32_t count; int len; INDEX_ENTRY *ie = NULL; uint8_t *data; @@ -689,16 +692,19 @@ static int ntfs_readdir(struct file *file, struct dirent *dirent) if ((uint8_t *)ir + len > (uint8_t *)mrec + NTFS_SB(fs)->mft_record_size) goto index_err; - if (!file->offset) { + if (!file->offset && NTFS_PVT(inode)->in_idx_root) { file->offset = (uint32_t)((uint8_t *)&ir->index + ir->index.entries_offset); - NTFS_PVT(inode)->in_idx_root = true; } if (NTFS_PVT(inode)->in_idx_root) { ie = (INDEX_ENTRY *)(uint8_t *)file->offset; if (ie->flags & INDEX_ENTRY_END) { file->offset = 0; + NTFS_PVT(inode)->in_idx_root = false; + NTFS_PVT(inode)->idx_blocks_count = 1; + NTFS_PVT(inode)->entries_count = 0; + NTFS_PVT(inode)->last_vcn = 0; goto descend_into_child_node; } @@ -707,8 +713,6 @@ static int ntfs_readdir(struct file *file, struct dirent *dirent) } descend_into_child_node: - NTFS_PVT(inode)->in_idx_root = false; - if (!(ie->flags & INDEX_ENTRY_NODE)) goto out; @@ -722,67 +726,82 @@ descend_into_child_node: } attr_len = (uint8_t *)attr + attr->len; + +next_run: stream = mapping_chunk_init(attr, &chunk, &offset); - do { + count = NTFS_PVT(inode)->idx_blocks_count; + while (count--) { err = parse_data_run(stream, &offset, attr_len, &chunk); - if (err) - break; + if (err) { + printf("Error on parsing data runs.\n"); + goto out; + } if (chunk.flags & MAP_UNALLOCATED) - continue; - - if (chunk.flags & MAP_ALLOCATED) { - dprintf("%d cluster(s) starting at 0x%X\n", chunk.len, chunk.lcn); + break; + if (chunk.flags & MAP_END) + goto out; + } - vcn = 0; - lcn = chunk.lcn; - while (vcn < chunk.len) { - block = ((lcn + vcn) << NTFS_SB(fs)->clust_shift) << - SECTOR_SHIFT(fs) >> BLOCK_SHIFT(fs); + if (chunk.flags & MAP_UNALLOCATED) { + NTFS_PVT(inode)->idx_blocks_count++; + goto next_run; + } - data = (uint8_t *)get_cache(fs->fs_dev, block); - if (!data) { - printf("get_cache() returned NULL.\n"); - goto not_found; - } +next_vcn: + vcn = NTFS_PVT(inode)->last_vcn; + if (vcn >= chunk.len) { + NTFS_PVT(inode)->last_vcn = 0; + NTFS_PVT(inode)->idx_blocks_count++; + goto next_run; + } - err = fixups_writeback(fs, (NTFS_RECORD *)data); - if (err) - goto not_found; + lcn = chunk.lcn; + block = ((lcn + vcn) << NTFS_SB(fs)->clust_shift) << SECTOR_SHIFT(fs) >> + BLOCK_SHIFT(fs); - iblock = (INDEX_BLOCK *)data; - if (iblock->magic != NTFS_MAGIC_INDX) { - printf("Not a valid INDX record.\n"); - goto not_found; - } + data = (uint8_t *)get_cache(fs->fs_dev, block); + if (!data) { + printf("get_cache() returned NULL.\n"); + goto not_found; + } - ie = (INDEX_ENTRY *)((uint8_t *)&iblock->index + - iblock->index.entries_offset); - for (;; ie = (INDEX_ENTRY *)((uint8_t *)ie + ie->len)) { - /* bounds checks */ - if ((uint8_t *)ie < (uint8_t *)iblock || (uint8_t *)ie + - sizeof(INDEX_ENTRY_HEADER) > - (uint8_t *)&iblock->index + iblock->index.index_len || - (uint8_t *)ie + ie->len > - (uint8_t *)&iblock->index + iblock->index.index_len) - goto index_err; + err = fixups_writeback(fs, (NTFS_RECORD *)data); + if (err) + goto not_found; - /* last entry cannot contain a key */ - if (ie->flags & INDEX_ENTRY_END) - break; + iblock = (INDEX_BLOCK *)data; + if (iblock->magic != NTFS_MAGIC_INDX) { + printf("Not a valid INDX record.\n"); + goto not_found; + } - if (file->offset < (uint32_t)(uint8_t *)ie) { - file->offset = (uint32_t)(uint8_t *)ie; - goto done; - } - } + ie = (INDEX_ENTRY *)((uint8_t *)&iblock->index + + iblock->index.entries_offset); + count = NTFS_PVT(inode)->entries_count; + for ( ; count--; ie = (INDEX_ENTRY *)((uint8_t *)ie + ie->len)) { + /* bounds checks */ + if ((uint8_t *)ie < (uint8_t *)iblock || (uint8_t *)ie + + sizeof(INDEX_ENTRY_HEADER) > + (uint8_t *)&iblock->index + iblock->index.index_len || + (uint8_t *)ie + ie->len > + (uint8_t *)&iblock->index + iblock->index.index_len) + goto index_err; - vcn++; /* go to the next VCN */ - } + /* last entry cannot contain a key */ + if (ie->flags & INDEX_ENTRY_END) { + NTFS_PVT(inode)->last_vcn++; + NTFS_PVT(inode)->entries_count = 0; + goto next_vcn; } - } while (!(chunk.flags & MAP_END)); + } + + NTFS_PVT(inode)->entries_count++; + goto done; out: + NTFS_PVT(inode)->in_idx_root = true; + return -1; done: @@ -792,7 +811,11 @@ done: len = ntfs_cvt_filename(filename, ie); dirent->d_reclen = offsetof(struct dirent, d_name) + len + 1; - block = NTFS_SB(fs)->mft_block; + if (NTFS_PVT(inode)->mft_no == FILE_root) + block = 0; + else + block = NTFS_SB(fs)->mft_block; + mrec = mft_record_lookup(ie->data.dir.indexed_file, fs, &block); if (!mrec) { printf("No MFT record found.\n"); diff --git a/core/fs/ntfs/ntfs.h b/core/fs/ntfs/ntfs.h index 5003bc4e..73569362 100644 --- a/core/fs/ntfs/ntfs.h +++ b/core/fs/ntfs/ntfs.h @@ -72,6 +72,9 @@ struct ntfs_inode { uint32_t type; /* Attribute type of this inode */ uint8_t non_resident; bool in_idx_root; + uint32_t idx_blocks_count; + uint32_t entries_count; + int64_t last_vcn; union { /* Non-resident $DATA attribute */ struct { /* Used only if non_resident flags isn't set */ uint32_t offset; /* Data offset */ |