Home | History | Annotate | Line # | Download | only in gen
      1 /*	$NetBSD: extattr.c,v 1.5 2017/03/09 11:39:41 maya 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.5 2017/03/09 11:39:41 maya 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 	free(aval);
    164 	free(alist);
    165 
    166 	return error;
    167 }
    168 
    169 int
    170 extattr_copy_file(const char *from, const char *to, int namespace)
    171 {
    172 	ssize_t llen, vlen, maxvlen;
    173 	size_t alen;
    174 	void *alist = NULL;
    175 	void *aval = NULL;
    176 	size_t i;
    177 	int error = -1;
    178 
    179 	llen = extattr_list_file(from, namespace, NULL, 0);
    180 	if (llen == -1) {
    181 		/* Silently ignore when EA are not supported */
    182 		if (errno == EOPNOTSUPP)
    183 			error = 0;
    184 		goto out;
    185 	}
    186 
    187 	if (llen == 0) {
    188 		error = 0;
    189 		goto out;
    190 	}
    191 
    192 	if ((alist = malloc((size_t)llen)) == NULL)
    193 		goto out;
    194 
    195 	llen = extattr_list_file(from, namespace, alist, (size_t)llen);
    196 	if (llen == -1)
    197 		goto out;
    198 
    199 	maxvlen = 1024;
    200 	if ((aval = malloc((size_t)maxvlen)) == NULL)
    201 		goto out;
    202 
    203 	for (i = 0; i < (size_t)llen; i += alen + 1) {
    204 		char aname[NAME_MAX + 1];
    205 		char *ap;
    206 
    207 		alen = ((uint8_t *)alist)[i];
    208 		ap = ((char *)alist) + i + 1;
    209 		(void)memcpy(aname, ap, alen);
    210 		aname[alen] = '\0';
    211 
    212 		vlen = extattr_get_file(from, namespace, aname, NULL, 0);
    213 		if (vlen == -1)
    214 			goto out;
    215 
    216 		if (vlen > maxvlen) {
    217 			if ((aval = realloc(aval, (size_t)vlen)) == NULL)
    218 				goto out;
    219 			maxvlen = vlen;
    220 		}
    221 
    222 		if ((vlen = extattr_get_file(from, namespace, aname,
    223 						aval, (size_t)vlen)) == -1)
    224 			goto out;
    225 
    226 		if (extattr_set_file(to, namespace, aname,
    227 				     aval, (size_t)vlen) != vlen)
    228 			goto out;
    229 	}
    230 
    231 	error = 0;
    232 out:
    233 	free(aval);
    234 	free(alist);
    235 
    236 	return error;
    237 }
    238 
    239 int
    240 extattr_copy_link(const char *from, const char *to, int namespace)
    241 {
    242 	ssize_t llen, vlen, maxvlen;
    243 	size_t alen;
    244 	void *alist = NULL;
    245 	void *aval = NULL;
    246 	size_t i;
    247 	int error = -1;
    248 
    249 	llen = extattr_list_link(from, namespace, NULL, 0);
    250 	if (llen == -1) {
    251 		/* Silently ignore when EA are not supported */
    252 		if (errno == EOPNOTSUPP)
    253 			error = 0;
    254 		goto out;
    255 	}
    256 
    257 	if (llen == 0) {
    258 		error = 0;
    259 		goto out;
    260 	}
    261 
    262 	if ((alist = malloc((size_t)llen)) == NULL)
    263 		goto out;
    264 
    265 	llen = extattr_list_link(from, namespace, alist, (size_t)llen);
    266 	if (llen == -1)
    267 		goto out;
    268 
    269 	maxvlen = 1024;
    270 	if ((aval = malloc((size_t)maxvlen)) == NULL)
    271 		goto out;
    272 
    273 	for (i = 0; i < (size_t)llen; i += alen + 1) {
    274 		char aname[NAME_MAX + 1];
    275 		char *ap;
    276 
    277 		alen = ((uint8_t *)alist)[i];
    278 		ap = ((char *)alist) + i + 1;
    279 		(void)memcpy(aname, ap, alen);
    280 		aname[alen] = '\0';
    281 
    282 		vlen = extattr_get_link(from, namespace, aname, NULL, 0);
    283 		if (vlen == -1)
    284 			goto out;
    285 
    286 		if (vlen > maxvlen) {
    287 			if ((aval = realloc(aval, (size_t)vlen)) == NULL)
    288 				goto out;
    289 			maxvlen = vlen;
    290 		}
    291 
    292 		if ((vlen = extattr_get_link(from, namespace, aname,
    293 					     aval, (size_t)vlen)) == -1)
    294 			goto out;
    295 
    296 		if (extattr_set_link(to, namespace, aname,
    297 				     aval, (size_t)vlen) != vlen)
    298 			goto out;
    299 	}
    300 
    301 	error = 0;
    302 out:
    303 	free(aval);
    304 	free(alist);
    305 
    306 	return error;
    307 }
    308 
    309 static int
    310 extattr_namespace_access(int namespace, int mode)
    311 {
    312 	switch (namespace) {
    313 	case EXTATTR_NAMESPACE_SYSTEM:
    314 		if ((mode & (R_OK|W_OK)) && getuid() != 0)
    315 			return -1;
    316 		break;
    317 	default:
    318 		break;
    319 	}
    320 
    321 	return 0;
    322 }
    323 
    324 int
    325 fcpxattr(int from_fd, int to_fd)
    326 {
    327 	const int *ns;
    328 	int error;
    329 
    330 	for (ns = extattr_namespaces; *ns; ns++) {
    331 		if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
    332 			continue;
    333 
    334 		if ((error = extattr_copy_fd(from_fd, to_fd, *ns)) != 0)
    335 			return error;
    336 	}
    337 
    338 	return 0;
    339 }
    340 
    341 int
    342 cpxattr(const char *from, const char *to)
    343 {
    344 	const int *ns;
    345 	int error;
    346 
    347 	for (ns = extattr_namespaces; *ns; ns++) {
    348 		if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
    349 			continue;
    350 
    351 		if ((error = extattr_copy_file(from, to, *ns)) != 0)
    352 			return error;
    353 	}
    354 
    355 	return 0;
    356 }
    357 
    358 int
    359 lcpxattr(const char *from, const char *to)
    360 {
    361 	const int *ns;
    362 	int error;
    363 
    364 	for (ns = extattr_namespaces; *ns; ns++) {
    365 		if (extattr_namespace_access(*ns, R_OK|W_OK) != 0)
    366 			continue;
    367 
    368 		if ((error = extattr_copy_link(from, to, *ns)) != 0)
    369 			return error;
    370 	}
    371 
    372 	return 0;
    373 }
    374