From 764a5c6b1fa4306dd7573c1d80914254909cd036 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 2 Dec 2015 14:44:43 +0100 Subject: xattr handlers: Simplify list operation Change the list operation to only return whether or not an attribute should be listed. Copying the attribute names into the buffer is moved to the callers. Since the result only depends on the dentry and not on the attribute name, we do not pass the attribute name to list operations. Signed-off-by: Andreas Gruenbacher Signed-off-by: Al Viro --- fs/f2fs/xattr.c | 82 ++++++++++++++++++--------------------------------------- 1 file changed, 26 insertions(+), 56 deletions(-) (limited to 'fs/f2fs/xattr.c') diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 21cfe516034f..036952a945fa 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -25,40 +25,6 @@ #include "f2fs.h" #include "xattr.h" -static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler, - struct dentry *dentry, char *list, size_t list_size, - const char *name, size_t len) -{ - struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); - const char *prefix; - int total_len, prefix_len; - - switch (handler->flags) { - case F2FS_XATTR_INDEX_USER: - if (!test_opt(sbi, XATTR_USER)) - return -EOPNOTSUPP; - break; - case F2FS_XATTR_INDEX_TRUSTED: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - break; - case F2FS_XATTR_INDEX_SECURITY: - break; - default: - return -EINVAL; - } - - prefix = xattr_prefix(handler); - prefix_len = strlen(prefix); - total_len = prefix_len + len + 1; - if (list && total_len <= list_size) { - memcpy(list, prefix, prefix_len); - memcpy(list + prefix_len, name, len); - list[prefix_len + len] = '\0'; - } - return total_len; -} - static int f2fs_xattr_generic_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) @@ -107,17 +73,16 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler, value, size, NULL, flags); } -static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler, - struct dentry *dentry, char *list, size_t list_size, - const char *name, size_t len) +static bool f2fs_xattr_user_list(struct dentry *dentry) { - const char *xname = F2FS_SYSTEM_ADVISE_NAME; - size_t size; + struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); + + return test_opt(sbi, XATTR_USER); +} - size = strlen(xname) + 1; - if (list && size <= list_size) - memcpy(list, xname, size); - return size; +static bool f2fs_xattr_trusted_list(struct dentry *dentry) +{ + return capable(CAP_SYS_ADMIN); } static int f2fs_xattr_advise_get(const struct xattr_handler *handler, @@ -175,7 +140,7 @@ int f2fs_init_security(struct inode *inode, struct inode *dir, const struct xattr_handler f2fs_xattr_user_handler = { .prefix = XATTR_USER_PREFIX, .flags = F2FS_XATTR_INDEX_USER, - .list = f2fs_xattr_generic_list, + .list = f2fs_xattr_user_list, .get = f2fs_xattr_generic_get, .set = f2fs_xattr_generic_set, }; @@ -183,7 +148,7 @@ const struct xattr_handler f2fs_xattr_user_handler = { const struct xattr_handler f2fs_xattr_trusted_handler = { .prefix = XATTR_TRUSTED_PREFIX, .flags = F2FS_XATTR_INDEX_TRUSTED, - .list = f2fs_xattr_generic_list, + .list = f2fs_xattr_trusted_list, .get = f2fs_xattr_generic_get, .set = f2fs_xattr_generic_set, }; @@ -191,7 +156,6 @@ const struct xattr_handler f2fs_xattr_trusted_handler = { const struct xattr_handler f2fs_xattr_advise_handler = { .name = F2FS_SYSTEM_ADVISE_NAME, .flags = F2FS_XATTR_INDEX_ADVISE, - .list = f2fs_xattr_advise_list, .get = f2fs_xattr_advise_get, .set = f2fs_xattr_advise_set, }; @@ -199,7 +163,6 @@ const struct xattr_handler f2fs_xattr_advise_handler = { const struct xattr_handler f2fs_xattr_security_handler = { .prefix = XATTR_SECURITY_PREFIX, .flags = F2FS_XATTR_INDEX_SECURITY, - .list = f2fs_xattr_generic_list, .get = f2fs_xattr_generic_get, .set = f2fs_xattr_generic_set, }; @@ -447,20 +410,27 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) list_for_each_xattr(entry, base_addr) { const struct xattr_handler *handler = f2fs_xattr_handler(entry->e_name_index); + const char *prefix; + size_t prefix_len; size_t size; - if (!handler) + if (!handler || (handler->list && !handler->list(dentry))) continue; - size = handler->list(handler, dentry, buffer, rest, - entry->e_name, entry->e_name_len); - if (buffer && size > rest) { - error = -ERANGE; - goto cleanup; + prefix = handler->prefix ?: handler->name; + prefix_len = strlen(prefix); + size = prefix_len + entry->e_name_len + 1; + if (buffer) { + if (size > rest) { + error = -ERANGE; + goto cleanup; + } + memcpy(buffer, prefix, prefix_len); + buffer += prefix_len; + memcpy(buffer, entry->e_name, entry->e_name_len); + buffer += entry->e_name_len; + *buffer++ = 0; } - - if (buffer) - buffer += size; rest -= size; } error = buffer_size - rest; -- cgit v1.2.3