aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <pcacjr@gmail.com>2011-07-08 01:59:33 +0000
committerPaulo Alcantara <pcacjr@gmail.com>2011-09-07 07:19:06 +0000
commit3db0b76af102e3306c9a3a804fedb4b57670251b (patch)
tree9b64759125714ad741f488c93e67c1adae882761
parentab60ce09495d2ff036255548f94dcf9b969d841f (diff)
downloadsyslinux-3db0b76af102e3306c9a3a804fedb4b57670251b.tar.gz
syslinux-3db0b76af102e3306c9a3a804fedb4b57670251b.tar.xz
syslinux-3db0b76af102e3306c9a3a804fedb4b57670251b.zip
ntfs: implement ntfs_iget_root()
Return an allocated inode of the respective root directory along with its information. Signed-off-by: Paulo Alcantara <pcacjr@gmail.com>
-rw-r--r--core/fs/ntfs/ntfs.c121
-rw-r--r--core/fs/ntfs/ntfs.h2
2 files changed, 122 insertions, 1 deletions
diff --git a/core/fs/ntfs/ntfs.c b/core/fs/ntfs/ntfs.c
index e476fab0..f4adf6db 100644
--- a/core/fs/ntfs/ntfs.c
+++ b/core/fs/ntfs/ntfs.c
@@ -69,6 +69,125 @@ static inline const void *get_right_block(struct fs_info *fs,
return get_cache(fs->fs_dev, NTFS_SB(fs)->mft + block);
}
+static MFT_RECORD *mft_record_lookup(uint32_t file, struct fs_info *fs,
+ sector_t *block)
+{
+ const uint8_t *data;
+ MFT_RECORD *mrec;
+
+ for_each_mft_record(fs, data, *block) {
+ mrec = (MFT_RECORD *)data;
+ if (mrec->mft_record_no == file)
+ return mrec;
+ }
+
+ return NULL;
+}
+
+static ATTR_RECORD *attr_lookup(uint32_t type, const MFT_RECORD *mrec)
+{
+ ATTR_RECORD *attr;
+
+ /* sanity check */
+ if (!mrec || type == NTFS_AT_END)
+ return NULL;
+
+ attr = (ATTR_RECORD *)((uint8_t *)mrec + mrec->attrs_offset);
+ /* walk through the file attribute records */
+ for (;; attr = (ATTR_RECORD *)((uint8_t *)attr + attr->len)) {
+ if (attr->type == NTFS_AT_END)
+ return NULL;
+
+ if (attr->type == type)
+ break;
+ }
+
+ return attr;
+}
+
+static int index_inode_setup(struct fs_info *fs, unsigned long mft_no,
+ struct inode *inode)
+{
+ MFT_RECORD *mrec;
+ sector_t block = 0;
+ ATTR_RECORD *attr;
+ uint32_t len;
+ INDEX_ROOT *ir;
+ uint32_t clust_size;
+
+ mrec = mft_record_lookup(mft_no, fs, &block);
+ if (!mrec) {
+ printf("No MFT record found!\n");
+ goto out;
+ }
+
+ NTFS_PVT(inode)->mft_no = mft_no;
+ NTFS_PVT(inode)->seq_no = mrec->seq_no;
+
+ NTFS_PVT(inode)->start_cluster = block >> NTFS_SB(fs)->clust_shift;
+ NTFS_PVT(inode)->here = block;
+
+ attr = attr_lookup(NTFS_AT_INDEX_ROOT, mrec);
+ if (!attr) {
+ printf("No attribute found!\n");
+ goto out;
+ }
+
+ NTFS_PVT(inode)->type = attr->type;
+
+ /* note: INDEX_ROOT is always resident */
+ ir = (INDEX_ROOT *)((uint8_t *)attr +
+ attr->data.resident.value_offset);
+ len = attr->data.resident.value_len;
+ if ((uint8_t *)ir + len > (uint8_t *)mrec + NTFS_SB(fs)->mft_record_size) {
+ printf("Index is corrupt!\n");
+ goto out;
+ }
+
+ NTFS_PVT(inode)->itype.index.collation_rule = ir->collation_rule;
+ NTFS_PVT(inode)->itype.index.block_size = ir->index_block_size;
+ NTFS_PVT(inode)->itype.index.block_size_shift =
+ ilog2(NTFS_PVT(inode)->itype.index.block_size);
+
+ /* determine the size of a vcn in the index */
+ clust_size = NTFS_PVT(inode)->itype.index.block_size;
+ if (NTFS_SB(fs)->clust_size <= clust_size) {
+ NTFS_PVT(inode)->itype.index.vcn_size = NTFS_SB(fs)->clust_size;
+ NTFS_PVT(inode)->itype.index.vcn_size_shift = NTFS_SB(fs)->clust_shift;
+ } else {
+ NTFS_PVT(inode)->itype.index.vcn_size = BLOCK_SIZE(fs);
+ NTFS_PVT(inode)->itype.index.vcn_size_shift = BLOCK_SHIFT(fs);
+ }
+
+ inode->mode = DT_DIR;
+
+ return 0;
+
+out:
+ return -1;
+}
+
+static struct inode *ntfs_iget_root(struct fs_info *fs)
+{
+ struct inode *inode = new_ntfs_inode(fs);
+ int err;
+
+ inode->fs = fs;
+
+ err = index_inode_setup(fs, FILE_root, inode);
+ if (err)
+ goto free_out;
+
+ NTFS_PVT(inode)->start = NTFS_PVT(inode)->here;
+
+ return inode;
+
+free_out:
+ free(inode);
+
+ return NULL;
+}
+
/* Initialize the filesystem metadata and return block size in bits */
static int ntfs_fs_init(struct fs_info *fs)
{
@@ -124,7 +243,7 @@ const struct fs_ops ntfs_fs_ops = {
.mangle_name = NULL,
.load_config = NULL,
.readdir = NULL,
- .iget_root = NULL,
+ .iget_root = ntfs_iget_root,
.iget = NULL,
.next_extent = NULL,
};
diff --git a/core/fs/ntfs/ntfs.h b/core/fs/ntfs/ntfs.h
index 9c7de0f9..e42ceb02 100644
--- a/core/fs/ntfs/ntfs.h
+++ b/core/fs/ntfs/ntfs.h
@@ -561,4 +561,6 @@ static inline struct ntfs_sb_info *NTFS_SB(struct fs_info *fs)
return fs->fs_info;
}
+#define NTFS_PVT(i) ((struct ntfs_inode *)((i)->pvt))
+
#endif /* _NTFS_H_ */