tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: cp/mv and extended attributes preservation



On Tue, Jul 26, 2011 at 11:30:06PM -0400, Mouse wrote:
> > The only problem with putting it in a library is that we will need to
> > decide what API we [w]ant to promote: the ugly one from FreeBSD or
> > the [one] from Linux.
> 
> Or we could invent our own.
> All the cool ki^W^Wother OSes are doing it.

Here is a patch that implements extended attribute copying routines
in libc, with both FreeBSD and Linux flavors:
extattr_copy_file extattr_copy_fd extattr_copy_link
cpxattr fcpxattr lcpxattr

cp -p and mv to a different filesystem use them (well, just the fcpxattr,
actually).

If nobody has concern about it, I will commit it shortly.

-- 
Emmanuel Dreyfus
manu%netbsd.org@localhost
Index: bin/cp/cp.c
===================================================================
RCS file: /cvsroot/src/bin/cp/cp.c,v
retrieving revision 1.55
diff -U4 -r1.55 cp.c
--- bin/cp/cp.c 6 Feb 2011 12:37:49 -0000       1.55
+++ bin/cp/cp.c 2 Aug 2011 07:00:18 -0000
@@ -196,8 +196,15 @@
        /* Copy the umask for explicit mode setting. */
        myumask = umask(0);
        (void)umask(myumask);
 
+       /* 
+        * Warn that system extended attributes will not be preserved 
+        * if not root
+        */
+       if ((myuid != 0) && pflag)
+               warnx("system extended attribute will not be preserved");
+
        /* Save the target base in "to". */
        target = argv[--argc];
        if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path))
                errx(EXIT_FAILURE, "%s: name too long", target);
Index: bin/cp/utils.c
===================================================================
RCS file: /cvsroot/src/bin/cp/utils.c,v
retrieving revision 1.39
diff -U4 -r1.39 utils.c
--- bin/cp/utils.c      6 Feb 2011 12:37:49 -0000       1.39
+++ bin/cp/utils.c      2 Aug 2011 07:00:18 -0000
@@ -41,8 +41,9 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/extattr.h>
 
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -226,8 +227,11 @@
                        }
                }
        }
 
+       if (pflag && (fcpxattr(from_fd, to_fd) != 0))
+               warn("%s: error copying extended attributes", to.p_path);
+
        (void)close(from_fd);
 
        if (rval == 1) {
                (void)close(to_fd);
Index: bin/mv/mv.c
===================================================================
RCS file: /cvsroot/src/bin/mv/mv.c,v
retrieving revision 1.41
diff -U4 -r1.41 mv.c
--- bin/mv/mv.c 20 Jul 2008 00:52:40 -0000      1.41
+++ bin/mv/mv.c 2 Aug 2011 07:00:19 -0000
@@ -49,8 +49,9 @@
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <sys/extattr.h>
 
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -289,8 +290,12 @@
                (void)close(from_fd);
                (void)close(to_fd);
                return (1);
        }
+
+       if (fcpxattr(from_fd, to_fd) == -1)
+               warn("%s: error copying extended attributes", to);
+
        (void)close(from_fd);
 #ifdef BSD4_4
        TIMESPEC_TO_TIMEVAL(&tval[0], &sbp->st_atimespec);
        TIMESPEC_TO_TIMEVAL(&tval[1], &sbp->st_mtimespec);
Index: distrib/sets/lists/comp/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v
retrieving revision 1.1651
diff -U4 -r1.1651 mi
--- distrib/sets/lists/comp/mi  31 Jul 2011 03:48:49 -0000      1.1651
+++ distrib/sets/lists/comp/mi  2 Aug 2011 07:00:27 -0000
@@ -5972,8 +5973,9 @@
 ./usr/share/man/cat3/cpuset_isset.0            comp-c-catman           .cat
 ./usr/share/man/cat3/cpuset_set.0              comp-c-catman           .cat
 ./usr/share/man/cat3/cpuset_size.0             comp-c-catman           .cat
 ./usr/share/man/cat3/cpuset_zero.0             comp-c-catman           .cat
