summaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index cd01c4a67ffb..4909ced4e672 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1259,19 +1259,24 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
1259#ifdef CONFIG_UNICODE 1259#ifdef CONFIG_UNICODE
1260/* 1260/*
1261 * Test whether a case-insensitive directory entry matches the filename 1261 * Test whether a case-insensitive directory entry matches the filename
1262 * being searched for. 1262 * being searched for. If quick is set, assume the name being looked up
1263 * is already in the casefolded form.
1263 * 1264 *
1264 * Returns: 0 if the directory entry matches, more than 0 if it 1265 * Returns: 0 if the directory entry matches, more than 0 if it
1265 * doesn't match or less than zero on error. 1266 * doesn't match or less than zero on error.
1266 */ 1267 */
1267int ext4_ci_compare(const struct inode *parent, const struct qstr *name, 1268int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
1268 const struct qstr *entry) 1269 const struct qstr *entry, bool quick)
1269{ 1270{
1270 const struct ext4_sb_info *sbi = EXT4_SB(parent->i_sb); 1271 const struct ext4_sb_info *sbi = EXT4_SB(parent->i_sb);
1271 const struct unicode_map *um = sbi->s_encoding; 1272 const struct unicode_map *um = sbi->s_encoding;
1272 int ret; 1273 int ret;
1273 1274
1274 ret = utf8_strncasecmp(um, name, entry); 1275 if (quick)
1276 ret = utf8_strncasecmp_folded(um, name, entry);
1277 else
1278 ret = utf8_strncasecmp(um, name, entry);
1279
1275 if (ret < 0) { 1280 if (ret < 0) {
1276 /* Handle invalid character sequence as either an error 1281 /* Handle invalid character sequence as either an error
1277 * or as an opaque byte sequence. 1282 * or as an opaque byte sequence.
@@ -1287,6 +1292,27 @@ int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
1287 1292
1288 return ret; 1293 return ret;
1289} 1294}
1295
1296void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
1297 struct fscrypt_str *cf_name)
1298{
1299 if (!IS_CASEFOLDED(dir)) {
1300 cf_name->name = NULL;
1301 return;
1302 }
1303
1304 cf_name->name = kmalloc(EXT4_NAME_LEN, GFP_NOFS);
1305 if (!cf_name->name)
1306 return;
1307
1308 cf_name->len = utf8_casefold(EXT4_SB(dir->i_sb)->s_encoding,
1309 iname, cf_name->name,
1310 EXT4_NAME_LEN);
1311 if (cf_name->len <= 0) {
1312 kfree(cf_name->name);
1313 cf_name->name = NULL;
1314 }
1315}
1290#endif 1316#endif
1291 1317
1292/* 1318/*
@@ -1313,8 +1339,15 @@ static inline bool ext4_match(const struct inode *parent,
1313#endif 1339#endif
1314 1340
1315#ifdef CONFIG_UNICODE 1341#ifdef CONFIG_UNICODE
1316 if (EXT4_SB(parent->i_sb)->s_encoding && IS_CASEFOLDED(parent)) 1342 if (EXT4_SB(parent->i_sb)->s_encoding && IS_CASEFOLDED(parent)) {
1317 return (ext4_ci_compare(parent, fname->usr_fname, &entry) == 0); 1343 if (fname->cf_name.name) {
1344 struct qstr cf = {.name = fname->cf_name.name,
1345 .len = fname->cf_name.len};
1346 return !ext4_ci_compare(parent, &cf, &entry, true);
1347 }
1348 return !ext4_ci_compare(parent, fname->usr_fname, &entry,
1349 false);
1350 }
1318#endif 1351#endif
1319 1352
1320 return fscrypt_match_name(&f, de->name, de->name_len); 1353 return fscrypt_match_name(&f, de->name, de->name_len);