xref: /onnv-gate/usr/src/lib/libcmdutils/common/process_xattrs.c (revision 6812:febeba71273d)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
21*6812Sraf 
225331Samw /*
235902Smarks  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245331Samw  * Use is subject to license terms.
255331Samw  */
265331Samw 
275331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
285331Samw 
295331Samw #include "libcmdutils.h"
305331Samw 
315331Samw 
325331Samw /*
335331Samw  * Gets file descriptors of attribute directories for source and target
345331Samw  * attribute files
355331Samw  */
365331Samw int
get_attrdirs(int indfd,int outdfd,char * attrfile,int * sfd,int * tfd)375331Samw get_attrdirs(int indfd, int outdfd, char *attrfile, int *sfd, int *tfd)
385331Samw {
395331Samw 	int	pwdfd;
405331Samw 	int	fd1;
415331Samw 	int	fd2;
425331Samw 
435331Samw 	pwdfd = open(".", O_RDONLY);
445331Samw 	if ((pwdfd != -1) && (fchdir(indfd) == 0)) {
455331Samw 		if ((fd1 = attropen(attrfile, ".", O_RDONLY)) == -1) {
465331Samw 			(void) fchdir(pwdfd);
475331Samw 			(void) close(pwdfd);
485331Samw 			return (1);
495331Samw 		}
505331Samw 		*sfd = fd1;
515331Samw 	} else {
525331Samw 		(void) fchdir(pwdfd);
535331Samw 		(void) close(pwdfd);
545331Samw 		return (1);
555331Samw 	}
565331Samw 	if (fchdir(outdfd) == 0) {
575331Samw 		if ((fd2 = attropen(attrfile, ".", O_RDONLY)) == -1) {
585331Samw 			(void) fchdir(pwdfd);
595331Samw 			(void) close(pwdfd);
605331Samw 			return (1);
615331Samw 		}
625331Samw 		*tfd = fd2;
635331Samw 	} else {
645331Samw 		(void) fchdir(pwdfd);
655331Samw 		(void) close(pwdfd);
665331Samw 		return (1);
675331Samw 	}
685331Samw 	(void) fchdir(pwdfd);
695331Samw 	return (0);
705331Samw }
715331Samw 
725331Samw /*
735331Samw  * mv_xattrs - Copies the content of the extended attribute files. Then
745331Samw  * 	moves the extended system attributes from the input attribute files
755331Samw  *      to the target attribute files. Moves the extended system attributes
765331Samw  *	from source to the target file. This function returns 0 on success
775331Samw  *	and nonzero on error.
785331Samw  */
795331Samw int
mv_xattrs(char * cmd,char * infile,char * outfile,int sattr,int silent)805331Samw mv_xattrs(char *cmd, char *infile, char *outfile, int sattr, int silent)
815331Samw {
825331Samw 	int srcfd = -1;
835331Samw 	int indfd = -1;
845331Samw 	int outdfd = -1;
855331Samw 	int tmpfd = -1;
865331Samw 	int sattrfd = -1;
875331Samw 	int tattrfd = -1;
885331Samw 	int asfd = -1;
895331Samw 	int atfd = -1;
905331Samw 	DIR *dirp = NULL;
915331Samw 	struct dirent *dp = NULL;
925331Samw 	char *etext = NULL;
935331Samw 	struct stat st1;
945331Samw 	struct stat st2;
955331Samw 	nvlist_t *response = NULL;
965331Samw 	nvlist_t *res = NULL;
975331Samw 
985331Samw 	if ((srcfd = open(infile, O_RDONLY)) == -1) {
995331Samw 		etext = dgettext(TEXT_DOMAIN, "cannot open source");
1005331Samw 		goto error;
1015331Samw 	}
1025331Samw 	if (sattr)
1035331Samw 		response = sysattr_list(cmd, srcfd, infile);
1045331Samw 
1055331Samw 	if ((indfd = openat(srcfd, ".", O_RDONLY|O_XATTR)) == -1) {
1065331Samw 		etext = dgettext(TEXT_DOMAIN, "cannot openat source");
1075331Samw 		goto error;
1085331Samw 	}
1095331Samw 	if ((outdfd = attropen(outfile, ".", O_RDONLY)) == -1) {
1105331Samw 		etext = dgettext(TEXT_DOMAIN, "cannot attropen target");
1115331Samw 		goto error;
1125331Samw 	}
1135331Samw 	if ((tmpfd = dup(indfd)) == -1) {
1145331Samw 		etext = dgettext(TEXT_DOMAIN, "cannot dup descriptor");
1155331Samw 		goto error;
1165331Samw 
1175331Samw 	}
1185331Samw 	if ((dirp = fdopendir(tmpfd)) == NULL) {
1195331Samw 		etext = dgettext(TEXT_DOMAIN, "cannot access source");
1205331Samw 		goto error;
1215331Samw 	}
1225331Samw 	while ((dp = readdir(dirp)) != NULL) {
1235331Samw 		if ((dp->d_name[0] == '.' && dp->d_name[1] == '\0') ||
1245331Samw 		    (dp->d_name[0] == '.' && dp->d_name[1] == '.' &&
1255331Samw 		    dp->d_name[2] == '\0') ||
1265331Samw 		    (sysattr_type(dp->d_name) == _RO_SATTR) ||
1275331Samw 		    (sysattr_type(dp->d_name) == _RW_SATTR))
1285331Samw 			continue;
1295331Samw 
1305331Samw 		if ((sattrfd = openat(indfd, dp->d_name,
1315331Samw 		    O_RDONLY)) == -1) {
1325331Samw 			etext = dgettext(TEXT_DOMAIN,
1335331Samw 			    "cannot open src attribute file");
1345331Samw 			goto error;
1355331Samw 		}
1365331Samw 		if (fstat(sattrfd, &st1) < 0) {
1375331Samw 			etext = dgettext(TEXT_DOMAIN,
1385331Samw 			    "could not stat attribute file");
1395331Samw 			goto error;
1405331Samw 		}
1415331Samw 		if ((tattrfd = openat(outdfd, dp->d_name,
1425331Samw 		    O_RDWR|O_CREAT|O_TRUNC, st1.st_mode)) == -1) {
1435331Samw 			etext = dgettext(TEXT_DOMAIN,
1445331Samw 			    "cannot open target attribute file");
1455331Samw 			goto error;
1465331Samw 		}
1475331Samw 		if (fstat(tattrfd, &st2) < 0) {
1485331Samw 			etext = dgettext(TEXT_DOMAIN,
1495331Samw 			    "could not stat attribute file");
1505331Samw 			goto error;
1515331Samw 		}
1525331Samw 		if (writefile(sattrfd, tattrfd, infile, outfile, dp->d_name,
1535331Samw 		    dp->d_name, &st1, &st2) != 0) {
1545331Samw 			etext = dgettext(TEXT_DOMAIN,
1555331Samw 			    "failed to copy extended attribute "
1565331Samw 			    "from source to target");
1575331Samw 			goto error;
1585331Samw 		}
1595331Samw 
1605331Samw 		errno = 0;
1615331Samw 		if (sattr) {
1625331Samw 			/*
1635331Samw 			 * Gets non default extended system attributes from
1645331Samw 			 * source to copy to target.
1655331Samw 			 */
1665331Samw 			if (dp->d_name != NULL)
1675331Samw 				res = sysattr_list(cmd, sattrfd, dp->d_name);
1685331Samw 
1695331Samw 			if (res != NULL &&
1705331Samw 			    get_attrdirs(indfd, outdfd, dp->d_name, &asfd,
1715331Samw 			    &atfd) != 0) {
1725331Samw 				etext = dgettext(TEXT_DOMAIN,
1735331Samw 				    "Failed to open attribute files");
1745331Samw 				goto error;
1755331Samw 			}
1765331Samw 			/*
1775331Samw 			 * Copy extended system attribute from source
1785331Samw 			 * attribute file to target attribute file
1795331Samw 			 */
1805331Samw 			if (res != NULL &&
1815331Samw 			    (renameat(asfd, VIEW_READWRITE, atfd,
1825331Samw 			    VIEW_READWRITE) != 0)) {
1835331Samw 				if (errno == EPERM)
1845331Samw 					etext = dgettext(TEXT_DOMAIN,
1855331Samw 					    "Permission denied -"
1865331Samw 					    "failed to move system attribute");
1875331Samw 				else
1885331Samw 					etext = dgettext(TEXT_DOMAIN,
1895331Samw 					    "failed to move extended "
1905331Samw 					    "system attribute");
1915331Samw 				goto error;
1925331Samw 			}
1935331Samw 		}
1945331Samw 		if (sattrfd != -1)
1955331Samw 			(void) close(sattrfd);
1965331Samw 		if (tattrfd != -1)
1975331Samw 			(void) close(tattrfd);
1985331Samw 		if (asfd != -1)
1995331Samw 			(void) close(asfd);
2005331Samw 		if (atfd != -1)
2015331Samw 			(void) close(atfd);
2025331Samw 		if (res != NULL) {
2035331Samw 			nvlist_free(res);
2045331Samw 			res = NULL;
2055331Samw 		}
2065331Samw 	}
2075331Samw 	errno = 0;
2085331Samw 	/* Copy extended system attribute from source to target */
2095331Samw 
2105331Samw 	if (response != NULL) {
2115331Samw 		if (renameat(indfd, VIEW_READWRITE, outdfd,
2125331Samw 		    VIEW_READWRITE) == 0)
2135331Samw 			goto done;
2145331Samw 
2155331Samw 		if (errno == EPERM)
2165331Samw 			etext = dgettext(TEXT_DOMAIN, "Permission denied");
2175331Samw 		else
2185331Samw 			etext = dgettext(TEXT_DOMAIN,
2195331Samw 			    "failed to move system attribute");
2205331Samw 	}
2215331Samw error:
2225331Samw 	if (res != NULL)
2235331Samw 		nvlist_free(res);
2245331Samw 	if (silent == 0 && etext != NULL) {
2255331Samw 		if (!sattr)
2265331Samw 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
2275331Samw 			    "%s: %s: cannot move extended attributes, "),
2285331Samw 			    cmd, infile);
2295331Samw 		else
2305331Samw 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
2315331Samw 			    "%s: %s: cannot move extended system "
2325331Samw 			    "attributes, "), cmd, infile);
2335331Samw 		perror(etext);
2345331Samw 	}
2355331Samw done:
2365331Samw 	if (dirp)
2375331Samw 		(void) closedir(dirp);
2385331Samw 	if (sattrfd != -1)
2395331Samw 		(void) close(sattrfd);
2405331Samw 	if (tattrfd != -1)
2415331Samw 		(void) close(tattrfd);
2425331Samw 	if (asfd != -1)
2435331Samw 		(void) close(asfd);
2445331Samw 	if (atfd != -1)
2455331Samw 		(void) close(atfd);
2465331Samw 	if (indfd != -1)
2475331Samw 		(void) close(indfd);
2485331Samw 	if (outdfd != -1)
2495331Samw 		(void) close(outdfd);
2505331Samw 	if (response != NULL)
2515331Samw 		nvlist_free(response);
2525331Samw 	if (etext != NULL)
2535331Samw 		return (1);
2545331Samw 	else
2555331Samw 		return (0);
2565331Samw }
2575331Samw 
2585331Samw /*
2595331Samw  * The function returns non default extended system attribute list
2605331Samw  * associated with 'fname' and returns NULL when an error has occured
2615331Samw  * or when only extended system attributes other than archive,
2625331Samw  * av_modified or crtime are set.
2635331Samw  *
2645331Samw  * The function returns system attribute list for the following cases:
2655331Samw  *
2665331Samw  *	- any extended system attribute other than the default attributes
2675331Samw  *	  ('archive', 'av_modified' and 'crtime') is set
2685331Samw  *	- nvlist has NULL name string
2695331Samw  *	- nvpair has data type of 'nvlist'
2705331Samw  *	- default data type.
2715331Samw  */
2725331Samw 
2735331Samw nvlist_t *
sysattr_list(char * cmd,int fd,char * fname)2745331Samw sysattr_list(char *cmd, int fd, char *fname)
2755331Samw {
2765331Samw 	boolean_t	value;
2775331Samw 	data_type_t	type;
2785331Samw 	nvlist_t	*response;
2795331Samw 	nvpair_t	*pair;
2805331Samw 	f_attr_t	fattr;
2815331Samw 	char		*name;
2825331Samw 
2835331Samw 	if (fgetattr(fd, XATTR_VIEW_READWRITE, &response) != 0) {
2845331Samw 		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
2855331Samw 		    "%s: %s: fgetattr failed\n"),
2865331Samw 		    cmd, fname);
2875331Samw 		return (NULL);
2885331Samw 	}
2895331Samw 	pair = NULL;
2905331Samw 	while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
2915331Samw 
2925331Samw 		name = nvpair_name(pair);
2935331Samw 
2945331Samw 		if (name != NULL)
2955331Samw 			fattr = name_to_attr(name);
2965331Samw 		else
2975331Samw 			return (response);
2985331Samw 
2995331Samw 		type = nvpair_type(pair);
3005331Samw 		switch (type) {
3015331Samw 			case DATA_TYPE_BOOLEAN_VALUE:
3025331Samw 				if (nvpair_value_boolean_value(pair,
3035331Samw 				    &value) != 0) {
3045331Samw 					(void) fprintf(stderr,
3055331Samw 					    dgettext(TEXT_DOMAIN, "%s "
3065331Samw 					    "nvpair_value_boolean_value "
3075331Samw 					    "failed\n"), cmd);
3085331Samw 					continue;
3095331Samw 				}
3105331Samw 				if (value && fattr != F_ARCHIVE &&
3115331Samw 				    fattr != F_AV_MODIFIED)
3125331Samw 					return (response);
3135331Samw 				break;
3145331Samw 			case DATA_TYPE_UINT64_ARRAY:
3155331Samw 				if (fattr != F_CRTIME)
3165331Samw 					return (response);
3175331Samw 				break;
3185331Samw 			case DATA_TYPE_NVLIST:
3195331Samw 			default:
3205331Samw 				return (response);
3215331Samw 				break;
3225331Samw 		}
3235331Samw 	}
3245331Samw 	if (response != NULL)
3255331Samw 		nvlist_free(response);
3265331Samw 	return (NULL);
3275331Samw }
328