+./usr/share/man/cat3/cpxattr.0                 comp-c-catman           .cat
 ./usr/share/man/cat3/creal.0                   comp-c-catman           
complex,.cat
 ./usr/share/man/cat3/crealf.0                  comp-c-catman           
complex,.cat
 ./usr/share/man/cat3/creall.0                  comp-c-catman           
complex,.cat
 ./usr/share/man/cat3/creat.0                   comp-c-catman           .cat
@@ -6329,16 +6331,20 @@
 ./usr/share/man/cat3/expf.0                    comp-c-catman           .cat
 ./usr/share/man/cat3/expm1.0                   comp-c-catman           .cat
 ./usr/share/man/cat3/expm1f.0                  comp-c-catman           .cat
 ./usr/share/man/cat3/extattr.0                 comp-c-catman           .cat
+./usr/share/man/cat3/extattr_copy_fd.0         comp-c-catman           .cat
+./usr/share/man/cat3/extattr_copy_file.0       comp-c-catman           .cat
+./usr/share/man/cat3/extattr_copy_link.0       comp-c-catman           .cat
 ./usr/share/man/cat3/extattr_namespace_to_string.0     comp-c-catman           
.cat
 ./usr/share/man/cat3/extattr_string_to_namespace.0     comp-c-catman           
.cat
 ./usr/share/man/cat3/fabs.0                    comp-c-catman           .cat
 ./usr/share/man/cat3/fabsf.0                   comp-c-catman           .cat
 ./usr/share/man/cat3/fast_divide32.0           comp-c-catman           .cat
 ./usr/share/man/cat3/fast_divide32_prepare.0   comp-c-catman           .cat
 ./usr/share/man/cat3/fast_remainder32.0                comp-c-catman           
.cat
 ./usr/share/man/cat3/fclose.0                  comp-c-catman           .cat
+./usr/share/man/cat3/fcpxattr.0                        comp-c-catman           
.cat
 ./usr/share/man/cat3/fdim.0                    comp-c-catman           .cat
 ./usr/share/man/cat3/fdimf.0                   comp-c-catman           .cat
 ./usr/share/man/cat3/fdiml.0                   comp-c-catman           .cat
 ./usr/share/man/cat3/fdopen.0                  comp-c-catman           .cat
@@ -7506,8 +7512,9 @@
 ./usr/share/man/cat3/lber-memory.0             comp-ldap-catman        
ldap,.cat
 ./usr/share/man/cat3/lber-sockbuf.0            comp-ldap-catman        
ldap,.cat
 ./usr/share/man/cat3/lber-types.0              comp-ldap-catman        
ldap,.cat
 ./usr/share/man/cat3/lcong48.0                 comp-c-catman           .cat
+./usr/share/man/cat3/lcpxattr.0                        comp-c-catman           
.cat
 ./usr/share/man/cat3/ld_errno.0                        comp-ldap-catman        
ldap,.cat
 ./usr/share/man/cat3/ldap.0                    comp-ldap-catman        
ldap,.cat
 ./usr/share/man/cat3/ldap_abandon.0            comp-ldap-catman        
ldap,.cat
 ./usr/share/man/cat3/ldap_abandon_ext.0                comp-ldap-catman        
ldap,.cat
@@ -12080,8 +12088,9 @@
 ./usr/share/man/html3/cpuset_isset.html                comp-c-htmlman          
html
 ./usr/share/man/html3/cpuset_set.html          comp-c-htmlman          html
 ./usr/share/man/html3/cpuset_size.html         comp-c-htmlman          html
 ./usr/share/man/html3/cpuset_zero.html         comp-c-htmlman          html
+./usr/share/man/html3/cpxattr.html             comp-c-htmlman          html
 ./usr/share/man/html3/creal.html               comp-c-htmlman          
complex,html
 ./usr/share/man/html3/crealf.html              comp-c-htmlman          
