1 /* $NetBSD: extattr.c,v 1.4 2012/03/13 21:13:34 christos Exp $ */
4 * Copyright (c) 2001 Robert N. M. Watson
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * TrustedBSD: Utility functions for extended attributes.
33 #include <sys/cdefs.h>
34 #if defined(LIBC_SCCS) && !defined(lint)
35 __RCSID("$NetBSD: extattr.c,v 1.4 2012/03/13 21:13:34 christos Exp $");
36 #endif /* LIBC_SCCS and not lint */
38 #include "namespace.h"
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/extattr.h>
48 const int extattr_namespaces
[] = {
49 EXTATTR_NAMESPACE_USER
,
50 EXTATTR_NAMESPACE_SYSTEM
,
55 extattr_namespace_to_string(int attrnamespace
, char **string
)
58 switch(attrnamespace
) {
59 case EXTATTR_NAMESPACE_USER
:
62 strdup(EXTATTR_NAMESPACE_USER_STRING
)) == NULL
)
67 case EXTATTR_NAMESPACE_SYSTEM
:
70 strdup(EXTATTR_NAMESPACE_SYSTEM_STRING
)) == NULL
)
81 extattr_string_to_namespace(const char *string
, int *attrnamespace
)
84 if (strcmp(string
, EXTATTR_NAMESPACE_USER_STRING
) == 0) {
85 if (attrnamespace
!= NULL
)
86 *attrnamespace
= EXTATTR_NAMESPACE_USER
;
88 } else if (strcmp(string
, EXTATTR_NAMESPACE_SYSTEM_STRING
) == 0) {
89 if (attrnamespace
!= NULL
)
90 *attrnamespace
= EXTATTR_NAMESPACE_SYSTEM
;
100 extattr_copy_fd(int from_fd
, int to_fd
, int namespace)
102 ssize_t llen
, vlen
, maxvlen
;
109 llen
= extattr_list_fd(from_fd
, namespace, NULL
, 0);
111 /* Silently ignore when EA are not supported */
112 if (errno
== EOPNOTSUPP
)
122 if ((alist
= malloc((size_t)llen
)) == NULL
)
125 llen
= extattr_list_fd(from_fd
, namespace, alist
, (size_t)llen
);
130 if ((aval
= malloc((size_t)maxvlen
)) == NULL
)
133 for (i
= 0; i
< (size_t)llen
; i
+= alen
+ 1) {
134 char aname
[NAME_MAX
+ 1];
137 alen
= ((uint8_t *)alist
)[i
];
138 ap
= ((char *)alist
) + i
+ 1;
139 (void)memcpy(aname
, ap
, alen
);
142 vlen
= extattr_get_fd(from_fd
, namespace, aname
, NULL
, 0);
146 if (vlen
> maxvlen
) {
147 if ((aval
= realloc(aval
, (size_t)vlen
)) == NULL
)
152 if ((vlen
= extattr_get_fd(from_fd
, namespace, aname
,
153 aval
, (size_t)vlen
)) == -1)
156 if (extattr_set_fd(to_fd
, namespace, aname
,
157 aval
, (size_t)vlen
) != vlen
)
173 extattr_copy_file(const char *from
, const char *to
, int namespace)
175 ssize_t llen
, vlen
, maxvlen
;
182 llen
= extattr_list_file(from
, namespace, NULL
, 0);
184 /* Silently ignore when EA are not supported */
185 if (errno
== EOPNOTSUPP
)
195 if ((alist
= malloc((size_t)llen
)) == NULL
)
198 llen
= extattr_list_file(from
, namespace, alist
, (size_t)llen
);
203 if ((aval
= malloc((size_t)maxvlen
)) == NULL
)
206 for (i
= 0; i
< (size_t)llen
; i
+= alen
+ 1) {
207 char aname
[NAME_MAX
+ 1];
210 alen
= ((uint8_t *)alist
)[i
];
211 ap
= ((char *)alist
) + i
+ 1;
212 (void)memcpy(aname
, ap
, alen
);
215 vlen
= extattr_get_file(from
, namespace, aname
, NULL
, 0);
219 if (vlen
> maxvlen
) {
220 if ((aval
= realloc(aval
, (size_t)vlen
)) == NULL
)
225 if ((vlen
= extattr_get_file(from
, namespace, aname
, aval
, (size_t)vlen
)) == -1)
228 if (extattr_set_file(to
, namespace, aname
,
229 aval
, (size_t)vlen
) != vlen
)
245 extattr_copy_link(const char *from
, const char *to
, int namespace)
247 ssize_t llen
, vlen
, maxvlen
;
254 llen
= extattr_list_link(from
, namespace, NULL
, 0);
256 /* Silently ignore when EA are not supported */
257 if (errno
== EOPNOTSUPP
)
267 if ((alist
= malloc((size_t)llen
)) == NULL
)
270 llen
= extattr_list_link(from
, namespace, alist
, (size_t)llen
);
275 if ((aval
= malloc((size_t)maxvlen
)) == NULL
)
278 for (i
= 0; i
< (size_t)llen
; i
+= alen
+ 1) {
279 char aname
[NAME_MAX
+ 1];
282 alen
= ((uint8_t *)alist
)[i
];
283 ap
= ((char *)alist
) + i
+ 1;
284 (void)memcpy(aname
, ap
, alen
);
287 vlen
= extattr_get_link(from
, namespace, aname
, NULL
, 0);
291 if (vlen
> maxvlen
) {
292 if ((aval
= realloc(aval
, (size_t)vlen
)) == NULL
)
297 if ((vlen
= extattr_get_link(from
, namespace, aname
,
298 aval
, (size_t)vlen
)) == -1)
301 if (extattr_set_link(to
, namespace, aname
,
302 aval
, (size_t)vlen
) != vlen
)
318 extattr_namespace_access(int namespace, int mode
)
321 case EXTATTR_NAMESPACE_SYSTEM
:
322 if ((mode
& (R_OK
|W_OK
)) && getuid() != 0)
333 fcpxattr(int from_fd
, int to_fd
)
338 for (ns
= extattr_namespaces
; *ns
; ns
++) {
339 if (extattr_namespace_access(*ns
, R_OK
|W_OK
) != 0)
342 if ((error
= extattr_copy_fd(from_fd
, to_fd
, *ns
)) != 0)
350 cpxattr(const char *from
, const char *to
)
355 for (ns
= extattr_namespaces
; *ns
; ns
++) {
356 if (extattr_namespace_access(*ns
, R_OK
|W_OK
) != 0)
359 if ((error
= extattr_copy_file(from
, to
, *ns
)) != 0)
367 lcpxattr(const char *from
, const char *to
)
372 for (ns
= extattr_namespaces
; *ns
; ns
++) {
373 if (extattr_namespace_access(*ns
, R_OK
|W_OK
) != 0)
376 if ((error
= extattr_copy_link(from
, to
, *ns
)) != 0)