aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <pcacjr@gmail.com>2011-08-02 00:54:54 +0000
committerPaulo Alcantara <pcacjr@gmail.com>2011-09-11 04:09:58 +0000
commit927138a28973167ccd427e734b952e8f99fe7829 (patch)
tree9c228276ad21d7c11d930fa6fdb3f238db37ab21
parent0b287553a124209d8759da0385d8e43f2c08dadb (diff)
downloadsyslinux-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.c125
-rw-r--r--core/fs/ntfs/ntfs.h3
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 */