/* * _utf8s_to_utf16s * * Modified version of 'utf8s_to_utf16s' allows to * detect -ENAMETOOLONG without writing out of expected maximum.
*/ staticint _utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian, wchar_t *pwcs, int maxout)
{
u16 *op; int size;
unicode_t u;
op = pwcs; while (inlen > 0 && *s) { if (*s & 0x80) {
size = utf8_to_utf32(s, inlen, &u); if (size < 0) return -EINVAL;
s += size;
inlen -= size;
if (u >= PLANE_SIZE) { if (maxout < 2) return -ENAMETOOLONG;
/* * returns false if 'ctx' if full
*/ staticinlinebool ntfs_dir_emit(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, conststruct NTFS_DE *e,
u8 *name, struct dir_context *ctx)
{ conststruct ATTR_FILE_NAME *fname; unsignedlong ino; int name_len;
u32 dt_type;
fname = Add2Ptr(e, sizeof(struct NTFS_DE));
if (fname->type == FILE_NAME_DOS) returntrue;
if (!mi_is_ref(&ni->mi, &fname->home)) returntrue;
ino = ino_get(&e->ref);
if (ino == MFT_REC_ROOT) returntrue;
/* Skip meta files. Unless option to show metafiles is set. */ if (!sbi->options->showmeta && ntfs_is_meta_file(sbi, ino)) returntrue;
if (sbi->options->nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN)) returntrue;
if (fname->name_len + sizeof(struct NTFS_DE) > le16_to_cpu(e->size)) returntrue;
name_len = ntfs_utf16_to_nls(sbi, fname->name, fname->name_len, name,
PATH_MAX); if (name_len <= 0) {
ntfs_warn(sbi->sb, "failed to convert name for inode %lx.",
ino); returntrue;
}
/* * NTFS: symlinks are "dir + reparse" or "file + reparse" * Unfortunately reparse attribute is used for many purposes (several dozens). * It is not possible here to know is this name symlink or not. * To get exactly the type of name we should to open inode (read mft). * getattr for opened file (fstat) correctly returns symlink.
*/
dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
/* * It is not reliable to detect the type of name using duplicated information * stored in parent directory. * The only correct way to get the type of name - read MFT record and find ATTR_STD. * The code below is not good idea. * It does additional locks/reads just to get the type of name. * Should we use additional mount option to enable branch below?
*/ if (fname->dup.extend_data &&
ino != ni->mi.rno) { struct inode *inode = ntfs_iget5(sbi->sb, &e->ref, NULL); if (!IS_ERR_OR_NULL(inode)) {
dt_type = fs_umode_to_dtype(inode->i_mode);
iput(inode);
}
}
/* * ntfs_read_hdr - Helper function for ntfs_readdir(). * * returns 0 if ok. * returns -EINVAL if directory is corrupted. * returns +1 if 'ctx' is full.
*/ staticint ntfs_read_hdr(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, conststruct INDEX_HDR *hdr, u64 vbo, u64 pos,
u8 *name, struct dir_context *ctx)
{ conststruct NTFS_DE *e;
u32 e_size;
u32 end = le32_to_cpu(hdr->used);
u32 off = le32_to_cpu(hdr->de_off);
for (;; off += e_size) { if (off + sizeof(struct NTFS_DE) > end) return -EINVAL;
e = Add2Ptr(hdr, off);
e_size = le16_to_cpu(e->size); if (e_size < sizeof(struct NTFS_DE) || off + e_size > end) return -EINVAL;
if (de_is_last(e)) return 0;
/* Skip already enumerated. */ if (vbo + off < pos) continue;
if (le16_to_cpu(e->key_size) < SIZEOF_ATTRIBUTE_FILENAME) return -EINVAL;
ctx->pos = vbo + off;
/* Submit the name to the filldir callback. */ if (!ntfs_dir_emit(sbi, ni, e, name, ctx)) { /* ctx is full. */ return +1;
}
}
}
/* * ntfs_readdir - file_operations::iterate_shared * * Use non sorted enumeration. * We have an example of broken volume where sorted enumeration * counts each name twice.
*/ staticint ntfs_readdir(struct file *file, struct dir_context *ctx)
{ conststruct INDEX_ROOT *root;
u64 vbo;
size_t bit;
loff_t eod; int err = 0; struct inode *dir = file_inode(file); struct ntfs_inode *ni = ntfs_i(dir); struct super_block *sb = dir->i_sb; struct ntfs_sb_info *sbi = sb->s_fs_info;
loff_t i_size = i_size_read(dir);
u32 pos = ctx->pos;
u8 *name = NULL; struct indx_node *node = NULL;
u8 index_bits = ni->dir.index_bits;
/* Name is a buffer of PATH_MAX length. */
static_assert(NTFS_NAME_LEN * 4 < PATH_MAX);
eod = i_size + sbi->record_size;
if (pos >= eod) return 0;
if (!dir_emit_dots(file, ctx)) return 0;
/* Allocate PATH_MAX bytes. */
name = __getname(); if (!name) return -ENOMEM;
if (!ni->mi_loaded && ni->attr_list.size) { /* * Directory inode is locked for read. * Load all subrecords to avoid 'write' access to 'ni' during * directory reading.
*/
ni_lock(ni); if (!ni->mi_loaded && ni->attr_list.size) {
err = ni_load_all_mi(ni); if (!err)
ni->mi_loaded = true;
}
ni_unlock(ni); if (err) goto out;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.