Home | History | Annotate | Line # | Download | only in gen
extattr.c revision 1.3.2.1
      1 /*	$NetBSD: extattr.c,v 1.3.2.1 2012/04/17 00:05:18 yamt Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2001 Robert N. M. Watson
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     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.
     15  *
     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
     26  * SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * TrustedBSD: Utility functions for extended attributes.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 #if defined(LIBC_SCCS) && !defined(lint)
     35 __RCSID("$NetBSD: extattr.c,v 1.3.2.1 2012/04/17 00:05:18 yamt Exp $");
     36 #endif /* LIBC_SCCS and not lint */
     37 
     38 #include "namespace.h"
     39 #include <sys/types.h>
     40 #include <sys/param.h>
     41 #include <sys/extattr.h>
     42 
     43 #include <errno.h>
     44 #include <unistd.h>
     45 #include <stdlib.h>
     46 #include <string.h>
     47 
     48 const int extattr_namespaces[] = {
     49 	EXTATTR_NAMESPACE_USER,
     50 	EXTATTR_NAMESPACE_SYSTEM,
     51 	0,
     52 };
     53 
     54 int
     55 extattr_namespace_to_string(int attrnamespace, char **string)
     56 {
     57 
     58 	switch(attrnamespace) {
     59 	case EXTATTR_NAMESPACE_USER:
     60 		if (string != NULL) {
     61 			if ((*string =
     62 			     strdup(EXTATTR_NAMESPACE_USER_STRING)) == NULL)
     63 				return (-1);
     64 		}
     65 		return (0);
     66 
     67 	case EXTATTR_NAMESPACE_SYSTEM:
     68 		if (string != NULL)
     69 			if ((*string =
     70 			     strdup(EXTATTR_NAMESPACE_SYSTEM_STRING)) == NULL)
     71 				return (-1);
     72 		return (0);
     73 
     74 	default:
     75 		errno = EINVAL;
     76 		return (-1);
     77 	}
     78 }
     79 
     80 int
     81 extattr_string_to_namespace(const char *string, int *attrnamespace)
     82 {
     83 
     84 	if (strcmp(string, EXTATTR_NAMESPACE_USER_STRING) == 0) {
     85 		if (attrnamespace != NULL)
     86 			*attrnamespace = EXTATTR_NAMESPACE_USER;
     87 		return (0);
     88 	} else if (strcmp(string, EXTATTR_NAMESPACE_SYSTEM_STRING) == 0) {
     89 		if (attrnamespace != NULL)
     90 			*attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
     91 		return (0);
     92 	} else {
     93 		errno = EINVAL;
     94 		return (-1);
     95 	}
     96 }
     97 
     98 
     99 int
    100 extattr_copy_fd(int from_fd, int to_fd, int namespace)
    101 {
    102 	ssize_t llen, vlen, maxvlen;
    103 	size_t alen;
    104 	void *alist = NULL;
    105 	void *aval = NULL;
    106 	size_t i;
    107 	int error = -1;
    108 
    109 	llen = extattr_list_fd(from_fd, namespace, NULL, 0);
    110 	if (llen == -1) {
    111 		/* Silently ignore when EA are not supported */
    112 		if (errno == EOPNOTSUPP)
    113 			error = 0;
    114 		goto out;
    115 	}
    116 
    117 	if (llen == 0) {
    118 		error = 0;
    119 		goto out;
    120 	}
    121 
    122 	if ((alist = malloc((size_t)llen)) == NULL)
    123 		goto out;
    124 
    125 	llen = extattr_list_fd(from_fd, namespace, alist, (size_t)llen);
    126 	if (llen == -1)
    127 		goto out;
    128 
    129 	maxvlen = 1024;
    130 	if ((aval = malloc((size_t)maxvlen)) == NULL)
    131 		goto out;
    132 
    133 	for (i = 0; i < (size_t)llen; i += alen + 1) {
    134 		char aname[NAME_MAX + 1];
    135 		char *ap;
    136 
    137 		alen = ((uint8_t *)alist)[i];
    138 		ap = ((char *)alist) + i + 1;
    139 		(void)memcpy(aname, ap, alen);
    140 		aname[alen] = '\0';
    141 
    142 		vlen = extattr_get_fd(from_fd, namespace, aname, NULL, 0);
    143 		if (vlen == -1)
    144 			goto out;
    145 
    146 		if (vlen > maxvlen) {
    147 			if ((aval = realloc(aval, (size_t)vlen)) == NULL)
    148 				goto out;
    149 			maxvlen = vlen;
    150 		}
    151 
    152 		if ((vlen = extattr_get_fd(from_fd, namespace, aname,
    153 				      aval, (size_t)vlen)) == -1)
    154 			goto out;
    155 
    156 		if (extattr_set_fd(to_fd, namespace, aname,
    157 				   aval, (size_t)vlen) != vlen)
    158 			goto out;
    159 	}
    160 
    161 	error = 0;
    162 out:
    163 	if (aval != NULL)
    164 		free(aval);
    165 
    166 	if (alist != NULL)
    167 		free(alist);
    168 
    169 	return error;
    170 }
    171 
    172 int
    173 extattr_copy_file(const char *from, const char *to, int namespace)
    174 {
    175 	ssize_t llen, vlen, maxvlen;
    176 	size_t alen;
    177 	void *alist = NULL;
    178 	void *aval = NULL;
    179 	size_t i;
    180 	int error = -1;
    181 
    182 	llen = extattr_list_file(from, namespace, NULL, 0);
    183 	if (llen == -1) {
    184 		/* Silently ignore when EA are not supported */
    185 		if (errno == EOPNOTSUPP)
    186 			error = 0;
    187 		goto out;
    188 	}
    189 
    190 	if (llen == 0) {
    191 		error = 0;
    192 		goto out;
    193 	}
    194 
    195 	if ((alist = malloc((size_t)llen)) == NULL)
    196 		goto out;
    197 
    198 	llen = extattr_list_file(from, namespace, alist, (size_t)llen);
    199 	if (llen == -1)
    200 		goto out;
    201 
    202 	maxvlen = 1024;
    203 	if ((aval = malloc((size_t)maxvlen)) == NULL)
    204 		goto out;
    205 
    206 	for (i = 0; i < (size_t)llen; i += alen + 1) {
    207 		char aname[NAME_MAX + 1];
    208 		char *ap;
    209 
    210 		alen = ((uint8_t *)alist)[i];
    211 		ap = ((char *)alist) + i + 1;
    212 		(void)memcpy(aname, ap, alen);
    213 		aname[alen] = '\0';
    214 
    215 		vlen = extattr_get_file(from, namespace, aname, NULL, 0);
    216 		if (vlen == -1)
    217 			goto out;
    218 
    219 		if (vlen > maxvlen) {
    220 			if ((aval = realloc(aval, (size_t)vlen)) == NULL)
    221 				goto out;
    222 			maxvlen = vlen;
    223 		}
    224 
    225 		if ((vlen = extattr_get_file(from, namespace, aname,							     aval, (size_t)vlen)) == -1)
    226 			goto out;
    227 
    228 		if (extattr_set_file(to, namespace, aname,
    229 				     aval, (size_t)vlen) != vlen)
    230 			goto out;
    231 	}
    232 
    233 	error = 0;
    234 out:
    235 	if (aval != NULL)
    236 		free(aval);
    237 
    238 	if (alist != NULL)
    239 		free(alist);
    240 
    241 	return error;
    242 }
    243 
    244 int
    245 extattr_copy_link(const char *from, const char *to, int namespace)
    246 {
    247 	ssize_t llen, vlen, maxvlen;
    248 	size_t alen;
    249 	void *alist = NULL;
    250 	void *aval = NULL;
    251 	size_t i;
    252 	int error = -1;
    253 
    254 	llen = extattr_list_link(from, namespace, NULL, 0);
    255 	if (llen == -1) {
    256 		/* Silently ignore when EA are not supported */
    257 		if (errno == EOPNOTSUPP)
    258 			error = 0;
    259 		goto out;
    260 	}
    261 
    262 	if (llen == 0) {
    263 		error = 0;
    264 		goto out;
    265 	}
    266 
    267 	if ((alist = malloc((size_t)llen)) == NULL)
    268 		goto out;
    269 
    270 	llen = extattr_list_link(from, namespace, alist, (size_t)llen);
    271 	if (llen == -1)
    272 		goto out;
    273 
    274 	maxvlen = 1024;
    275 	if ((aval = malloc((size_t)maxvlen)) == NULL)
    276 		goto out;
    277 
    278 	for (i = 0; i < (size_t)llen; i += alen + 1) {
    279 		char aname[NAME_MAX + 1];
    280 		char *ap;
    281 
    282 		alen = ((uint8_t *)alist)[i];
    283 		ap = ((char *)alist) + i + 1;
    284 		(void)memcpy(aname, ap, alen);
    285 		aname[alen] = '\0';
    286 
    287 		vlen = extattr_get_link(from, namespace, aname, NULL, 0);
    288 		if (vlen == -1)
    289 			goto out;
    290 
    291 		if (vlen > maxvlen) {
    292 			if ((aval = realloc(aval, (size_t)vlen)) == NULL)
    293 				goto out;
    294 			maxvlen = vlen;
    295 		}
    296 
    297 		if ((vlen = extattr_get_link(from, namespace, aname,
    298 					     aval, (size_t)vlen)) == -1)
    299 			goto out;
    300 
    301 		if (extattr_set_link(to, namespace, aname,
    302 				     aval, (size_t)vlen) != vlen)
    303 			goto out;
    304 	}
    305 
    306 	error = 0;
    307 out:
    308 	if (aval != NULL)
    309 		free(aval);
    310 
    311 	if (alist != NULL)
    312 		free(alist);
    313 
    314 	return error;
    315 }
    316 
    317 static int
    318 extattr_namespace_access(int namespace, int mode)
    319 {
    320 	switch (namespace) {
    321 	case EXTATTR_NAMESPACE_SYSTEM:
    322 		if ((mode & (R_OK|W_OK)) && getuid() != 0)
    323 			return -1;
    324 		break;
    325 	default:
    326 		break;
    327 	}
    328 
    329 	return 0;
    330 }
    331 
    332 int
    333 fcpxattr(int from_fd, int to_fd)
    334 {
    335 	const int *ns;
    336 	int error;
    337 
    338 	for (ns = extattr_namespaces; *ns; ns++) {
    339 		if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
    340 			continue;
    341 
    342 		if ((error = extattr_copy_fd(from_fd, to_fd, *ns)) != 0)
    343 			return error;
    344 	}
    345 
    346 	return 0;
    347 }
    348 
    349 int
    350 cpxattr(const char *from, const char *to)
    351 {
    352 	const int *ns;
    353 	int error;
    354 
    355 	for (ns = extattr_namespaces; *ns; ns++) {
    356 		if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
    357 			continue;
    358 
    359 		if ((error = extattr_copy_file(from, to, *ns)) != 0)
    360 			return error;
    361 	}
    362 
    363 	return 0;
    364 }
    365 
    366 int
    367 lcpxattr(const char *from, const char *to)
    368 {
    369 	const int *ns;
    370 	int error;
    371 
    372 	for (ns = extattr_namespaces; *ns; ns++) {
    373 		if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
    374 			continue;
    375 
    376 		if ((error = extattr_copy_link(from, to, *ns)) != 0)
    377 			return error;
    378 	}
    379 
    380 	return 0;
    381 }
    382