complex,html
 ./usr/share/man/html3/creall.html              comp-c-htmlman          
complex,html
 ./usr/share/man/html3/creat.html               comp-c-htmlman          html
@@ -12435,16 +12444,20 @@
 ./usr/share/man/html3/expf.html                        comp-c-htmlman          
html
 ./usr/share/man/html3/expm1.html               comp-c-htmlman          html
 ./usr/share/man/html3/expm1f.html              comp-c-htmlman          html
 ./usr/share/man/html3/extattr.html             comp-c-htmlman          html
+./usr/share/man/html3/extattr_copy_fd.html     comp-c-htmlman          html
+./usr/share/man/html3/extattr_copy_file.html   comp-c-htmlman          html
+./usr/share/man/html3/extattr_copy_link.html   comp-c-htmlman          html
 ./usr/share/man/html3/extattr_namespace_to_string.html comp-c-htmlman          
html
 ./usr/share/man/html3/extattr_string_to_namespace.html comp-c-htmlman          
html
 ./usr/share/man/html3/fabs.html                        comp-c-htmlman          
html
 ./usr/share/man/html3/fabsf.html               comp-c-htmlman          html
 ./usr/share/man/html3/fast_divide32.html               comp-c-htmlman          
html
 ./usr/share/man/html3/fast_divide32_prepare.html       comp-c-htmlman          
html
 ./usr/share/man/html3/fast_remainder32.html            comp-c-htmlman          
html
 ./usr/share/man/html3/fclose.html              comp-c-htmlman          html
+./usr/share/man/html3/fcpxattr.html            comp-c-htmlman          html
 ./usr/share/man/html3/fdim.html                        comp-c-htmlman          
html
 ./usr/share/man/html3/fdimf.html               comp-c-htmlman          html
 ./usr/share/man/html3/fdiml.html               comp-c-htmlman          html
 ./usr/share/man/html3/fdopen.html              comp-c-htmlman          html
@@ -13589,8 +13602,9 @@
 ./usr/share/man/html3/lber-memory.html         comp-ldap-htmlman       
ldap,html
 ./usr/share/man/html3/lber-sockbuf.html                comp-ldap-htmlman       
ldap,html
 ./usr/share/man/html3/lber-types.html          comp-ldap-htmlman       
ldap,html
 ./usr/share/man/html3/lcong48.html             comp-c-htmlman          html
+./usr/share/man/html3/lcpxattr.html            comp-c-htmlman          html
 ./usr/share/man/html3/ld_errno.html            comp-ldap-htmlman       
ldap,html
 ./usr/share/man/html3/ldap.html                        comp-ldap-htmlman       
ldap,html
 ./usr/share/man/html3/ldap_abandon.html                comp-ldap-htmlman       
ldap,html
 ./usr/share/man/html3/ldap_abandon_ext.html    comp-ldap-htmlman       
ldap,html
@@ -18095,8 +18110,9 @@
 ./usr/share/man/man3/cpuset_isset.3            comp-c-man              .man
 ./usr/share/man/man3/cpuset_set.3              comp-c-man              .man
 ./usr/share/man/man3/cpuset_size.3             comp-c-man              .man
 ./usr/share/man/man3/cpuset_zero.3             comp-c-man              .man
+./usr/share/man/man3/cpxattr.3                 comp-c-man              .man
 ./usr/share/man/man3/creal.3                   comp-c-man              
complex,.man
 ./usr/share/man/man3/crealf.3                  comp-c-man              
complex,.man
 ./usr/share/man/man3/creall.3                  comp-c-man              
complex,.man
 ./usr/share/man/man3/creat.3                   comp-c-man              .man
@@ -18452,16 +18468,20 @@
 ./usr/share/man/man3/expf.3                    comp-c-man              .man
 ./usr/share/man/man3/expm1.3                   comp-c-man              .man
 ./usr/share/man/man3/expm1f.3                  comp-c-man              .man
 ./usr/share/man/man3/extattr.3                 comp-c-man              .man
