[syslinux:master] ntfs: heh :-)

syslinux-bot for Paulo Alcantara pcacjr at gmail.com
Sat Dec 17 20:54:58 PST 2011


Commit-ID:  59352ea089659392c7076184f03cc0665e52c7b6
Gitweb:     http://www.syslinux.org/commit/59352ea089659392c7076184f03cc0665e52c7b6
Author:     Paulo Alcantara <pcacjr at gmail.com>
AuthorDate: Mon, 25 Jul 2011 00:24:24 +0000
Committer:  Paulo Alcantara <pcacjr at gmail.com>
CommitDate: Wed, 7 Sep 2011 07:19:07 +0000

ntfs: heh :-)

Signed-off-by: Paulo Alcantara <pcacjr at gmail.com>

---
 core/fs/ntfs/ntfs.c |  187 ++++++++++++++++++++++++++-------------------------
 core/fs/ntfs/ntfs.h |    5 +-
 2 files changed, 98 insertions(+), 94 deletions(-)

diff --git a/core/fs/ntfs/ntfs.c b/core/fs/ntfs/ntfs.c
index 2702f01..f37f3d4 100644
--- a/core/fs/ntfs/ntfs.c
+++ b/core/fs/ntfs/ntfs.c
@@ -28,14 +28,6 @@
 #include "codepage.h"
 #include "ntfs.h"
 
