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