+./usr/share/man/man3/extattr_copy_fd.3         comp-c-man              .man
+./usr/share/man/man3/extattr_copy_file.3       comp-c-man              .man
+./usr/share/man/man3/extattr_copy_link.3       comp-c-man              .man
 ./usr/share/man/man3/extattr_namespace_to_string.3     comp-c-man              
.man
 ./usr/share/man/man3/extattr_string_to_namespace.3     comp-c-man              
.man
 ./usr/share/man/man3/fabs.3                    comp-c-man              .man
 ./usr/share/man/man3/fabsf.3                   comp-c-man              .man
 ./usr/share/man/man3/fast_divide32.3           comp-c-man              .man
 ./usr/share/man/man3/fast_divide32_prepare.3   comp-c-man              .man
 ./usr/share/man/man3/fast_remainder32.3                comp-c-man              
.man
 ./usr/share/man/man3/fclose.3                  comp-c-man              .man
+./usr/share/man/man3/fcpxattr.3                        comp-c-man              
.man
 ./usr/share/man/man3/fdim.3                    comp-c-man              .man
 ./usr/share/man/man3/fdimf.3                   comp-c-man              .man
 ./usr/share/man/man3/fdiml.3                   comp-c-man              .man
 ./usr/share/man/man3/fdopen.3                  comp-c-man              .man
@@ -19629,8 +19649,9 @@
 ./usr/share/man/man3/lber-memory.3             comp-ldap-man           
ldap,.man
 ./usr/share/man/man3/lber-sockbuf.3            comp-ldap-man           
ldap,.man
 ./usr/share/man/man3/lber-types.3              comp-ldap-man           
ldap,.man
 ./usr/share/man/man3/lcong48.3                 comp-c-man              .man
+./usr/share/man/man3/lcpxattr.3                        comp-c-man              
.man
 ./usr/share/man/man3/ld_errno.3                        comp-ldap-man           
ldap,.man
 ./usr/share/man/man3/ldap.3                    comp-ldap-man           
ldap,.man
 ./usr/share/man/man3/ldap_abandon.3            comp-ldap-man           
ldap,.man
 ./usr/share/man/man3/ldap_abandon_ext.3                comp-ldap-man           
ldap,.man
Index: lib/libc/gen/Makefile.inc
===================================================================
RCS file: /cvsroot/src/lib/libc/gen/Makefile.inc,v
retrieving revision 1.178
diff -U4 -r1.178 Makefile.inc
--- lib/libc/gen/Makefile.inc   26 Mar 2011 19:51:42 -0000      1.178
+++ lib/libc/gen/Makefile.inc   2 Aug 2011 07:02:56 -0000
@@ -92,9 +92,15 @@
         err.3 warnx.3 err.3 vwarnx.3
 MLINKS+=exec.3 execl.3 exec.3 execle.3 exec.3 execlp.3 exec.3 execv.3 \
        exec.3 execvp.3 exec.3 exect.3
 MLINKS+=extattr.3 extattr_namespace_to_string.3 \
-       extattr.3 extattr_string_to_namespace.3
+       extattr.3 extattr_string_to_namespace.3 \
+       extattr.3 extattr_copy_file.3 \
+       extattr.3 extattr_copy_fd.3 \
+       extattr.3 extattr_copy_link.3 \
+       extattr.3 cpxattr.3 \
+       extattr.3 fcpxattr.3 \
+       extattr.3 lcpxattr.3
 MLINKS+=fpgetmask.3 fpgetround.3 fpgetmask.3 fpgetsticky.3 \
        fpgetmask.3 fpsetmask.3  fpgetmask.3 fpsetround.3 \
        fpgetmask.3 fpsetsticky.3 fpgetmask.3 fpgetprec.3 \
        fpgetmask.3 fpsetprec.3
