Instantly share code, notes, and snippets.

Embed
What would you like to do?
Патч для утилиты cp ОС FreeBSD 11.2.0-RELEASE, добавляющий функционал копирования расширенных атрибутов файла. Подробнее: https://habr.com/post/425795/
--- /usr/src/bin/cp/extern.h.orig
+++ /usr/src/bin/cp/extern.h
@@ -49,4 +49,5 @@
int preserve_dir_acls(struct stat *, char *, char *);
int preserve_fd_acls(int, int);
void usage(void);
+int user_extattr_copy_fd(int, int);
__END_DECLS
--- /usr/src/bin/cp/utils.c.orig
+++ /usr/src/bin/cp/utils.c
@@ -39,6 +39,7 @@
#include <sys/acl.h>
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/extattr.h>
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
#include <sys/mman.h>
#endif
@@ -50,6 +51,7 @@
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sysexits.h>
#include <unistd.h>
@@ -262,6 +264,8 @@
rval = 1;
if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
rval = 1;
+ if(user_extattr_copy_fd(from_fd, to_fd) != 0)
+ rval = 1;
if (close(to_fd)) {
warn("%s", to.p_path);
rval = 1;
@@ -557,3 +561,76 @@
"target_directory");
exit(EX_USAGE);
}
+
+int
+user_extattr_copy_fd(int from_fd, int to_fd)
+{
+ ssize_t llen, vlen, maxvlen;
+ size_t alen;
+ void *alist = NULL;
+ void *aval = NULL;
+ size_t i;
+ int error = -1;
+
+ llen = extattr_list_fd(from_fd, EXTATTR_NAMESPACE_USER, NULL, 0);
+ if (llen == -1) {
+ /* Silently ignore when EA are not supported */
+ if (errno == EOPNOTSUPP)
+ error = 0;
+ goto out;
+ }
+
+ if (llen == 0) {
+ error = 0;
+ goto out;
+ }
+
+ if ((alist = malloc((size_t)llen)) == NULL)
+ goto out;
+
+ llen = extattr_list_fd(from_fd, EXTATTR_NAMESPACE_USER, alist, (size_t)llen);
+ if (llen == -1)
+ goto out;
+
+ maxvlen = 1024;
+ if ((aval = malloc((size_t)maxvlen)) == NULL)
+ goto out;
+
+ for (i = 0; i < (size_t)llen; i += alen + 1) {
+ char aname[NAME_MAX + 1];
+ char *ap;
+
+ alen = ((uint8_t *)alist)[i];
+ ap = ((char *)alist) + i + 1;
+ (void)memcpy(aname, ap, alen);
+ aname[alen] = '\0';
+
+ vlen = extattr_get_fd(from_fd, EXTATTR_NAMESPACE_USER, aname, NULL, 0);
+ if (vlen == -1)
+ goto out;
+
+ if (vlen > maxvlen) {
+ if ((aval = realloc(aval, (size_t)vlen)) == NULL)
+ goto out;
+ maxvlen = vlen;
+ }
+
+ if ((vlen = extattr_get_fd(from_fd, EXTATTR_NAMESPACE_USER, aname,
+ aval, (size_t)vlen)) == -1)
+ goto out;
+
+ if (extattr_set_fd(to_fd, EXTATTR_NAMESPACE_USER, aname,
+ aval, (size_t)vlen) != vlen)
+ goto out;
+ }
+
+ error = 0;
+out:
+ if (aval != NULL)
+ free(aval);
+
+ if (alist != NULL)
+ free(alist);
+
+ return error;
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment