Loading fs/ntfs3/index.c +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ static int cmp_fnames(const void *key1, size_t l1, const void *key2, size_t l2, if (l2 < fsize2) return -1; both_case = f2->type != FILE_NAME_DOS /*&& !sbi->options.nocase*/; both_case = f2->type != FILE_NAME_DOS && !sbi->options->nocase; if (!l1) { const struct le_str *s2 = (struct le_str *)&f2->name_len; Loading fs/ntfs3/namei.c +139 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include <linux/fs.h> #include <linux/nls.h> #include <linux/ctype.h> #include "debug.h" #include "ntfs.h" Loading Loading @@ -355,6 +356,138 @@ struct dentry *ntfs3_get_parent(struct dentry *child) return ERR_PTR(-ENOENT); } /* * dentry_operations::d_hash */ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name) { struct ntfs_sb_info *sbi; const char *n = name->name; unsigned int len = name->len; unsigned long hash; struct cpu_str *uni; unsigned int c; int err; /* First try fast implementation. */ hash = init_name_hash(dentry); for (;;) { if (!len--) { name->hash = end_name_hash(hash); return 0; } c = *n++; if (c >= 0x80) break; hash = partial_name_hash(toupper(c), hash); } /* * Try slow way with current upcase table */ uni = __getname(); if (!uni) return -ENOMEM; sbi = dentry->d_sb->s_fs_info; err = ntfs_nls_to_utf16(sbi, name->name, name->len, uni, NTFS_NAME_LEN, UTF16_HOST_ENDIAN); if (err < 0) goto out; if (!err) { err = -EINVAL; goto out; } hash = ntfs_names_hash(uni->name, uni->len, sbi->upcase, init_name_hash(dentry)); name->hash = end_name_hash(hash); err = 0; out: __putname(uni); return err; } /* * dentry_operations::d_compare */ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1, const char *str, const struct qstr *name) { struct ntfs_sb_info *sbi; int ret; const char *n1 = str; const char *n2 = name->name; unsigned int len2 = name->len; unsigned int lm = min(len1, len2); unsigned char c1, c2; struct cpu_str *uni1, *uni2; /* First try fast implementation. */ for (;;) { if (!lm--) { ret = len1 == len2 ? 0 : 1; goto out; } if ((c1 = *n1++) == (c2 = *n2++)) continue; if (c1 >= 0x80 || c2 >= 0x80) break; if (toupper(c1) != toupper(c2)) { ret = 1; goto out; } } /* * Try slow way with current upcase table */ sbi = dentry->d_sb->s_fs_info; uni1 = __getname(); if (!uni1) return -ENOMEM; ret = ntfs_nls_to_utf16(sbi, str, len1, uni1, NTFS_NAME_LEN, UTF16_HOST_ENDIAN); if (ret < 0) goto out; if (!ret) { ret = -EINVAL; goto out; } uni2 = Add2Ptr(uni1, 2048); ret = ntfs_nls_to_utf16(sbi, name->name, name->len, uni2, NTFS_NAME_LEN, UTF16_HOST_ENDIAN); if (ret < 0) goto out; if (!ret) { ret = -EINVAL; goto out; } ret = !ntfs_cmp_names(uni1->name, uni1->len, uni2->name, uni2->len, sbi->upcase, false) ? 0 : 1; out: __putname(uni1); return ret; } // clang-format off const struct inode_operations ntfs_dir_inode_operations = { .lookup = ntfs_lookup, Loading Loading @@ -382,4 +515,10 @@ const struct inode_operations ntfs_special_inode_operations = { .get_acl = ntfs_get_acl, .set_acl = ntfs_set_acl, }; const struct dentry_operations ntfs_dentry_ops = { .d_hash = ntfs_d_hash, .d_compare = ntfs_d_compare, }; // clang-format on fs/ntfs3/ntfs_fs.h +4 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,7 @@ struct ntfs_mount_options { unsigned force : 1; /* RW mount dirty volume. */ unsigned noacsrules : 1; /* Exclude acs rules. */ unsigned prealloc : 1; /* Preallocate space when file is growing. */ unsigned nocase : 1; /* case insensitive. */ }; /* Special value to unpack and deallocate. */ Loading Loading @@ -721,6 +722,7 @@ struct dentry *ntfs3_get_parent(struct dentry *child); extern const struct inode_operations ntfs_dir_inode_operations; extern const struct inode_operations ntfs_special_inode_operations; extern const struct dentry_operations ntfs_dentry_ops; /* Globals from record.c */ int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi); Loading Loading @@ -840,6 +842,8 @@ int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2, const u16 *upcase, bool bothcase); int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2, const u16 *upcase, bool bothcase); unsigned long ntfs_names_hash(const u16 *name, size_t len, const u16 *upcase, unsigned long hash); /* globals from xattr.c */ #ifdef CONFIG_NTFS3_FS_POSIX_ACL Loading fs/ntfs3/super.c +6 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,7 @@ enum Opt { Opt_iocharset, Opt_prealloc, Opt_noacsrules, Opt_nocase, Opt_err, }; Loading @@ -272,6 +273,7 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = { fsparam_flag_no("showmeta", Opt_showmeta), fsparam_flag_no("prealloc", Opt_prealloc), fsparam_flag_no("acsrules", Opt_noacsrules), fsparam_flag_no("nocase", Opt_nocase), fsparam_string("iocharset", Opt_iocharset), {} }; Loading Loading @@ -383,6 +385,9 @@ static int ntfs_fs_parse_param(struct fs_context *fc, case Opt_noacsrules: opts->noacsrules = result.negated ? 1 : 0; break; case Opt_nocase: opts->nocase = result.negated ? 1 : 0; break; default: /* Should not be here unless we forget add case. */ return -EINVAL; Loading Loading @@ -936,6 +941,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_export_op = &ntfs_export_ops; sb->s_time_gran = NTFS_TIME_GRAN; // 100 nsec sb->s_xattr = ntfs_xattr_handlers; sb->s_d_op = sbi->options->nocase ? &ntfs_dentry_ops : NULL; sbi->options->nls = ntfs_load_nls(sbi->options->nls_name); if (IS_ERR(sbi->options->nls)) { Loading fs/ntfs3/upcase.c +12 −0 Original line number Diff line number Diff line Loading @@ -102,3 +102,15 @@ int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2, diff2 = l1 - l2; return diff2 ? diff2 : diff1; } /* Helper function for ntfs_d_hash. */ unsigned long ntfs_names_hash(const u16 *name, size_t len, const u16 *upcase, unsigned long hash) { while (len--) { unsigned int c = upcase_unicode_char(upcase, *name++); hash = partial_name_hash(c, hash); } return hash; } Loading
fs/ntfs3/index.c +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ static int cmp_fnames(const void *key1, size_t l1, const void *key2, size_t l2, if (l2 < fsize2) return -1; both_case = f2->type != FILE_NAME_DOS /*&& !sbi->options.nocase*/; both_case = f2->type != FILE_NAME_DOS && !sbi->options->nocase; if (!l1) { const struct le_str *s2 = (struct le_str *)&f2->name_len; Loading
fs/ntfs3/namei.c +139 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include <linux/fs.h> #include <linux/nls.h> #include <linux/ctype.h> #include "debug.h" #include "ntfs.h" Loading Loading @@ -355,6 +356,138 @@ struct dentry *ntfs3_get_parent(struct dentry *child) return ERR_PTR(-ENOENT); } /* * dentry_operations::d_hash */ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name) { struct ntfs_sb_info *sbi; const char *n = name->name; unsigned int len = name->len; unsigned long hash; struct cpu_str *uni; unsigned int c; int err; /* First try fast implementation. */ hash = init_name_hash(dentry); for (;;) { if (!len--) { name->hash = end_name_hash(hash); return 0; } c = *n++; if (c >= 0x80) break; hash = partial_name_hash(toupper(c), hash); } /* * Try slow way with current upcase table */ uni = __getname(); if (!uni) return -ENOMEM; sbi = dentry->d_sb->s_fs_info; err = ntfs_nls_to_utf16(sbi, name->name, name->len, uni, NTFS_NAME_LEN, UTF16_HOST_ENDIAN); if (err < 0) goto out; if (!err) { err = -EINVAL; goto out; } hash = ntfs_names_hash(uni->name, uni->len, sbi->upcase, init_name_hash(dentry)); name->hash = end_name_hash(hash); err = 0; out: __putname(uni); return err; } /* * dentry_operations::d_compare */ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1, const char *str, const struct qstr *name) { struct ntfs_sb_info *sbi; int ret; const char *n1 = str; const char *n2 = name->name; unsigned int len2 = name->len; unsigned int lm = min(len1, len2); unsigned char c1, c2; struct cpu_str *uni1, *uni2; /* First try fast implementation. */ for (;;) { if (!lm--) { ret = len1 == len2 ? 0 : 1; goto out; } if ((c1 = *n1++) == (c2 = *n2++)) continue; if (c1 >= 0x80 || c2 >= 0x80) break; if (toupper(c1) != toupper(c2)) { ret = 1; goto out; } } /* * Try slow way with current upcase table */ sbi = dentry->d_sb->s_fs_info; uni1 = __getname(); if (!uni1) return -ENOMEM; ret = ntfs_nls_to_utf16(sbi, str, len1, uni1, NTFS_NAME_LEN, UTF16_HOST_ENDIAN); if (ret < 0) goto out; if (!ret) { ret = -EINVAL; goto out; } uni2 = Add2Ptr(uni1, 2048); ret = ntfs_nls_to_utf16(sbi, name->name, name->len, uni2, NTFS_NAME_LEN, UTF16_HOST_ENDIAN); if (ret < 0) goto out; if (!ret) { ret = -EINVAL; goto out; } ret = !ntfs_cmp_names(uni1->name, uni1->len, uni2->name, uni2->len, sbi->upcase, false) ? 0 : 1; out: __putname(uni1); return ret; } // clang-format off const struct inode_operations ntfs_dir_inode_operations = { .lookup = ntfs_lookup, Loading Loading @@ -382,4 +515,10 @@ const struct inode_operations ntfs_special_inode_operations = { .get_acl = ntfs_get_acl, .set_acl = ntfs_set_acl, }; const struct dentry_operations ntfs_dentry_ops = { .d_hash = ntfs_d_hash, .d_compare = ntfs_d_compare, }; // clang-format on
fs/ntfs3/ntfs_fs.h +4 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,7 @@ struct ntfs_mount_options { unsigned force : 1; /* RW mount dirty volume. */ unsigned noacsrules : 1; /* Exclude acs rules. */ unsigned prealloc : 1; /* Preallocate space when file is growing. */ unsigned nocase : 1; /* case insensitive. */ }; /* Special value to unpack and deallocate. */ Loading Loading @@ -721,6 +722,7 @@ struct dentry *ntfs3_get_parent(struct dentry *child); extern const struct inode_operations ntfs_dir_inode_operations; extern const struct inode_operations ntfs_special_inode_operations; extern const struct dentry_operations ntfs_dentry_ops; /* Globals from record.c */ int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi); Loading Loading @@ -840,6 +842,8 @@ int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2, const u16 *upcase, bool bothcase); int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2, const u16 *upcase, bool bothcase); unsigned long ntfs_names_hash(const u16 *name, size_t len, const u16 *upcase, unsigned long hash); /* globals from xattr.c */ #ifdef CONFIG_NTFS3_FS_POSIX_ACL Loading
fs/ntfs3/super.c +6 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,7 @@ enum Opt { Opt_iocharset, Opt_prealloc, Opt_noacsrules, Opt_nocase, Opt_err, }; Loading @@ -272,6 +273,7 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = { fsparam_flag_no("showmeta", Opt_showmeta), fsparam_flag_no("prealloc", Opt_prealloc), fsparam_flag_no("acsrules", Opt_noacsrules), fsparam_flag_no("nocase", Opt_nocase), fsparam_string("iocharset", Opt_iocharset), {} }; Loading Loading @@ -383,6 +385,9 @@ static int ntfs_fs_parse_param(struct fs_context *fc, case Opt_noacsrules: opts->noacsrules = result.negated ? 1 : 0; break; case Opt_nocase: opts->nocase = result.negated ? 1 : 0; break; default: /* Should not be here unless we forget add case. */ return -EINVAL; Loading Loading @@ -936,6 +941,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_export_op = &ntfs_export_ops; sb->s_time_gran = NTFS_TIME_GRAN; // 100 nsec sb->s_xattr = ntfs_xattr_handlers; sb->s_d_op = sbi->options->nocase ? &ntfs_dentry_ops : NULL; sbi->options->nls = ntfs_load_nls(sbi->options->nls_name); if (IS_ERR(sbi->options->nls)) { Loading
fs/ntfs3/upcase.c +12 −0 Original line number Diff line number Diff line Loading @@ -102,3 +102,15 @@ int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2, diff2 = l1 - l2; return diff2 ? diff2 : diff1; } /* Helper function for ntfs_d_hash. */ unsigned long ntfs_names_hash(const u16 *name, size_t len, const u16 *upcase, unsigned long hash) { while (len--) { unsigned int c = upcase_unicode_char(upcase, *name++); hash = partial_name_hash(c, hash); } return hash; }