Index: lib/libc/gen/extattr.3
===================================================================
RCS file: /cvsroot/src/lib/libc/gen/extattr.3,v
retrieving revision 1.3
diff -U4 -r1.3 extattr.3
--- lib/libc/gen/extattr.3      2 Jan 2005 18:25:09 -0000       1.3
+++ lib/libc/gen/extattr.3      2 Aug 2011 07:02:56 -0000
@@ -1,7 +1,8 @@
 .\"    $NetBSD: extattr.3,v 1.3 2005/01/02 18:25:09 wiz Exp $
 .\"
 .\" Copyright (c) 2001 Dima Dorfman <dd%FreeBSD.org@localhost>
+.\" Copyright (c) 2011 Emmanuel Dreyfus <manu%NetBSD.org@localhost>
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
@@ -32,16 +33,35 @@
 .Sh NAME
 .Nm extattr_namespace_to_string ,
 .Nm extattr_string_to_namespace
 .Nd convert an extended attribute namespace identifier to a string and vice 
versa
+.Nm extattr_copy_file ,
+.Nm extattr_copy_fd ,
+.Nm extattr_copy_link ,
+.Nm cpxattr ,
+.Nm fcpxattr ,
+.Nm lcpxattr 
+.Nd copy extended attributes from a file to another one
 .Sh LIBRARY
 .Lb libc
 .Sh SYNOPSIS
 .In sys/extattr.h
 .Ft int
 .Fn extattr_namespace_to_string "int attrnamespace" "char **string"
 .Ft int
 .Fn extattr_string_to_namespace "const char *string" "int *attrnamespace"
+.Ft int
+.Fn extattr_copy_file "const char *from" "const char *to" "int namespace"
+.Ft int
+.Fn extattr_copy_fd "int from_fd" "int to_fd" "int namespace"
+.Ft int
+.Fn extattr_copy_link "const char *from" "const char *to" "int namespace"
+.Ft int
+.Fn cpxattr "const char *from" "const char *to"
+.Ft int
+.Fn fcpxattr "int from_fd" "int to_fd"
+.Ft int
+.Fn lcpxattr "const char *from" "const char *to"
 .Sh DESCRIPTION
 The
 .Fn extattr_namespace_to_string
 function converts a VFS extended attribute identifier to a human-readable
@@ -73,8 +93,33 @@
 instead of requiring a user to enter the integer representing a namespace,
 an interactive program might ask for a name and use
 .Fn extattr_string_to_namespace
 to get the desired identifier.
+.Pp
+.Fn extattr_copy_file
+copies extended attributes of namespace
+.Ar namespace
+from a file to another one.
+.Fn extattr_copy_fd 
+does the same using open file descriptors, and
+.Fn extattr_copy_link
+does the same as
+.Fn extattr_copy_file
+but operates on symbolic links themselves instead of their targets.
+.Pp
+.Fn cpxattr ,
+.Fn fcpxattr ,
+and
+.Fn lcpxattr
+respectively work the same was as 
+.Fn extattr_copy_file ,
+.Fn extattr_copy_fd ,
+and
+.Fn extattr_copy_link ,
+but will copy extended attributes from all namespaces accessible to the user,
+silently skiping unaccessible namespaces.
+.Pp
+Please note that none of the extended attribute copying functions are atomic.
 .Sh RETURN VALUES
 If any of the calls are unsuccessful, the value \-1 is returned
 and the global variable
 .Va errno
@@ -83,8 +128,13 @@
 .Bl -tag -width Er
 .It Bq Er EINVAL
 The requested namespace could not be identified.
 .El
+.Pp
+Extended attribute copying functions may also raise errors produced by
+.Fn extattr_list_file 
+and
+.Fn extattr_get_file .
 .Sh SEE ALSO
 .Xr getextattr 1 ,
 .Xr extattr_get_file 2 ,
 .Xr extattr 9
