Search
SailfishOS Open Build Service
>
Projects
>
home:elros34
:
glibc
>
busybox
> _service:tar_git:0001-Copy-extended-attributes-if-p-flag-is-provided-to-cp.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File _service:tar_git:0001-Copy-extended-attributes-if-p-flag-is-provided-to-cp.patch of Package busybox
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Kalle Jokiniemi <kalle.jokiniemi@jolla.com> Date: Thu, 16 Jul 2015 11:46:16 +0300 Subject: [PATCH] Copy extended attributes if -p flag is provided to cp, mv. Contributes to JB#30370 Doing a full file system copy of root is not currently possible when busybox cp does not support copying extended attributes. Added this patch from Dimitry Falko, which adds xattr support when using "-p" option. This behaviour slightly differs from coreutils cp. Original cp copying only ACLs and not copying executable file capabilities on "-p". To copy all extended attributes with coreutils cp the option "--preserve=all" must be used. At this time of applying, the patch has not been merged to upstream busybox. This patch was fixed by copying attributes after chown() called because it resets file capabilities. Signed-off-by: Igor Zhbanov <igor.zhbanov@jolla.com> --- include/libbb.h | 3 + libbb/Config.src | 6 ++ libbb/Kbuild.src | 2 + libbb/copy_file.c | 7 +++ libbb/copy_file_attr.c | 125 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 libbb/copy_file_attr.c diff --git a/include/libbb.h b/include/libbb.h index cae54658b..d3f67b5fb 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -457,6 +457,9 @@ extern int remove_file(const char *path, int flags) FAST_FUNC; * This makes "cp /dev/null file" and "install /dev/null file" (!!!) * 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, const char *dst_path) FAST_FUNC; +#endif enum { ACTION_RECURSE = (1 << 0), diff --git a/libbb/Config.src b/libbb/Config.src index f97de8ef7..520966791 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -395,3 +395,9 @@ config FEATURE_HWIB default y help 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. diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 676300801..bb5ecb9ef 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -199,3 +199,5 @@ lib-$(CONFIG_FEATURE_FIND_REGEX) += xregcomp.o # Add the experimental logging functionality, only used by zcip lib-$(CONFIG_ZCIP) += logenv.o + +lib-$(CONFIG_XATTR) += copy_file_attr.o diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 49d1ec9c6..0f64a1e31 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -434,6 +434,13 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) source_stat.st_mode &= ~(S_ISUID | S_ISGID); bb_perror_msg("can't preserve %s of '%s'", "ownership", dest); } +#if ENABLE_XATTR + /* Preserve extended attributes. We must copy it after chown() + * because it resets capabilities. */ + if (copy_file_attr(source, dest) == -1) + bb_perror_msg("can't preserve %s of '%s'", + "extended attributes", dest); +#endif if (chmod(dest, source_stat.st_mode) < 0) bb_perror_msg("can't preserve %s of '%s'", "permissions", dest); } diff --git a/libbb/copy_file_attr.c b/libbb/copy_file_attr.c new file mode 100644 index 000000000..180b0311e --- /dev/null +++ b/libbb/copy_file_attr.c @@ -0,0 +1,125 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copy extended attributes between files + * + * Copyright (C) 2014 Dmitry Falko <dfalko@digiflak.com>, digiFLAK + * Fixed by Igor Zhbanov <igor.zhbanov@jolla.com> + * + * 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 <sys/types.h> +#include <sys/xattr.h> + +#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, const char *dst_path) +{ + int ret = 0; + ssize_t size; + char *names = NULL, *end_names, *name, *value = NULL; + unsigned int setxattr_ENOTSUP = 0; + + if ((size = listxattr(src_path, NULL, 0)) < 0) { + if (errno != ENOSYS && errno != ENOTSUP) { + bb_perror_msg("listing attributes of %s", src_path); + ret = -1; + } + + goto getout; + } + + if (!(names = (char *)bb_alloc(size + 1))) { + bb_error_msg("cannot allocate buffer"); + ret = -1; + goto getout; + } + + if ((size = listxattr(src_path, names, 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; + + if ((size = getxattr(src_path, name, NULL, 0)) < 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) { + free(old_value); + bb_error_msg("failed to realloc"); + ret = -1; + } + + if ((size = getxattr(src_path, name, value, size)) < 0) { + bb_error_msg("getting attribute %s of %s", + src_path, name); + ret = -1; + continue; + } + + if (setxattr(dst_path, 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; + /* no hope of getting any further */ + break; + } 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; +} -- 2.31.1