Commit 26e8a8ac authored by Kalle Jokiniemi's avatar Kalle Jokiniemi

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: default avatarIgor Zhbanov <igor.zhbanov@jolla.com>
parent a679bff2
......@@ -342,6 +342,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),
......
......@@ -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
......@@ -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
......
......@@ -314,6 +314,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
}
}
#endif
if (bb_copyfd_eof(src_fd, dst_fd) == -1)
retval = -1;
/* Careful with writing... */
......@@ -385,6 +386,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);
}
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment