diff options
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r-- | fs/ext4/namei.c | 43 |
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 | */ |
1267 | int ext4_ci_compare(const struct inode *parent, const struct qstr *name, | 1268 | int 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 | |||
1296 | void 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); |