xattr: simplify listxattr helpers
authorChristian Brauner <brauner@kernel.org>
Wed, 1 Feb 2023 13:14:52 +0000 (14:14 +0100)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Mon, 6 Mar 2023 08:57:07 +0000 (09:57 +0100)
The generic_listxattr() and simple_xattr_list() helpers list xattrs and
contain duplicated code. Add two helpers that both generic_listxattr()
and simple_xattr_list() can use.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
fs/posix_acl.c
fs/xattr.c
include/linux/posix_acl.h
include/linux/xattr.h

index 5a76fb35923a5de9c1e362cf1d849ee5d2650106..b350e8396adb4bae1e1d7d82e5938ccbd3c857be 100644 (file)
@@ -957,6 +957,31 @@ set_posix_acl(struct mnt_idmap *idmap, struct dentry *dentry,
 }
 EXPORT_SYMBOL(set_posix_acl);
 
+int posix_acl_listxattr(struct inode *inode, char **buffer,
+                       ssize_t *remaining_size)
+{
+       int err;
+
+       if (!IS_POSIXACL(inode))
+               return 0;
+
+       if (inode->i_acl) {
+               err = xattr_list_one(buffer, remaining_size,
+                                    XATTR_NAME_POSIX_ACL_ACCESS);
+               if (err)
+                       return err;
+       }
+
+       if (inode->i_default_acl) {
+               err = xattr_list_one(buffer, remaining_size,
+                                    XATTR_NAME_POSIX_ACL_DEFAULT);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static bool
 posix_acl_xattr_list(struct dentry *dentry)
 {
index 14a7eb3c8fa898ffb2a697968efb9eb70bd7bac2..1a35235ecc7355d082d3149e84615cf62705c562 100644 (file)
@@ -949,6 +949,21 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
        return error;
 }
 
+int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
+{
+       size_t len;
+
+       len = strlen(name) + 1;
+       if (*buffer) {
+               if (*remaining_size < len)
+                       return -ERANGE;
+               memcpy(*buffer, name, len);
+               *buffer += len;
+       }
+       *remaining_size -= len;
+       return 0;
+}
+
 /*
  * Combine the results of the list() operation from every xattr_handler in the
  * list.
@@ -957,33 +972,22 @@ ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
        const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
-       unsigned int size = 0;
-
-       if (!buffer) {
-               for_each_xattr_handler(handlers, handler) {
-                       if (!handler->name ||
-                           (handler->list && !handler->list(dentry)))
-                               continue;
-                       size += strlen(handler->name) + 1;
-               }
-       } else {
-               char *buf = buffer;
-               size_t len;
-
-               for_each_xattr_handler(handlers, handler) {
-                       if (!handler->name ||
-                           (handler->list && !handler->list(dentry)))
-                               continue;
-                       len = strlen(handler->name);
-                       if (len + 1 > buffer_size)
-                               return -ERANGE;
-                       memcpy(buf, handler->name, len + 1);
-                       buf += len + 1;
-                       buffer_size -= len + 1;
-               }
-               size = buf - buffer;
+       ssize_t remaining_size = buffer_size;
+       int err = 0;
+
+       err = posix_acl_listxattr(d_inode(dentry), &buffer, &remaining_size);
+       if (err)
+               return err;
+
+       for_each_xattr_handler(handlers, handler) {
+               if (!handler->name || (handler->list && !handler->list(dentry)))
+                       continue;
+               err = xattr_list_one(&buffer, &remaining_size, handler->name);
+               if (err)
+                       return err;
        }
-       return size;
+
+       return err ? err : buffer_size - remaining_size;
 }
 EXPORT_SYMBOL(generic_listxattr);
 
@@ -1245,20 +1249,6 @@ static bool xattr_is_trusted(const char *name)
        return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static int xattr_list_one(char **buffer, ssize_t *remaining_size,
-                         const char *name)
-{
-       size_t len = strlen(name) + 1;
-       if (*buffer) {
-               if (*remaining_size < len)
-                       return -ERANGE;
-               memcpy(*buffer, name, len);
-               *buffer += len;
-       }
-       *remaining_size -= len;
-       return 0;
-}
-
 /**
  * simple_xattr_list - list all xattr objects
  * @inode: inode from which to get the xattrs
@@ -1287,22 +1277,9 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
        ssize_t remaining_size = size;
        int err = 0;
 
-#ifdef CONFIG_FS_POSIX_ACL
-       if (IS_POSIXACL(inode)) {
-               if (inode->i_acl) {
-                       err = xattr_list_one(&buffer, &remaining_size,
-                                            XATTR_NAME_POSIX_ACL_ACCESS);
-                       if (err)
-                               return err;
-               }
-               if (inode->i_default_acl) {
-                       err = xattr_list_one(&buffer, &remaining_size,
-                                            XATTR_NAME_POSIX_ACL_DEFAULT);
-                       if (err)
-                               return err;
-               }
-       }
-#endif
+       err = posix_acl_listxattr(inode, &buffer, &remaining_size);
+       if (err)
+               return err;
 
        read_lock(&xattrs->lock);
        for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) {
index 21cc29b8a9e8d18000702316773d04a11d6d9ed9..0e65b3d634d9afd330ccfff3263142ffa1457aec 100644 (file)
@@ -106,6 +106,8 @@ struct posix_acl *vfs_get_acl(struct mnt_idmap *idmap,
                              struct dentry *dentry, const char *acl_name);
 int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
                   const char *acl_name);
+int posix_acl_listxattr(struct inode *inode, char **buffer,
+                       ssize_t *remaining_size);
 #else
 static inline int posix_acl_chmod(struct mnt_idmap *idmap,
                                  struct dentry *dentry, umode_t mode)
@@ -153,6 +155,11 @@ static inline int vfs_remove_acl(struct mnt_idmap *idmap,
 {
        return -EOPNOTSUPP;
 }
+static inline int posix_acl_listxattr(struct inode *inode, char **buffer,
+                                     ssize_t *remaining_size)
+{
+       return 0;
+}
 #endif /* CONFIG_FS_POSIX_ACL */
 
 struct posix_acl *get_inode_acl(struct inode *inode, int type);
index 6af72461397d425e9f99f33148450f06d6a9103e..ce8fb0bd56c6d719751564cc3f1b4e1f117e537a 100644 (file)
@@ -109,5 +109,6 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
                          char *buffer, size_t size);
 void simple_xattr_add(struct simple_xattrs *xattrs,
                      struct simple_xattr *new_xattr);
+int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name);
 
 #endif /* _LINUX_XATTR_H */