summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/dir.c')
-rw-r--r--fs/f2fs/dir.c125
1 files changed, 115 insertions, 10 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 85a1528f319f..dac07d17cdbd 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -8,6 +8,7 @@
8#include <linux/fs.h> 8#include <linux/fs.h>
9#include <linux/f2fs_fs.h> 9#include <linux/f2fs_fs.h>
10#include <linux/sched/signal.h> 10#include <linux/sched/signal.h>
11#include <linux/unicode.h>
11#include "f2fs.h" 12#include "f2fs.h"
12#include "node.h" 13#include "node.h"
13#include "acl.h" 14#include "acl.h"
@@ -81,7 +82,8 @@ static unsigned long dir_block_index(unsigned int level,
81 return bidx; 82 return bidx;
82} 83}
83 84
84static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, 85static struct f2fs_dir_entry *find_in_block(struct inode *dir,
86 struct page *dentry_page,
85 struct fscrypt_name *fname, 87 struct fscrypt_name *fname,
86 f2fs_hash_t namehash, 88 f2fs_hash_t namehash,
87 int *max_slots, 89 int *max_slots,
@@ -93,7 +95,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
93 95
94 dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page); 96 dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page);
95 97
96 make_dentry_ptr_block(NULL, &d, dentry_blk); 98 make_dentry_ptr_block(dir, &d, dentry_blk);
97 de = f2fs_find_target_dentry(fname, namehash, max_slots, &d); 99 de = f2fs_find_target_dentry(fname, namehash, max_slots, &d);
98 if (de) 100 if (de)
99 *res_page = dentry_page; 101 *res_page = dentry_page;
@@ -101,6 +103,39 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
101 return de; 103 return de;
102} 104}
103 105
106#ifdef CONFIG_UNICODE
107/*
108 * Test whether a case-insensitive directory entry matches the filename
109 * being searched for.
110 *
111 * Returns: 0 if the directory entry matches, more than 0 if it
112 * doesn't match or less than zero on error.
113 */
114int f2fs_ci_compare(const struct inode *parent, const struct qstr *name,
115 const struct qstr *entry)
116{
117 const struct f2fs_sb_info *sbi = F2FS_SB(parent->i_sb);
118 const struct unicode_map *um = sbi->s_encoding;
119 int ret;
120
121 ret = utf8_strncasecmp(um, name, entry);
122 if (ret < 0) {
123 /* Handle invalid character sequence as either an error
124 * or as an opaque byte sequence.
125 */
126 if (f2fs_has_strict_mode(sbi))
127 return -EINVAL;
128
129 if (name->len != entry->len)
130 return 1;
131
132 return !!memcmp(name->name, entry->name, name->len);
133 }
134
135 return ret;
136}
137#endif
138
104struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname, 139struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
105 f2fs_hash_t namehash, int *max_slots, 140 f2fs_hash_t namehash, int *max_slots,
106 struct f2fs_dentry_ptr *d) 141 struct f2fs_dentry_ptr *d)
@@ -108,6 +143,9 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
108 struct f2fs_dir_entry *de; 143 struct f2fs_dir_entry *de;
109 unsigned long bit_pos = 0; 144 unsigned long bit_pos = 0;
110 int max_len = 0; 145 int max_len = 0;
146#ifdef CONFIG_UNICODE
147 struct qstr entry;
148#endif
111 149
112 if (max_slots) 150 if (max_slots)
113 *max_slots = 0; 151 *max_slots = 0;
@@ -119,16 +157,28 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
119 } 157 }
120 158
121 de = &d->dentry[bit_pos]; 159 de = &d->dentry[bit_pos];
160#ifdef CONFIG_UNICODE
161 entry.name = d->filename[bit_pos];
162 entry.len = de->name_len;
163#endif
122 164
123 if (unlikely(!de->name_len)) { 165 if (unlikely(!de->name_len)) {
124 bit_pos++; 166 bit_pos++;
125 continue; 167 continue;
126 } 168 }
169 if (de->hash_code == namehash) {
170#ifdef CONFIG_UNICODE
171 if (F2FS_SB(d->inode->i_sb)->s_encoding &&
172 IS_CASEFOLDED(d->inode) &&
173 !f2fs_ci_compare(d->inode,
174 fname->usr_fname, &entry))
175 goto found;
127 176
128 if (de->hash_code == namehash && 177#endif
129 fscrypt_match_name(fname, d->filename[bit_pos], 178 if (fscrypt_match_name(fname, d->filename[bit_pos],
130 le16_to_cpu(de->name_len))) 179 le16_to_cpu(de->name_len)))
131 goto found; 180 goto found;
181 }
132 182
133 if (max_slots && max_len > *max_slots) 183 if (max_slots && max_len > *max_slots)
134 *max_slots = max_len; 184 *max_slots = max_len;
@@ -157,7 +207,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
157 struct f2fs_dir_entry *de = NULL; 207 struct f2fs_dir_entry *de = NULL;
158 bool room = false; 208 bool room = false;
159 int max_slots; 209 int max_slots;
160 f2fs_hash_t namehash = f2fs_dentry_hash(&name, fname); 210 f2fs_hash_t namehash = f2fs_dentry_hash(dir, &name, fname);
161 211
162 nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level); 212 nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
163 nblock = bucket_blocks(level); 213 nblock = bucket_blocks(level);
@@ -179,8 +229,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
179 } 229 }
180 } 230 }
181 231
182 de = find_in_block(dentry_page, fname, namehash, &max_slots, 232 de = find_in_block(dir, dentry_page, fname, namehash,
183 res_page); 233 &max_slots, res_page);
184 if (de) 234 if (de)
185 break; 235 break;
186 236
@@ -250,6 +300,14 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
250 struct fscrypt_name fname; 300 struct fscrypt_name fname;
251 int err; 301 int err;
252 302
303#ifdef CONFIG_UNICODE
304 if (f2fs_has_strict_mode(F2FS_I_SB(dir)) && IS_CASEFOLDED(dir) &&
305 utf8_validate(F2FS_I_SB(dir)->s_encoding, child)) {
306 *res_page = ERR_PTR(-EINVAL);
307 return NULL;
308 }
309#endif
310
253 err = fscrypt_setup_filename(dir, child, 1, &fname); 311 err = fscrypt_setup_filename(dir, child, 1, &fname);
254 if (err) { 312 if (err) {
255 if (err == -ENOENT) 313 if (err == -ENOENT)
@@ -504,7 +562,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
504 562
505 level = 0; 563 level = 0;
506 slots = GET_DENTRY_SLOTS(new_name->len); 564 slots = GET_DENTRY_SLOTS(new_name->len);
507 dentry_hash = f2fs_dentry_hash(new_name, NULL); 565 dentry_hash = f2fs_dentry_hash(dir, new_name, NULL);
508 566
509 current_depth = F2FS_I(dir)->i_current_depth; 567 current_depth = F2FS_I(dir)->i_current_depth;
510 if (F2FS_I(dir)->chash == dentry_hash) { 568 if (F2FS_I(dir)->chash == dentry_hash) {
@@ -943,3 +1001,50 @@ const struct file_operations f2fs_dir_operations = {
943 .compat_ioctl = f2fs_compat_ioctl, 1001 .compat_ioctl = f2fs_compat_ioctl,
944#endif 1002#endif
945}; 1003};
1004
1005#ifdef CONFIG_UNICODE
1006static int f2fs_d_compare(const struct dentry *dentry, unsigned int len,
1007 const char *str, const struct qstr *name)
1008{
1009 struct qstr qstr = {.name = str, .len = len };
1010
1011 if (!IS_CASEFOLDED(dentry->d_parent->d_inode)) {
1012 if (len != name->len)
1013 return -1;
1014 return memcmp(str, name, len);
1015 }
1016
1017 return f2fs_ci_compare(dentry->d_parent->d_inode, name, &qstr);
1018}
1019
1020static int f2fs_d_hash(const struct dentry *dentry, struct qstr *str)
1021{
1022 struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
1023 const struct unicode_map *um = sbi->s_encoding;
1024 unsigned char *norm;
1025 int len, ret = 0;
1026
1027 if (!IS_CASEFOLDED(dentry->d_inode))
1028 return 0;
1029
1030 norm = f2fs_kmalloc(sbi, PATH_MAX, GFP_ATOMIC);
1031 if (!norm)
1032 return -ENOMEM;
1033
1034 len = utf8_casefold(um, str, norm, PATH_MAX);
1035 if (len < 0) {
1036 if (f2fs_has_strict_mode(sbi))
1037 ret = -EINVAL;
1038 goto out;
1039 }
1040 str->hash = full_name_hash(dentry, norm, len);
1041out:
1042 kvfree(norm);
1043 return ret;
1044}
1045
1046const struct dentry_operations f2fs_dentry_ops = {
1047 .d_hash = f2fs_d_hash,
1048 .d_compare = f2fs_d_compare,
1049};
1050#endif