aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <pcacjr@gmail.com>2011-07-23 16:52:20 +0000
committerPaulo Alcantara <pcacjr@gmail.com>2011-09-07 07:19:07 +0000
commit338081d635fccb80ee533a46babc6c3718f6a99d (patch)
tree81b6a3238e9a5bbbb5d85784ce1e5cdabd87a143
parentbb57a2fbf93317d5aff31403cac38b2e73759fa8 (diff)
downloadsyslinux-338081d635fccb80ee533a46babc6c3718f6a99d.tar.gz
syslinux-338081d635fccb80ee533a46babc6c3718f6a99d.tar.xz
syslinux-338081d635fccb80ee533a46babc6c3718f6a99d.zip
ntfs: implement ntfs_next_extent() and ntfs_getfssec()
Signed-off-by: Paulo Alcantara <pcacjr@gmail.com>
-rw-r--r--core/fs/ntfs/ntfs.c121
1 files changed, 116 insertions, 5 deletions
diff --git a/core/fs/ntfs/ntfs.c b/core/fs/ntfs/ntfs.c
index 30c81c2c..a1c35726 100644
--- a/core/fs/ntfs/ntfs.c
+++ b/core/fs/ntfs/ntfs.c
@@ -640,6 +640,115 @@ static int ntfs_cvt_longname(char *entry_name, const uint16_t *long_name)
return (p - entry_name) - 1;
}
+static int ntfs_next_extent(struct inode *inode, uint32_t lstart)
+{
+ struct fs_info *fs = inode->fs;
+ struct ntfs_sb_info *sbi = NTFS_SB(fs);
+ uint32_t mcluster = lstart >> sbi->clust_shift;
+ 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);
+
+ 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
+ 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.pstart = pstart;
+
+ return 0;
+
+out:
+ return -1;
+}
+
+static uint32_t ntfs_getfssec(struct file *file, char *buf, int sectors,
+ bool *have_more)
+{
+ uint32_t ret;
+ struct inode *inode = file->inode;
+ uint8_t non_resident;
+ struct fs_info *fs = file->fs;
+ struct disk *disk = fs->fs_dev->disk;
+ sector_t block;
+ MFT_RECORD *mrec;
+ ATTR_RECORD *attr;
+ uint8_t *usa_start;
+ uint16_t usa_no;
+ uint8_t *usa_end;
+ char data[1024];
+ char *pbuf;
+ char *p;
+ uint16_t val;
+
+ non_resident = NTFS_PVT(inode)->non_resident;
+
+ ret = generic_getfssec(file, buf, sectors, have_more);
+ if (!ret)
+ return ret;
+
+ if (!non_resident) {
+ block = NTFS_SB(file->fs)->mft + NTFS_PVT(inode)->here;
+
+ /* read the whole MFT Record into our data buffer */
+ disk->rdwr_sectors(disk, data, block, 2, 0);
+
+ mrec = (MFT_RECORD *)&data[0];
+ if (mrec->magic != NTFS_MAGIC_FILE) {
+ printf("No MFT record found!\n");
+ goto out;
+ }
+
+ /* get the Update Sequence Array */
+ usa_start = (uint8_t *)mrec + mrec->usa_ofs; /* there it is! grr... */
+ usa_no = *(uint16_t *)usa_start;
+ usa_end = (uint8_t *)usa_start + mrec->usa_count + 1;
+
+ attr = attr_lookup(NTFS_AT_DATA, mrec);
+ if (!attr) {
+ printf("No attribute found!\n");
+ goto out;
+ }
+
+ pbuf = (char *)attr + attr->data.resident.value_offset;
+
+ /* pbuf now points to the data offset, so let's copy it into
+ * buf
+ */
+ memcpy(buf, pbuf, inode->size);
+
+ p = buf;
+ usa_start += 2; /* make it to point to the fixups */
+ while (*p) {
+ val = *p | *(p + 1);
+ if (val == usa_no) {
+ if (usa_start != usa_end && usa_start + 1 != usa_end) {
+ *p++ = *usa_start++;
+ *p++ = *usa_start++;
+ } else {
+ p++;
+ }
+ } else {
+ p++;
+ }
+ }
+
+ ret = inode->size;
+ }
+
+ return ret;
+
+out:
+ return 0;
+}
+
static int ntfs_readdir(struct file *file, struct dirent *dirent)
{
struct fs_info *fs = file->fs;
@@ -651,6 +760,8 @@ static int ntfs_readdir(struct file *file, struct dirent *dirent)
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");
@@ -760,12 +871,12 @@ const struct fs_ops ntfs_fs_ops = {
.fs_flags = FS_USEMEM | FS_THISIND,
.fs_init = ntfs_fs_init,
.searchdir = NULL,
- .getfssec = NULL,
- .close_file = NULL,
- .mangle_name = NULL,
- .load_config = NULL,
+ .getfssec = ntfs_getfssec,
+ .close_file = generic_close_file,
+ .mangle_name = generic_mangle_name,
+ .load_config = generic_load_config,
.readdir = ntfs_readdir,
.iget_root = ntfs_iget_root,
.iget = ntfs_iget,
- .next_extent = NULL,
+ .next_extent = ntfs_next_extent,
};