]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: support copying in xattrs
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:24:23 +0000 (16:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:28 +0000 (18:01 -0800)
Update the protofile code to import extended attributes from the source
files.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
mkfs/proto.c

index 6946c22ff14d2a24db6eb4336461c31c9c89f401..7a0493ec71cfd95403e3a449bc9f11b766fc048b 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "libxfs.h"
 #include <sys/stat.h>
+#include <sys/xattr.h>
+#include <linux/xattr.h>
 #include "libfrog/convert.h"
 #include "proto.h"
 
@@ -359,6 +361,97 @@ writefile(
                fail(_("error committing isize transaction"), error);
 }
 
+static void
+writeattr(
+       struct xfs_inode        *ip,
+       const char              *fname,
+       int                     fd,
+       const char              *attrname,
+       char                    *valuebuf,
+       size_t                  valuelen)
+{
+       struct xfs_da_args      args = {
+               .dp             = ip,
+               .geo            = ip->i_mount->m_attr_geo,
+               .owner          = ip->i_ino,
+               .whichfork      = XFS_ATTR_FORK,
+               .op_flags       = XFS_DA_OP_OKNOENT,
+               .value          = valuebuf,
+       };
+       ssize_t                 ret;
+       int                     error;
+
+       ret = fgetxattr(fd, attrname, valuebuf, valuelen);
+       if (ret < 0) {
+               if (errno == EOPNOTSUPP)
+                       return;
+               fail(_("error collecting xattr value"), errno);
+       }
+       if (ret == 0)
+               return;
+
+       if (!strncmp(attrname, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
+               args.name = (unsigned char *)attrname + XATTR_TRUSTED_PREFIX_LEN;
+               args.attr_filter = LIBXFS_ATTR_ROOT;
+       } else if (!strncmp(attrname, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
+               args.name = (unsigned char *)attrname + XATTR_SECURITY_PREFIX_LEN;
+               args.attr_filter = LIBXFS_ATTR_SECURE;
+       } else if (!strncmp(attrname, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
+               args.name = (unsigned char *)attrname + XATTR_USER_PREFIX_LEN;
+               args.attr_filter = 0;
+       } else {
+               args.name = (unsigned char *)attrname;
+               args.attr_filter = 0;
+       }
+       args.namelen = strlen((char *)args.name);
+
+       args.valuelen = ret;
+       libxfs_attr_sethash(&args);
+
+       error = -libxfs_attr_set(&args, XFS_ATTRUPDATE_UPSERT, false);
+       if (error)
+               fail(_("setting xattr value"), error);
+}
+
+static void
+writeattrs(
+       struct xfs_inode        *ip,
+       const char              *fname,
+       int                     fd)
+{
+       char                    *namebuf, *p, *end;
+       char                    *valuebuf = NULL;
+       ssize_t                 ret;
+
+       namebuf = malloc(XATTR_LIST_MAX);
+       if (!namebuf)
+               fail(_("error allocating xattr name buffer"), errno);
+
+       ret = flistxattr(fd, namebuf, XATTR_LIST_MAX);
+       if (ret < 0) {
+               if (errno == EOPNOTSUPP)
+                       goto out_namebuf;
+               fail(_("error collecting xattr names"), errno);
+       }
+
+       p = namebuf;
+       end = namebuf + ret;
+       for (p = namebuf; p < end; p += strlen(p) + 1) {
+               if (!valuebuf) {
+                       valuebuf = malloc(ATTR_MAX_VALUELEN);
+                       if (!valuebuf)
+                               fail(_("error allocating xattr value buffer"),
+                                               errno);
+               }
+
+               writeattr(ip, fname, fd, p, valuebuf, ATTR_MAX_VALUELEN);
+       }
+
+       free(valuebuf);
+out_namebuf:
+       free(namebuf);
+}
+
 static int
 newregfile(
        char            **pp,
@@ -833,6 +926,7 @@ parseproto(
        libxfs_parent_finish(mp, ppargs);
        if (fmt == IF_REGULAR) {
                writefile(ip, fname, fd);
+               writeattrs(ip, fname, fd);
                close(fd);
        }
        libxfs_irele(ip);