Module Name:    src
Committed By:   manu
Date:           Wed Aug  3 04:11:17 UTC 2011

Modified Files:
        src/bin/cp: cp.c utils.c
        src/bin/mv: mv.c
        src/distrib/sets/lists/comp: mi
        src/lib/libc/gen: Makefile.inc extattr.3 extattr.c
        src/lib/libc/sys: extattr_get_file.2
        src/sys/sys: extattr.h

Log Message:
Make cp -p and mv preverve extended attributes, and complain if they cannot.

Also introduce library functions for copying extended attributes from one
file to another:
- extattr_copy_file, extattr_copy_fd, extattr_copy_link, with FreeBSD style,
  where a namespace is to be supplied
- cpxattr, fcpxattr, lcpxattr, with Linux style, where all namespaces
  accessible to the caller are copied, and the others are silently ignored.


To generate a diff of this commit:
cvs rdiff -u -r1.55 -r1.56 src/bin/cp/cp.c
cvs rdiff -u -r1.39 -r1.40 src/bin/cp/utils.c
cvs rdiff -u -r1.41 -r1.42 src/bin/mv/mv.c
cvs rdiff -u -r1.1651 -r1.1652 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.178 -r1.179 src/lib/libc/gen/Makefile.inc
cvs rdiff -u -r1.3 -r1.4 src/lib/libc/gen/extattr.3
cvs rdiff -u -r1.2 -r1.3 src/lib/libc/gen/extattr.c
cvs rdiff -u -r1.3 -r1.4 src/lib/libc/sys/extattr_get_file.2
cvs rdiff -u -r1.6 -r1.7 src/sys/sys/extattr.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/cp/cp.c
diff -u src/bin/cp/cp.c:1.55 src/bin/cp/cp.c:1.56
--- src/bin/cp/cp.c:1.55	Sun Feb  6 12:37:49 2011
+++ src/bin/cp/cp.c	Wed Aug  3 04:11:15 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: cp.c,v 1.55 2011/02/06 12:37:49 darcy Exp $ */
+/* $NetBSD: cp.c,v 1.56 2011/08/03 04:11:15 manu Exp $ */
 
 /*
  * Copyright (c) 1988, 1993, 1994
@@ -43,7 +43,7 @@
 #if 0
 static char sccsid[] = "@(#)cp.c	8.5 (Berkeley) 4/29/95";
 #else
-__RCSID("$NetBSD: cp.c,v 1.55 2011/02/06 12:37:49 darcy Exp $");
+__RCSID("$NetBSD: cp.c,v 1.56 2011/08/03 04:11:15 manu Exp $");
 #endif
 #endif /* not lint */
 
@@ -197,6 +197,13 @@
 	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))

Index: src/bin/cp/utils.c
diff -u src/bin/cp/utils.c:1.39 src/bin/cp/utils.c:1.40
--- src/bin/cp/utils.c:1.39	Sun Feb  6 12:37:49 2011
+++ src/bin/cp/utils.c	Wed Aug  3 04:11:15 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: utils.c,v 1.39 2011/02/06 12:37:49 darcy Exp $ */
+/* $NetBSD: utils.c,v 1.40 2011/08/03 04:11:15 manu Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)utils.c	8.3 (Berkeley) 4/1/94";
 #else
-__RCSID("$NetBSD: utils.c,v 1.39 2011/02/06 12:37:49 darcy Exp $");
+__RCSID("$NetBSD: utils.c,v 1.40 2011/08/03 04:11:15 manu Exp $");
 #endif
 #endif /* not lint */
 
@@ -42,6 +42,7 @@
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/extattr.h>
 
 #include <err.h>
 #include <errno.h>
@@ -227,6 +228,9 @@
 		}
 	}
 
