aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDaniel Rosenberg <drosen@google.com>2017-03-01 17:04:41 -0800
committerMister Oyster <oysterized@gmail.com>2017-04-13 12:35:17 +0200
commitc4a6d2a0d8dc3d8130a91cb140e4cde45cb3aec4 (patch)
treee22f65a8a41cb7edd948e0c3f40a348a19e39048 /fs
parent8fb4e66f124f5ee122b55777e6ae56dab6a73fe3 (diff)
ANDROID: sdcardfs: Fix case insensitive lookup
The previous case insensitive lookup relied on the entry being present in the dcache. This instead uses iterate_dir to find the correct case. Signed-off-by: Daniel Rosenberg <drosen@google.com bug: 35633782 Change-Id: I556f7090773468c1943c89a5e2aa07f746ba49c5
Diffstat (limited to 'fs')
-rwxr-xr-xfs/sdcardfs/lookup.c68
1 files changed, 51 insertions, 17 deletions
diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c
index 08df46036..18ce7e4e3 100755
--- a/fs/sdcardfs/lookup.c
+++ b/fs/sdcardfs/lookup.c
@@ -211,6 +211,28 @@ out:
return err;
}
+struct sdcardfs_name_data {
+ struct dir_context ctx;
+ const struct qstr *to_find;
+ char *name;
+ bool found;
+};
+
+static int sdcardfs_name_match(void *__buf, const char *name, int namelen,
+ loff_t offset, u64 ino, unsigned int d_type)
+{
+ struct sdcardfs_name_data *buf = (struct sdcardfs_name_data *) __buf;
+ struct qstr candidate = QSTR_INIT(name, namelen);
+
+ if (qstr_case_eq(buf->to_find, &candidate)) {
+ memcpy(buf->name, name, namelen);
+ buf->name[namelen] = 0;
+ buf->found = true;
+ return 1;
+ }
+ return 0;
+}
+
/*
* Main driver function for sdcardfs's lookup.
*
@@ -247,27 +269,39 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
&lower_path);
/* check for other cases */
if (err == -ENOENT) {
- struct dentry *child;
- struct dentry *match = NULL;
- mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
- spin_lock(&lower_dir_dentry->d_lock);
- list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) {
- if (child && child->d_inode) {
- if (qstr_case_eq(&child->d_name, name)) {
- match = dget(child);
- break;
- }
- }
+ struct file *file;
+ const struct cred *cred = current_cred();
+
+ struct sdcardfs_name_data buffer = {
+ .ctx.actor = sdcardfs_name_match,
+ .to_find = name,
+ .name = __getname(),
+ .found = false,
+ };
+
+ if (!buffer.name) {
+ err = -ENOMEM;
+ goto out;
+ }
+ file = dentry_open(lower_parent_path, O_RDONLY, cred);
+ if (IS_ERR(file)) {
+ err = PTR_ERR(file);
+ goto put_name;
}
- spin_unlock(&lower_dir_dentry->d_lock);
- mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
- if (match) {
+ err = iterate_dir(file, &buffer.ctx);
+ fput(file);
+ if (err)
+ goto put_name;
+
+ if (buffer.found)
err = vfs_path_lookup(lower_dir_dentry,
lower_dir_mnt,
- match->d_name.name, 0,
+ buffer.name, 0,
&lower_path);
- dput(match);
- }
+ else
+ err = -ENOENT;
+put_name:
+ __putname(buffer.name);
}
/* no error: handle positive dentries */