Index: lib/libc/gen/extattr.c
===================================================================
RCS file: /cvsroot/src/lib/libc/gen/extattr.c,v
retrieving revision 1.2
diff -U4 -r1.2 extattr.c
--- lib/libc/gen/extattr.c      9 Feb 2005 21:35:46 -0000       1.2
+++ lib/libc/gen/extattr.c      2 Aug 2011 07:02:56 -0000
@@ -36,13 +36,22 @@
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
 #include <sys/types.h>
+#include <sys/param.h>
 #include <sys/extattr.h>
 
 #include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
 #include <string.h>
 
+const int extattr_namespaces[] = {
+       EXTATTR_NAMESPACE_USER,
+       EXTATTR_NAMESPACE_SYSTEM,
+       0,
+};  
+
 int
 extattr_namespace_to_string(int attrnamespace, char **string)
 {
 
@@ -84,4 +93,289 @@
                errno = EINVAL;
                return (-1);
        }
 }
+
+
+int
+extattr_copy_fd(int from_fd, int to_fd, int namespace)
+{
+       ssize_t llen, vlen, maxvlen;
+       size_t alen;
+       void *alist = NULL;
+       void *aval = NULL;
+       int i;
+       int error = -1;
+
+       llen = extattr_list_fd(from_fd, namespace, 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, namespace, alist, (size_t)llen);
+       if (llen == -1)
+               goto out;
+
+       maxvlen = 1024;
+       if ((aval = malloc((size_t)maxvlen)) == NULL)
+               goto out;
+
+       for (i = 0; i < 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, namespace, 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, namespace, aname,
+                                     aval, (size_t)vlen)) == -1)
+                       goto out;
+       
+               if (extattr_set_fd(to_fd, namespace, aname,
+                                  aval, (size_t)vlen) != vlen)
+                       goto out;
+       }
+
+       error = 0;
+out:
+       if (aval != NULL)
+               free(aval);
+       
+       if (alist != NULL)
+               free(alist);
+       
+       return error;
+}
+
+int
+extattr_copy_file(const char *from, const char *to, int namespace)
+{
+       ssize_t llen, vlen, maxvlen;
+       size_t alen;
+       void *alist = NULL;
+       void *aval = NULL;
+       int i;
+       int error = -1;
+
+       llen = extattr_list_file(from, namespace, 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_file(from, namespace, alist, (size_t)llen);
+       if (llen == -1)
+               goto out;
+
+       maxvlen = 1024;
+       if ((aval = malloc((size_t)maxvlen)) == NULL)
+               goto out;
+
+       for (i = 0; i < 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_file(from, namespace, 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_file(from, namespace, aname,            
                                             aval, (size_t)vlen)) == -1)
+                       goto out;
+       
+               if (extattr_set_file(to, namespace, aname,
+                                    aval, (size_t)vlen) != vlen)
+                       goto out;
+       }
+
+       error = 0;
+out:
+       if (aval != NULL)
+               free(aval);
+       
+       if (alist != NULL)
+               free(alist);
+       
+       return error;
+}
+
+int
+extattr_copy_link(const char *from, const char *to, int namespace)
+{
+       ssize_t llen, vlen, maxvlen;
+       size_t alen;
+       void *alist = NULL;
+       void *aval = NULL;
+       int i;
+       int error = -1;
+
+       llen = extattr_list_link(from, namespace, 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_link(from, namespace, alist, (size_t)llen);
+       if (llen == -1)
+               goto out;
+
+       maxvlen = 1024;
+       if ((aval = malloc((size_t)maxvlen)) == NULL)
+               goto out;
+
+       for (i = 0; i < 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_link(from, namespace, 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_link(from, namespace, aname,
+                                            aval, (size_t)vlen)) == -1)
+                       goto out;
+       
+               if (extattr_set_link(to, namespace, aname,
+                                    aval, (size_t)vlen) != vlen)
+                       goto out;
+       }
+
+       error = 0;
+out:
+       if (aval != NULL)
+               free(aval);
+       
+       if (alist != NULL)
+               free(alist);
+       
+       return error;
+}
+
+static int
+extattr_namespace_access(int namespace, int mode)
+{
+       switch (namespace) {
+       case EXTATTR_NAMESPACE_SYSTEM:
+               if ((mode & (R_OK|W_OK)) && getuid() != 0)
+                       return -1;
+               break;
+       default:
+               break;
+       }
+       
+       return 0;
+}
+
+int
+fcpxattr(int from_fd, int to_fd)
+{
+       const int *ns;
+       int error;
+
+       for (ns = extattr_namespaces; *ns; ns++) {
+               if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
+                       continue;
+       
+               if ((error = extattr_copy_fd(from_fd, to_fd, *ns)) != 0)
+                       return error;
+       }
+
+       return 0;
+}
+
+int
+cpxattr(const char *from, const char *to)
+{
+       const int *ns;
+       int error;
+
+       for (ns = extattr_namespaces; *ns; ns++) {
+               if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
+                       continue;
+       
+               if ((error = extattr_copy_file(from, to, *ns)) != 0)
+                       return error;
+       }
+
+       return 0;
+}
+
+int
+lcpxattr(const char *from, const char *to)
+{
+       const int *ns;
+       int error;
+
+       for (ns = extattr_namespaces; *ns; ns++) {
+               if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
+                       continue;
+       
+               if ((error = extattr_copy_link(from, to, *ns)) != 0)
+                       return error;
+       }
+
+       return 0;
+}
Index: lib/libc/sys/extattr_get_file.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/extattr_get_file.2,v
retrieving revision 1.3
diff -U4 -r1.3 extattr_get_file.2
--- lib/libc/sys/extattr_get_file.2     2 Jan 2005 18:28:48 -0000       1.3
+++ lib/libc/sys/extattr_get_file.2     2 Aug 2011 07:02:57 -0000
@@ -96,10 +96,12 @@
 .Fn extattr_delete_file
 system call deletes the extended attribute specified.
 The
 .Fn extattr_list_file