+	if (pflag && (fcpxattr(from_fd, to_fd) != 0))
+		warn("%s: error copying extended attributes", to.p_path);
+
 	(void)close(from_fd);
 
 	if (rval == 1) {

Index: src/bin/mv/mv.c
diff -u src/bin/mv/mv.c:1.41 src/bin/mv/mv.c:1.42
--- src/bin/mv/mv.c:1.41	Sun Jul 20 00:52:40 2008
+++ src/bin/mv/mv.c	Wed Aug  3 04:11:15 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: mv.c,v 1.41 2008/07/20 00:52:40 lukem Exp $ */
+/* $NetBSD: mv.c,v 1.42 2011/08/03 04:11:15 manu Exp $ */
 
 /*
  * Copyright (c) 1989, 1993, 1994
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)mv.c	8.2 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: mv.c,v 1.41 2008/07/20 00:52:40 lukem Exp $");
+__RCSID("$NetBSD: mv.c,v 1.42 2011/08/03 04:11:15 manu Exp $");
 #endif
 #endif /* not lint */
 
@@ -50,6 +50,7 @@
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <sys/extattr.h>
 
 #include <err.h>
 #include <errno.h>
@@ -290,6 +291,10 @@
 		(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);

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.1651 src/distrib/sets/lists/comp/mi:1.1652
--- src/distrib/sets/lists/comp/mi:1.1651	Sun Jul 31 03:48:49 2011
+++ src/distrib/sets/lists/comp/mi	Wed Aug  3 04:11:15 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.1651 2011/07/31 03:48:49 dholland Exp $
+#	$NetBSD: mi,v 1.1652 2011/08/03 04:11:15 manu Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -5973,6 +5973,7 @@
 ./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
@@ -6330,6 +6331,9 @@
 ./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
@@ -6338,6 +6342,7 @@
 ./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
@@ -7507,6 +7512,7 @@
 ./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
@@ -12081,6 +12087,7 @@
 ./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
@@ -12436,6 +12443,9 @@
 ./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
@@ -12444,6 +12454,7 @@
 ./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
@@ -13590,6 +13601,7 @@
 ./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
@@ -18096,6 +18108,7 @@
 ./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
@@ -18453,6 +18466,9 @@
 ./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
@@ -18461,6 +18477,7 @@
 ./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
@@ -19630,6 +19647,7 @@
 ./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

Index: src/lib/libc/gen/Makefile.inc
diff -u src/lib/libc/gen/Makefile.inc:1.178 src/lib/libc/gen/Makefile.inc:1.179
--- src/lib/libc/gen/Makefile.inc:1.178	Sat Mar 26 19:51:42 2011
+++ src/lib/libc/gen/Makefile.inc	Wed Aug  3 04:11:16 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.178 2011/03/26 19:51:42 christos Exp $
+#	$NetBSD: Makefile.inc,v 1.179 2011/08/03 04:11:16 manu Exp $
 #	from: @(#)Makefile.inc	8.6 (Berkeley) 5/4/95
 
 # gen sources
@@ -93,7 +93,13 @@
 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 \

Index: src/lib/libc/gen/extattr.3
diff -u src/lib/libc/gen/extattr.3:1.3 src/lib/libc/gen/extattr.3:1.4
--- src/lib/libc/gen/extattr.3:1.3	Sun Jan  2 18:25:09 2005
+++ src/lib/libc/gen/extattr.3	Wed Aug  3 04:11:17 2011
@@ -1,6 +1,7 @@
-.\"	$NetBSD: extattr.3,v 1.3 2005/01/02 18:25:09 wiz Exp $
+.\"	$NetBSD: extattr.3,v 1.4 2011/08/03 04:11:17 manu Exp $
 .\"
 .\" Copyright (c) 2001 Dima Dorfman <[email protected]>
+.\" Copyright (c) 2011 Emmanuel Dreyfus <[email protected]>
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -33,6 +34,13 @@
 .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
@@ -41,6 +49,18 @@
 .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
@@ -74,6 +94,31 @@
 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
@@ -84,6 +129,11 @@
 .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 ,

Index: src/lib/libc/gen/extattr.c
diff -u src/lib/libc/gen/extattr.c:1.2 src/lib/libc/gen/extattr.c:1.3
--- src/lib/libc/gen/extattr.c:1.2	Wed Feb  9 21:35:46 2005
+++ src/lib/libc/gen/extattr.c	Wed Aug  3 04:11:17 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: extattr.c,v 1.2 2005/02/09 21:35:46 kleink Exp $	*/
+/*	$NetBSD: extattr.c,v 1.3 2011/08/03 04:11:17 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 Robert N. M. Watson
@@ -32,16 +32,25 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: extattr.c,v 1.2 2005/02/09 21:35:46 kleink Exp $");
+__RCSID("$NetBSD: extattr.c,v 1.3 2011/08/03 04:11:17 manu Exp $");
 #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)
 {
@@ -85,3 +94,288 @@
 		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: src/lib/libc/sys/extattr_get_file.2
diff -u src/lib/libc/sys/extattr_get_file.2:1.3 src/lib/libc/sys/extattr_get_file.2:1.4
--- src/lib/libc/sys/extattr_get_file.2:1.3	Sun Jan  2 18:28:48 2005
+++ src/lib/libc/sys/extattr_get_file.2	Wed Aug  3 04:11:17 2011
@@ -1,4 +1,4 @@
-.\"	$NetBSD: extattr_get_file.2,v 1.3 2005/01/02 18:28:48 wiz Exp $
+.\"	$NetBSD: extattr_get_file.2,v 1.4 2011/08/03 04:11:17 manu Exp $
 .\"
 .\" Copyright (c) 2001 Dima Dorfman <[email protected]>
 .\" Copyright (c) 2003 Robert Watson <[email protected]>
@@ -97,8 +97,10 @@
 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
@@ -254,3 +256,7 @@
 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: src/sys/sys/extattr.h
diff -u src/sys/sys/extattr.h:1.6 src/sys/sys/extattr.h:1.7
--- src/sys/sys/extattr.h:1.6	Mon Jul  4 08:07:31 2011
+++ src/sys/sys/extattr.h	Wed Aug  3 04:11:17 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: extattr.h,v 1.6 2011/07/04 08:07:31 manu Exp $	*/
+/*	$NetBSD: extattr.h,v 1.7 2011/08/03 04:11:17 manu Exp $	*/
 
 /*-
  * Copyright (c) 1999-2001 Robert N. M. Watson
@@ -94,8 +94,17 @@
 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 */

Reply via email to