[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    cp and mv with -p preserve xattrs
From:       Dmitry Falko <dfalko () digiflak ! com>
Date:       2014-09-29 9:31:30
Message-ID: 542926F2.7020304 () digiflak ! com
[Download RAW message or body]

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 <dfalko@digiflak.com>
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 <dfalko@digiflak.com>, digiFLAK
+ *
+ * based on libattr code, original copyright:
+ * Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * 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
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic