|
|
|
@ -1004,13 +1004,11 @@ dir_err_out: |
|
|
|
|
/**
|
|
|
|
|
* ntfs_filldir - ntfs specific filldir method |
|
|
|
|
* @vol: current ntfs volume |
|
|
|
|
* @fpos: position in the directory |
|
|
|
|
* @ndir: ntfs inode of current directory |
|
|
|
|
* @ia_page: page in which the index allocation buffer @ie is in resides |
|
|
|
|
* @ie: current index entry |
|
|
|
|
* @name: buffer to use for the converted name |
|
|
|
|
* @dirent: vfs filldir callback context |
|
|
|
|
* @filldir: vfs filldir callback |
|
|
|
|
* @actor: what to feed the entries to |
|
|
|
|
* |
|
|
|
|
* Convert the Unicode @name to the loaded NLS and pass it to the @filldir |
|
|
|
|
* callback. |
|
|
|
@ -1024,12 +1022,12 @@ dir_err_out: |
|
|
|
|
* retake the lock if we are returning a non-zero value as ntfs_readdir() |
|
|
|
|
* would need to drop the lock immediately anyway. |
|
|
|
|
*/ |
|
|
|
|
static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, |
|
|
|
|
static inline int ntfs_filldir(ntfs_volume *vol, |
|
|
|
|
ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, |
|
|
|
|
u8 *name, void *dirent, filldir_t filldir) |
|
|
|
|
u8 *name, struct dir_context *actor) |
|
|
|
|
{ |
|
|
|
|
unsigned long mref; |
|
|
|
|
int name_len, rc; |
|
|
|
|
int name_len; |
|
|
|
|
unsigned dt_type; |
|
|
|
|
FILE_NAME_TYPE_FLAGS name_type; |
|
|
|
|
|
|
|
|
@ -1068,13 +1066,14 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, |
|
|
|
|
if (ia_page) |
|
|
|
|
unlock_page(ia_page); |
|
|
|
|
ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " |
|
|
|
|
"0x%lx, DT_%s.", name, name_len, fpos, mref, |
|
|
|
|
"0x%lx, DT_%s.", name, name_len, actor->pos, mref, |
|
|
|
|
dt_type == DT_DIR ? "DIR" : "REG"); |
|
|
|
|
rc = filldir(dirent, name, name_len, fpos, mref, dt_type); |
|
|
|
|
if (!dir_emit(actor, name, name_len, mref, dt_type)) |
|
|
|
|
return 1; |
|
|
|
|
/* Relock the page but not if we are aborting ->readdir. */ |
|
|
|
|
if (!rc && ia_page) |
|
|
|
|
if (ia_page) |
|
|
|
|
lock_page(ia_page); |
|
|
|
|
return rc; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -1097,11 +1096,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, |
|
|
|
|
* removes them again after the write is complete after which it
|
|
|
|
|
* unlocks the page. |
|
|
|
|
*/ |
|
|
|
|
static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
|
|
|
|
static int ntfs_readdir(struct file *file, struct dir_context *actor) |
|
|
|
|
{ |
|
|
|
|
s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; |
|
|
|
|
loff_t fpos, i_size; |
|
|
|
|
struct inode *bmp_vi, *vdir = file_inode(filp); |
|
|
|
|
loff_t i_size; |
|
|
|
|
struct inode *bmp_vi, *vdir = file_inode(file); |
|
|
|
|
struct super_block *sb = vdir->i_sb; |
|
|
|
|
ntfs_inode *ndir = NTFS_I(vdir); |
|
|
|
|
ntfs_volume *vol = NTFS_SB(sb); |
|
|
|
@ -1116,33 +1115,16 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
|
|
|
|
u8 *kaddr, *bmp, *index_end; |
|
|
|
|
ntfs_attr_search_ctx *ctx; |
|
|
|
|
|
|
|
|
|
fpos = filp->f_pos; |
|
|
|
|
ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", |
|
|
|
|
vdir->i_ino, fpos); |
|
|
|
|
vdir->i_ino, actor->pos); |
|
|
|
|
rc = err = 0; |
|
|
|
|
/* Are we at end of dir yet? */ |
|
|
|
|
i_size = i_size_read(vdir); |
|
|
|
|
if (fpos >= i_size + vol->mft_record_size) |
|
|
|
|
goto done; |
|
|
|
|
if (actor->pos >= i_size + vol->mft_record_size) |
|
|
|
|
return 0; |
|
|
|
|
/* Emulate . and .. for all directories. */ |
|
|
|
|
if (!fpos) { |
|
|
|
|
ntfs_debug("Calling filldir for . with len 1, fpos 0x0, " |
|
|
|
|
"inode 0x%lx, DT_DIR.", vdir->i_ino); |
|
|
|
|
rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR); |
|
|
|
|
if (rc) |
|
|
|
|
goto done; |
|
|
|
|
fpos++; |
|
|
|
|
} |
|
|
|
|
if (fpos == 1) { |
|
|
|
|
ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, " |
|
|
|
|
"inode 0x%lx, DT_DIR.", |
|
|
|
|
(unsigned long)parent_ino(filp->f_path.dentry)); |
|
|
|
|
rc = filldir(dirent, "..", 2, fpos, |
|
|
|
|
parent_ino(filp->f_path.dentry), DT_DIR); |
|
|
|
|
if (rc) |
|
|
|
|
goto done; |
|
|
|
|
fpos++; |
|
|
|
|
} |
|
|
|
|
if (!dir_emit_dots(file, actor)) |
|
|
|
|
return 0; |
|
|
|
|
m = NULL; |
|
|
|
|
ctx = NULL; |
|
|
|
|
/*
|
|
|
|
@ -1155,7 +1137,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
|
|
|
|
goto err_out; |
|
|
|
|
} |
|
|
|
|
/* Are we jumping straight into the index allocation attribute? */ |
|
|
|
|
if (fpos >= vol->mft_record_size) |
|
|
|
|
if (actor->pos >= vol->mft_record_size) |
|
|
|
|
goto skip_index_root; |
|
|
|
|
/* Get hold of the mft record for the directory. */ |
|
|
|
|
m = map_mft_record(ndir); |
|
|
|
@ -1170,7 +1152,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
|
|
|
|
goto err_out; |
|
|
|
|
} |
|
|
|
|
/* Get the offset into the index root attribute. */ |
|
|
|
|
ir_pos = (s64)fpos; |
|
|
|
|
ir_pos = (s64)actor->pos; |
|
|
|
|
/* Find the index root attribute in the mft record. */ |
|
|
|
|
err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, |
|
|
|
|
0, ctx); |
|
|
|
@ -1226,10 +1208,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
|
|
|
|
if (ir_pos > (u8*)ie - (u8*)ir) |
|
|
|
|
continue; |
|
|
|
|
/* Advance the position even if going to skip the entry. */ |
|
|
|
|
fpos = (u8*)ie - (u8*)ir; |
|
|
|
|
actor->pos = (u8*)ie - (u8*)ir; |
|
|
|
|
/* Submit the name to the filldir callback. */ |
|
|
|
|
rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent, |
|
|
|
|
filldir); |
|
|
|
|
rc = ntfs_filldir(vol, ndir, NULL, ie, name, actor); |
|
|
|
|
if (rc) { |
|
|
|
|
kfree(ir); |
|
|
|
|
goto abort; |
|
|
|
@ -1242,12 +1223,12 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
|
|
|
|
if (!NInoIndexAllocPresent(ndir)) |
|
|
|
|
goto EOD; |
|
|
|
|
/* Advance fpos to the beginning of the index allocation. */ |
|
|
|
|
fpos = vol->mft_record_size; |
|
|
|
|
actor->pos = vol->mft_record_size; |
|
|
|
|
skip_index_root: |
|
|
|
|
kaddr = NULL; |
|
|
|
|
prev_ia_pos = -1LL; |
|
|
|
|
/* Get the offset into the index allocation attribute. */ |
|
|
|
|
ia_pos = (s64)fpos - vol->mft_record_size; |
|
|
|
|
ia_pos = (s64)actor->pos - vol->mft_record_size; |
|
|
|
|
ia_mapping = vdir->i_mapping; |
|
|
|
|
ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino); |
|
|
|
|
bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); |
|
|
|
@ -1409,7 +1390,7 @@ find_next_index_buffer: |
|
|
|
|
if (ia_pos - ia_start > (u8*)ie - (u8*)ia) |
|
|
|
|
continue; |
|
|
|
|
/* Advance the position even if going to skip the entry. */ |
|
|
|
|
fpos = (u8*)ie - (u8*)ia + |
|
|
|
|
actor->pos = (u8*)ie - (u8*)ia + |
|
|
|
|
(sle64_to_cpu(ia->index_block_vcn) << |
|
|
|
|
ndir->itype.index.vcn_size_bits) + |
|
|
|
|
vol->mft_record_size; |
|
|
|
@ -1419,8 +1400,7 @@ find_next_index_buffer: |
|
|
|
|
* before returning, unless a non-zero value is returned in |
|
|
|
|
* which case the page is left unlocked. |
|
|
|
|
*/ |
|
|
|
|
rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent, |
|
|
|
|
filldir); |
|
|
|
|
rc = ntfs_filldir(vol, ndir, ia_page, ie, name, actor); |
|
|
|
|
if (rc) { |
|
|
|
|
/* @ia_page is already unlocked in this case. */ |
|
|
|
|
ntfs_unmap_page(ia_page); |
|
|
|
@ -1439,18 +1419,9 @@ unm_EOD: |
|
|
|
|
iput(bmp_vi); |
|
|
|
|
EOD: |
|
|
|
|
/* We are finished, set fpos to EOD. */ |
|
|
|
|
fpos = i_size + vol->mft_record_size; |
|
|
|
|
actor->pos = i_size + vol->mft_record_size; |
|
|
|
|
abort: |
|
|
|
|
kfree(name); |
|
|
|
|
done: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
if (!rc) |
|
|
|
|
ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos); |
|
|
|
|
else |
|
|
|
|
ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.", |
|
|
|
|
rc, fpos); |
|
|
|
|
#endif |
|
|
|
|
filp->f_pos = fpos; |
|
|
|
|
return 0; |
|
|
|
|
err_out: |
|
|
|
|
if (bmp_page) { |
|
|
|
@ -1471,7 +1442,6 @@ iput_err_out: |
|
|
|
|
if (!err) |
|
|
|
|
err = -EIO; |
|
|
|
|
ntfs_debug("Failed. Returning error code %i.", -err); |
|
|
|
|
filp->f_pos = fpos; |
|
|
|
|
return err; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1571,7 +1541,7 @@ static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end, |
|
|
|
|
const struct file_operations ntfs_dir_ops = { |
|
|
|
|
.llseek = generic_file_llseek, /* Seek inside directory. */ |
|
|
|
|
.read = generic_read_dir, /* Return -EISDIR. */ |
|
|
|
|
.readdir = ntfs_readdir, /* Read directory contents. */ |
|
|
|
|
.iterate = ntfs_readdir, /* Read directory contents. */ |
|
|
|
|
#ifdef NTFS_RW |
|
|
|
|
.fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ |
|
|
|
|
/*.aio_fsync = ,*/ /* Sync all outstanding async
|
|
|
|
|