-#define for_each_mft_record(fs, data, block) \
-    for ((data) = get_right_block((fs), (block)); \
-            (block) < NTFS_SB((fs))->mft_size && \
-            ((const MFT_RECORD *)(data))->magic == NTFS_MAGIC_FILE; \
-            (block) += ((const MFT_RECORD *)(data))->bytes_allocated >> \
-                                                        BLOCK_SHIFT((fs)), \
-            (data) = get_right_block((fs), (block)))
-
 /* Check if there are specific zero fields in an NTFS boot sector */
 static inline int ntfs_check_zero_fields(const struct ntfs_bpb *sb)
 {
@@ -66,23 +58,36 @@ static inline struct inode *new_ntfs_inode(struct fs_info *fs)
 static inline const void *get_right_block(struct fs_info *fs,
                                                         block_t block)
 {
-    return get_cache(fs->fs_dev, NTFS_SB(fs)->mft + block);
+    return get_cache(fs->fs_dev, NTFS_SB(fs)->mft_block + 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;
+static MFT_RECORD * mft_record_lookup(
+    uint32_t file,
+    struct fs_info * fs,
+    block_t * block
+  ) {
+    int offset = 0;
+    const uint8_t * data;
+    MFT_RECORD * mrec;
+
+    goto jump_in;
+    while (1) {
+        mrec = (MFT_RECORD *) (data + offset);
+        if (mrec->magic != NTFS_MAGIC_FILE)
+          break;
         if (mrec->mft_record_no == file)
-            return mrec;
-    }
+          return mrec;
+        offset += mrec->bytes_allocated;
+        if (offset >= BLOCK_SIZE(fs)) {
+            ++*block;
+            offset -= BLOCK_SIZE(fs);
+            jump_in:
+            data = get_right_block(fs, *block);
+          }
+      }
 
     return NULL;
-}
+  }
 
 static ATTR_RECORD *attr_lookup(uint32_t type, const MFT_RECORD *mrec)
 {
@@ -109,7 +114,7 @@ static bool ntfs_match_longname(const char *str, unsigned long mft_no,
                                     struct fs_info *fs)
 {
     MFT_RECORD *mrec;
-    sector_t block = 0;
+    block_t block = 0;
     ATTR_RECORD *attr;
     FILE_NAME_ATTR *fn;
     uint8_t len;
@@ -133,7 +138,7 @@ static bool ntfs_match_longname(const char *str, unsigned long mft_no,
     len = fn->file_name_len;
     match = fn->file_name;
 
-    dprintf("Matching: %s\n", str);
+    printf("Matching: %s\n", str);
 
     while (len) {
         cp = *match++;
@@ -268,13 +273,13 @@ static enum dirent_type get_inode_mode(MFT_RECORD *mrec)
 
     attr = attr_lookup(NTFS_AT_FILENAME, mrec);
     if (!attr) {
-        dprintf("No attribute found!\n");
+        printf("No attribute found!\n");
         return DT_UNKNOWN;
     }
 
     fn = (FILE_NAME_ATTR *)((uint8_t *)attr +
                                 attr->data.resident.value_offset);
-    dprintf("File attributes:        0x%X\n", fn->file_attrs);
+    printf("File attributes:        0x%X\n", fn->file_attrs);
 
     dir_mask = NTFS_FILE_ATTR_ARCHIVE |
                 NTFS_FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT;
@@ -287,9 +292,9 @@ static enum dirent_type get_inode_mode(MFT_RECORD *mrec)
     root = fn->file_attrs & ~root_mask;
     file = fn->file_attrs & ~file_mask;
 
-    dprintf("dir = 0x%X\n", dir);
-    dprintf("root= 0x%X\n", root);
-    dprintf("file = 0x%X\n", file);
+    printf("dir = 0x%X\n", dir);
+    printf("root= 0x%X\n", root);
+    printf("file = 0x%X\n", file);
     if (((!dir && root) || (!dir && !root)) && !file)
         infile = true;
 
@@ -300,7 +305,7 @@ static int index_inode_setup(struct fs_info *fs, unsigned long mft_no,
                                 struct inode *inode)
 {
     MFT_RECORD *mrec;
-    sector_t block = 0;
+    block_t block = 0;
     ATTR_RECORD *attr;
     enum dirent_type d_type;
     uint32_t len;
@@ -314,7 +319,7 @@ static int index_inode_setup(struct fs_info *fs, unsigned long mft_no,
 
     mrec = mft_record_lookup(mft_no, fs, &block);
     if (!mrec) {
-        dprintf("No MFT record found!\n");
+        printf("No MFT record found!\n");
         goto out;
     }
 
@@ -326,15 +331,15 @@ static int index_inode_setup(struct fs_info *fs, unsigned long mft_no,
 
     d_type = get_inode_mode(mrec);
     if (d_type == DT_UNKNOWN) {
-        dprintf("Failed on determining inode's mode\n");
+        printf("Failed on determining inode's mode\n");
         goto out;
     }
 
     if (d_type == DT_DIR) {    /* directory stuff */
-        dprintf("Got a directory.\n");
+        printf("Got a directory.\n");
         attr = attr_lookup(NTFS_AT_INDEX_ROOT, mrec);
         if (!attr) {
-            dprintf("No attribute found!\n");
+            printf("No attribute found!\n");
             goto out;
         }
 
@@ -344,7 +349,7 @@ static int index_inode_setup(struct fs_info *fs, unsigned long mft_no,
         len = attr->data.resident.value_len;
         if ((uint8_t *)ir + len > (uint8_t *)mrec +
                         NTFS_SB(fs)->mft_record_size) {
-            dprintf("Corrupt index\n");
+            printf("Corrupt index\n");
             goto out;
         }
 
@@ -364,10 +369,10 @@ static int index_inode_setup(struct fs_info *fs, unsigned long mft_no,
             NTFS_PVT(inode)->itype.index.vcn_size_shift = BLOCK_SHIFT(fs);
         }
     } else if (d_type == DT_REG) {        /* file stuff */
-        dprintf("Got a file.\n");
+        printf("Got a file.\n");
         attr = attr_lookup(NTFS_AT_DATA, mrec);
         if (!attr) {
-            dprintf("No attribute found!\n");
+            printf("No attribute found!\n");
             goto out;
         }
 
@@ -427,7 +432,7 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
 {
     struct fs_info *fs = dir->fs;
     MFT_RECORD *mrec;
-    sector_t block;
+    block_t block;
     ATTR_RECORD *attr;
     INDEX_ROOT *ir;
     uint32_t len;
@@ -435,7 +440,6 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
     uint8_t vcn_count;
     INDEX_BLOCK *iblock;
     int64_t vcn;
-    unsigned block_count;
     uint8_t *stream;
     uint32_t offset;
     uint8_t *attr_len;
@@ -444,16 +448,16 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
     struct inode *inode;
 
     block = NTFS_PVT(dir)->start;
-    dprintf("index_lookup() - mft record number: %d\n", NTFS_PVT(dir)->mft_no);
+    printf("index_lookup() - mft record number: %d\n", NTFS_PVT(dir)->mft_no);
     mrec = mft_record_lookup(NTFS_PVT(dir)->mft_no, fs, &block);
     if (!mrec) {
-        dprintf("No MFT record found!\n");
+        printf("No MFT record found!\n");
         goto out;
     }
 
     attr = attr_lookup(NTFS_AT_INDEX_ROOT, mrec);
     if (!attr) {
-        dprintf("No attribute found!\n");
+        printf("No attribute found!\n");
         goto out;
     }
 
@@ -478,20 +482,20 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
         /* last entry cannot contain a key. it can however contain
          * a pointer to a child node in the B+ tree so we just break out
          */
-        dprintf("(0) ie->flags:          0x%X\n", ie->flags);
+        printf("(0) ie->flags:          0x%X\n", ie->flags);
         if (ie->flags & INDEX_ENTRY_END)
             break;
 
         if (ntfs_match_longname(dname, ie->data.dir.indexed_file, fs)) {
-            dprintf("Filename matches up!\n");
-            dprintf("MFT record number = %d\n", ie->data.dir.indexed_file);
+            printf("Filename matches up!\n");
+            printf("MFT record number = %d\n", ie->data.dir.indexed_file);
             goto found;
         }
     }
 
     /* check for the presence of a child node */
     if (!(ie->flags & INDEX_ENTRY_NODE)) {
-        dprintf("No child node, aborting...\n");
+        printf("No child node, aborting...\n");
         goto out;
     }
 
@@ -499,12 +503,12 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
 
     attr = attr_lookup(NTFS_AT_INDEX_ALLOCATION, mrec);
     if (!attr) {
-        dprintf("No attribute found!\n");
+        printf("No attribute found!\n");
         goto out;
     }
 
     if (!attr->non_resident) {
-        dprintf("WTF ?! $INDEX_ALLOCATION isn't really resident.\n");
+        printf("WTF ?! $INDEX_ALLOCATION isn't really resident.\n");
         goto out;
     }
 
@@ -528,24 +532,21 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
             break;
 
         if (chunk.flags & MAP_ALLOCATED) {
-            dprintf("%d cluster(s) starting at 0x%X\n", chunk.vcn_len,
+            printf("%d cluster(s) starting at 0x%X\n", chunk.vcn_len,
                     chunk.cur_lcn);
 
             vcn_count = 0;
-            vcn = chunk.cur_vcn;
+            vcn = chunk.cur_vcn;        /* HUMMMMMMM!!!!! */
             while (vcn_count++ < chunk.vcn_len) {
-                block = (chunk.cur_lcn + vcn) << NTFS_SB(fs)->clust_shift;
+                block = ((chunk.cur_lcn + vcn) << NTFS_SB(fs)->clust_shift) <<
+                        SECTOR_SHIFT(fs) >> BLOCK_SHIFT(fs);
+
                 iblock = (INDEX_BLOCK *)get_cache(fs->fs_dev, block);
                 if (iblock->magic != NTFS_MAGIC_INDX) {
-                    dprintf("Not a valid INDX record\n");
+                    printf("Not a valid INDX record\n");
                     goto out;
                 }
 
-                /* get the index entries region cached */
-                block_count = iblock->index.allocated_size >> BLOCK_SHIFT(fs);
-                while (block_count--)
-                    (void)get_cache(fs->fs_dev, ++block);
-
                 ie = (INDEX_ENTRY *)((uint8_t *)&iblock->index +
                                             iblock->index.entries_offset);
                 for (;; ie = (INDEX_ENTRY *)((uint8_t *)ie + ie->len)) {
@@ -557,17 +558,17 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
                         (uint8_t *)&iblock->index + iblock->index.index_len)
                         goto index_err;
 
-                    dprintf("Entry length 0x%x (%d)\n", ie->len, ie->len);
+                    printf("Entry length 0x%x (%d)\n", ie->len, ie->len);
 
                     /* last entry cannot contain a key */
-                    dprintf("(1) ie->flags:          0x%X\n", ie->flags);
+                    printf("(1) ie->flags:          0x%X\n", ie->flags);
                     if (ie->flags & INDEX_ENTRY_END)
                         break;
 
                     if (ntfs_match_longname(dname, ie->data.dir.indexed_file,
                                             fs)) {
-                        dprintf("Filename matches up!\n");
-                        dprintf("MFT record number = %d\n",
+                        printf("Filename matches up!\n");
+                        printf("MFT record number = %d\n",
                                 ie->data.dir.indexed_file);
                         goto found;
                     }
@@ -579,13 +580,13 @@ static struct inode *index_lookup(const char *dname, struct inode *dir)
     }
 
 not_found:
-    dprintf("Index not found\n");
+    printf("Index not found\n");
 
 out:
     return NULL;
 
 found:
-    dprintf("--------------- Found index -------------------\n");
+    printf("--------------- Found index -------------------\n");
     inode = new_ntfs_inode(fs);
     err = index_inode_setup(fs, ie->data.dir.indexed_file, inode);
     if (err) {
@@ -596,7 +597,7 @@ found:
     return inode;
 
 index_err:
-    dprintf("Corrupt index. Aborting lookup...\n");
+    printf("Corrupt index. Aborting lookup...\n");
     goto out;
 }
 
@@ -648,19 +649,21 @@ static int ntfs_next_extent(struct inode *inode, uint32_t lstart)
     uint32_t tcluster;
     const uint32_t cluster_bytes = UINT32_C(1) << sbi->clust_byte_shift;
     sector_t pstart;
-    const uint32_t blk_size = BLOCK_SIZE(fs);
-    const uint32_t blk_shift = BLOCK_SHIFT(fs);
+    const uint32_t sec_size = SECTOR_SIZE(fs);
+    const uint32_t sec_shift = SECTOR_SHIFT(fs);
 
     tcluster = (inode->size + cluster_bytes - 1) >> sbi->clust_byte_shift;
     if (mcluster >= tcluster)
         goto out;       /* Requested cluster beyond end of file */
 
-    if (!NTFS_PVT(inode)->non_resident)
-        pstart = sbi->mft + NTFS_PVT(inode)->here;
-    else
+    if (!NTFS_PVT(inode)->non_resident) {
+        pstart = sbi->mft_block + NTFS_PVT(inode)->here;
+        pstart <<= BLOCK_SHIFT(fs) >> sec_shift;
+    } else {
         pstart = NTFS_PVT(inode)->data.non_resident.lcn << sbi->clust_shift;
+    }
 
-    inode->next_extent.len = (inode->size + blk_size - 1) >> blk_shift;
+    inode->next_extent.len = (inode->size + sec_size - 1) >> sec_shift;
     inode->next_extent.pstart = pstart;
 
     return 0;
@@ -707,7 +710,7 @@ static uint32_t ntfs_getfssec(struct file *file, char *buf, int sectors,
     struct inode *inode = file->inode;
     uint8_t non_resident;
     struct fs_info *fs = file->fs;
-    sector_t block;
+    block_t block = 0;
     MFT_RECORD *mrec;
     ATTR_RECORD *attr;
     char *data;
@@ -719,10 +722,9 @@ static uint32_t ntfs_getfssec(struct file *file, char *buf, int sectors,
         return ret;
 
     if (!non_resident) {
-        block = NTFS_SB(file->fs)->mft + NTFS_PVT(inode)->here;
-
-        mrec = (MFT_RECORD *)get_cache(fs->fs_dev, block);
-        if (mrec->magic != NTFS_MAGIC_FILE) {
+        printf("mft_no:     %d\n", NTFS_PVT(inode)->mft_no);
+        mrec = mft_record_lookup(NTFS_PVT(inode)->mft_no, fs, &block);
+        if (!mrec) {
             printf("No MFT record found!\n");
             goto out;
         }
@@ -754,23 +756,21 @@ static int ntfs_readdir(struct file *file, struct dirent *dirent)
     struct fs_info *fs = file->fs;
     struct inode *inode = file->inode;
     MFT_RECORD *mrec;
-    sector_t block = 0;
+    block_t block = 0;
     ATTR_RECORD *attr;
     FILE_NAME_ATTR *fn;
     char filename[NTFS_MAX_FILE_NAME_LEN + 1];
     int len;
 
-    printf("here!\n");
-
     mrec = mft_record_lookup(NTFS_PVT(inode)->mft_no, fs, &block);
     if (!mrec) {
-        dprintf("No MFT record found!\n");
+        printf("No MFT record found!\n");
         goto out;
     }
 
     attr = attr_lookup(NTFS_AT_FILENAME, mrec);
     if (!attr) {
-        dprintf("No attribute found!\n");
+        printf("No attribute found!\n");
         goto out;
     }
 
@@ -779,7 +779,7 @@ static int ntfs_readdir(struct file *file, struct dirent *dirent)
 
     len = ntfs_cvt_longname(filename, fn->file_name);
     if (len < 0 || len != fn->file_name_len) {
-        dprintf("Failed on converting UTF-16LE LFN to OEM LFN\n");
+        printf("Failed on converting UTF-16LE LFN to OEM LFN\n");
         goto out;
     }
 
@@ -827,6 +827,7 @@ static int ntfs_fs_init(struct fs_info *fs)
     struct ntfs_bpb ntfs;
     struct ntfs_sb_info *sbi;
     struct disk *disk = fs->fs_dev->disk;
+    uint8_t clust_per_mft_record;
 
     disk->rdwr_sectors(disk, &ntfs, 0, 1, 0);
 
@@ -834,8 +835,19 @@ static int ntfs_fs_init(struct fs_info *fs)
     if (!ntfs_check_sb_fields(&ntfs))
         return -1;
 
+    /* Note: clust_per_mft_record can be a negative number */
+    clust_per_mft_record = ntfs.clust_per_mft_record < 0 ?
+                    -ntfs.clust_per_mft_record : ntfs.clust_per_mft_record;
+
     SECTOR_SHIFT(fs) = disk->sector_shift;
+
+    /* We need _at least_ 1 KiB to read the whole MFT record */
+    BLOCK_SHIFT(fs) = ilog2(ntfs.sec_per_clust) + SECTOR_SHIFT(fs);
+    if (BLOCK_SHIFT(fs) < clust_per_mft_record)
+        BLOCK_SHIFT(fs) = clust_per_mft_record;
+
     SECTOR_SIZE(fs) = 1 << SECTOR_SHIFT(fs);
+    BLOCK_SIZE(fs) = 1 << BLOCK_SHIFT(fs);
 
     sbi = malloc(sizeof(*sbi));
     if (!sbi)
@@ -847,21 +859,14 @@ static int ntfs_fs_init(struct fs_info *fs)
     sbi->clust_byte_shift   = sbi->clust_shift + SECTOR_SHIFT(fs);
     sbi->clust_mask         = ntfs.sec_per_clust - 1;
     sbi->clust_size         = ntfs.sec_per_clust << SECTOR_SHIFT(fs);
-    sbi->mft_record_size    = ntfs.clust_per_mft_record <<
-                                            sbi->clust_byte_shift;
-    sbi->root = sbi->mft + sbi->mft_size;
-
-    /* Note: we need at least 1 KiB to read the whole MFT record, so the block
-     * shift will be at least 10 for now.
-     */
-    BLOCK_SHIFT(fs) = sbi->clust_shift > 10 ? sbi->clust_shift : 10;
-    BLOCK_SIZE(fs) = 1 << BLOCK_SHIFT(fs);
+    sbi->mft_record_size    = 1 << clust_per_mft_record;
 
-    sbi->mft = ntfs.mft_lclust << sbi->clust_shift;
+    sbi->mft_block = ntfs.mft_lclust << sbi->clust_shift <<
+                    SECTOR_SHIFT(fs) >> BLOCK_SHIFT(fs);
     /* 16 MFT entries reserved for metadata files (approximately 16 KiB) */
-    sbi->mft_size = (ntfs.clust_per_mft_record << sbi->clust_shift) << 4;
+    sbi->mft_size = (clust_per_mft_record << sbi->clust_shift) << 4;
 
-    sbi->clusters = (ntfs.total_sectors - sbi->root) >> sbi->clust_shift;
+    sbi->clusters = ntfs.total_sectors << SECTOR_SHIFT(fs) >> sbi->clust_shift;
     if (sbi->clusters > 0xFFFFFFFFFFF4ULL)
         sbi->clusters = 0xFFFFFFFFFFF4ULL;
 
diff --git a/core/fs/ntfs/ntfs.h b/core/fs/ntfs/ntfs.h
index ac48c84..78a0004 100644
--- a/core/fs/ntfs/ntfs.h
+++ b/core/fs/ntfs/ntfs.h
@@ -35,7 +35,7 @@ struct ntfs_bpb {
     uint64_t total_sectors;
     uint64_t mft_lclust;
     uint64_t mft_mirr_lclust;
-    uint8_t clust_per_mft_record;
+    int8_t clust_per_mft_record;
     uint8_t unused_4[3];
     uint8_t clust_per_idx_buf;
     uint8_t unused_5[3];
@@ -46,8 +46,7 @@ struct ntfs_bpb {
 } __attribute__((packed));
 
 struct ntfs_sb_info {
-    sector_t mft;                   /* The MFT region */
-    sector_t root;                  /* The root dir region */
+    block_t mft_block;              /* The first MFT record block */
 
     unsigned mft_size;              /* The MFT size in sectors */
     unsigned mft_record_size;       /* MFT record size in bytes */


More information about the Syslinux-commits mailing list