Hello to all!

On the work required to copy files with extended attributes, busybox cp(and mv), unfortunately, unlike the older brother did not know how to copy extended attributes, so I wrote a patch copying extended attributes (if the call command with the option -p), maybe it will be useful.

Perhaps the quality of the patch is not entirely satisfactory, so waiting for the critics.

From 5782979527f9498b7d39f4a63dbf05483fe66c5d Mon Sep 17 00:00:00 2001
From: Dmitry Falko <[email protected]>
Date: Mon, 29 Sep 2014 11:38:15 +0400
Subject: [PATCH] add feature copy xattrs of file if set flag preserve status
 to mv, cp

---
 include/libbb.h        |    5 +-
 libbb/Config.src       |    6 +++
 libbb/Kbuild.src       |    1 +
 libbb/copy_file.c      |    7 +++
libbb/copy_file_attr.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 136 insertions(+), 1 deletion(-)
 create mode 100644 libbb/copy_file_attr.c

diff --git a/include/libbb.h b/include/libbb.h
index e520060..4a16542 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -343,6 +343,10 @@ extern int remove_file(const char *path, int flags) FAST_FUNC;
  * work coreutils-compatibly. */
extern int copy_file(const char *source, const char *dest, int flags) FAST_FUNC;

+#if ENABLE_XATTR
+extern int copy_file_attr(const char *src_path, int src_fd, const char *dst_path, int dst_fd) FAST_FUNC;
+#endif
+
 enum {
     ACTION_RECURSE        = (1 << 0),
     ACTION_FOLLOWLINKS    = (1 << 1),
@@ -1262,7 +1266,6 @@ extern void selinux_preserve_fcontext(int fdesc) FAST_FUNC;
 #endif
 extern void selinux_or_die(void) FAST_FUNC;

-
 /* systemd support */
 #define SD_LISTEN_FDS_START 3
 int sd_listen_fds(void);
diff --git a/libbb/Config.src b/libbb/Config.src
index 19021fe..8615cb2 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -232,4 +232,10 @@ config FEATURE_HWIB
       Support for printing infiniband addresses in
       network applets.

+config XATTR
+    bool "Support preserve extended attributes for cp command"
+    default y
+    help
+      Support preserve extended attributes for cp and mv command.
+
 endmenu
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 61eec26..ec13b96 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -172,6 +172,7 @@ lib-$(CONFIG_TRACEROUTE6) += inet_cksum.o
 lib-$(CONFIG_UDHCPC) += inet_cksum.o
 lib-$(CONFIG_UDHCPC6) += inet_cksum.o
 lib-$(CONFIG_UDHCPD) += inet_cksum.o
+lib-$(CONFIG_XATTR) += copy_file_attr.o

# We shouldn't build xregcomp.c if we don't need it - this ensures we don't # require regex.h to be in the include dir even if we don't need it thereby
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index 9333a8d..6904e2b 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -314,6 +314,13 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
             }
         }
 #endif
+#if ENABLE_XATTR
+        /* Preserve extended attributes */
+        if(flags & FILEUTILS_PRESERVE_STATUS &&
+            copy_file_attr(source, src_fd, dest, dst_fd) == -1) {
+            return -1;
+        }
+#endif
         if (bb_copyfd_eof(src_fd, dst_fd) == -1)
             retval = -1;
         /* Careful with writing... */
diff --git a/libbb/copy_file_attr.c b/libbb/copy_file_attr.c
new file mode 100644
index 0000000..2e0c295
--- /dev/null
+++ b/libbb/copy_file_attr.c
@@ -0,0 +1,118 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copy extended attributes between files
+ *
+ * Copyright (C) 2014 Dmitry Falko <[email protected]>, digiFLAK
+ *
+ * based on libattr code, original copyright:
+ * Copyright (C) 1999-2005 by Erik Andersen <[email protected]>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#include "libbb.h"
+
+#if !defined(ENOTSUP)
+# define ENOTSUP (-1)
+#endif
+
+#if defined(HAVE_ALLOCA)
+# define bb_alloc(size) alloca (size)
+# define bb_free(ptr) do { } while(0)
+#else
+# define bb_alloc(size) xmalloc (size)
+# define bb_free(ptr) free (ptr)
+#endif
+
+/* Copy extended attributes from src_path to dst_path. If the file
+   has an extended Access ACL (system.posix_acl_access) and that is
+   copied successfully, the file mode permission bits are copied as
+   a side effect. This may not always the case, so the file mode
+   and/or ownership must be copied separately. */
+int FAST_FUNC copy_file_attr(const char *src_path, int src_fd,
+         const char *dst_path, int dst_fd)
+{
+    int ret = 0;
+    ssize_t size;
+    char *names = NULL, *end_names, *name, *value = NULL;
+    unsigned int setxattr_ENOTSUP = 0;
+
+    size = flistxattr (src_fd, NULL, 0);
+    if (size < 0) {
+        if (errno != ENOSYS && errno != ENOTSUP) {
+            bb_perror_msg("listing attributes of %s", src_path);
+            ret = -1;
+        }
+        goto getout;
+    }
+    names = (char *) bb_alloc (size+1);
+    if (names == NULL) {
+        bb_error_msg("cannot allocate buffer");
+        ret = -1;
+        goto getout;
+    }
+    size = flistxattr (src_fd, names, size);
+    if (size < 0) {
+        bb_error_msg("listing attributes of %s", src_path);
+        ret = -1;
+        goto getout;
+    } else {
+        names[size] = '\0';
+        end_names = names + size;
+    }
+
+    for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
+        void *old_value;
+
+        if (!*name)
+            continue;
+
+        size = fgetxattr (src_fd, name, NULL, 0);
+        if (size < 0) {
+            bb_error_msg("getting attribute %s of %s",
+                   src_path, name);
+            ret = -1;
+            continue;
+        }
+        value = (char *) xrealloc (old_value = value, size);
+        if (size != 0 && value == NULL) {
+            free(old_value);
+            bb_error_msg(" failed to realloc ");
+            ret = -1;
+        }
+        size = fgetxattr (src_fd, name, value, size);
+        if (size < 0) {
+            bb_error_msg("getting attribute %s of %s",
+                   src_path, name);
+            ret = -1;
+            continue;
+        }
+        if (fsetxattr (dst_fd, name, value, size, 0) != 0) {
+            if (errno == ENOTSUP)
+                setxattr_ENOTSUP++;
+            else {
+                if (errno == ENOSYS) {
+                    bb_error_msg("setting attributes for "
+                           "%s", dst_path);
+                    ret = -1;
+                    break;  /* no hope of getting any further */
+                } else {
+                    bb_error_msg("setting attribute %s for %s",
+                           name, dst_path);
+                    ret = -1;
+                }
+            }
+        }
+    }
+    if (setxattr_ENOTSUP) {
+        errno = ENOTSUP;
+        /* ignore this error */
+        bb_error_msg("setting attributes for %s", dst_path);
+        ret = 0;
+    }
+getout:
+    free (value);
+    bb_free (names);
+    return ret;
+}
+
--
1.7.9.5



--
Best Regards, Dmitry!

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to