-returns a list of attributes present in the requested namespace, separated
-by ASCII 0 (nul) characters.
+returns a list of attributes present in the requested namespace.
+Each list entry consists of a single byte containing the length
+of the attribute name, followed by the attribute name.
+The attribute name is not terminated by ASCII 0 (nul).
 The
 .Fn extattr_get_file
 and
 .Fn extattr_list_file
@@ -253,4 +255,8 @@
 .Sh CAVEATS
 This interface is under active development, and as such is subject to
 change as applications are adapted to use it.
 Developers are discouraged from relying on its stability.
+.Pp
+Note that previous versions of this man page incorrectly stated that
+.Fn extattr_list_file 
+returned a list of attribute names separated by ASCII 0 (nul).
Index: sys/sys/extattr.h
===================================================================
RCS file: /cvsroot/src/sys/sys/extattr.h,v
retrieving revision 1.6
diff -U4 -r1.6 extattr.h
--- sys/sys/extattr.h   4 Jul 2011 08:07:31 -0000       1.6
+++ sys/sys/extattr.h   2 Aug 2011 07:03:38 -0000
@@ -93,10 +93,19 @@
            const char *_attrname, const void *_data, size_t _nbytes);
 int    extattr_set_link(const char *_path, int _attrnamespace,
            const char *_attrname, const void *_data, size_t _nbytes);
 
+extern const int extattr_namespaces[];
+
 int    extattr_namespace_to_string(int, char **);
 int    extattr_string_to_namespace(const char *, int *);
+int    extattr_copy_fd(int _from_fd, int _to_fd, int _namespace);
+int    extattr_copy_file(const char *_from, const char *_to, int _namespace);
+int    extattr_copy_link(const char *_from, const char *_to, int _namespace);
+
+int    fcpxattr(int _from_fd, int _to_fd);
+int    cpxattr(const char *_from, const char *_to);
+int    lcpxattr(const char *_from, const char *_to);
 __END_DECLS
 
 #endif /* !_KERNEL */
 #endif /* !_SYS_EXTATTR_H_ */


Home | Main Index | Thread Index | Old Index