dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libcmdutils / common / process_xattrs.c
blob50b1de58d6c9f39a7408d0dc52936cd739ce10b8
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Milan Jurik. All rights reserved.
28 #include "libcmdutils.h"
32 * Gets file descriptors of attribute directories for source and target
33 * attribute files
35 int
36 get_attrdirs(int indfd, int outdfd, char *attrfile, int *sfd, int *tfd)
38 int pwdfd;
39 int fd1;
40 int fd2;
42 pwdfd = open(".", O_RDONLY);
43 if ((pwdfd != -1) && (fchdir(indfd) == 0)) {
44 if ((fd1 = attropen(attrfile, ".", O_RDONLY)) == -1) {
45 (void) fchdir(pwdfd);
46 (void) close(pwdfd);
47 return (1);
49 *sfd = fd1;
50 } else {
51 (void) fchdir(pwdfd);
52 (void) close(pwdfd);
53 return (1);
55 if (fchdir(outdfd) == 0) {
56 if ((fd2 = attropen(attrfile, ".", O_RDONLY)) == -1) {
57 (void) fchdir(pwdfd);
58 (void) close(pwdfd);
59 return (1);
61 *tfd = fd2;
62 } else {
63 (void) fchdir(pwdfd);
64 (void) close(pwdfd);
65 return (1);
67 (void) fchdir(pwdfd);
68 return (0);
72 * mv_xattrs - Copies the content of the extended attribute files. Then
73 * moves the extended system attributes from the input attribute files
74 * to the target attribute files. Moves the extended system attributes
75 * from source to the target file. This function returns 0 on success
76 * and nonzero on error.
78 int
79 mv_xattrs(char *cmd, char *infile, char *outfile, int sattr, int silent)
81 int srcfd = -1;
82 int indfd = -1;
83 int outdfd = -1;
84 int tmpfd = -1;
85 int sattrfd = -1;
86 int tattrfd = -1;
87 int asfd = -1;
88 int atfd = -1;
89 DIR *dirp = NULL;
90 struct dirent *dp = NULL;
91 char *etext = NULL;
92 struct stat st1;
93 struct stat st2;
94 nvlist_t *response = NULL;
95 nvlist_t *res = NULL;
97 if ((srcfd = open(infile, O_RDONLY)) == -1) {
98 etext = dgettext(TEXT_DOMAIN, "cannot open source");
99 goto error;
101 if (sattr)
102 response = sysattr_list(cmd, srcfd, infile);
104 if ((indfd = openat(srcfd, ".", O_RDONLY|O_XATTR)) == -1) {
105 etext = dgettext(TEXT_DOMAIN, "cannot openat source");
106 goto error;
108 if ((outdfd = attropen(outfile, ".", O_RDONLY)) == -1) {
109 etext = dgettext(TEXT_DOMAIN, "cannot attropen target");
110 goto error;
112 if ((tmpfd = dup(indfd)) == -1) {
113 etext = dgettext(TEXT_DOMAIN, "cannot dup descriptor");
114 goto error;
117 if ((dirp = fdopendir(tmpfd)) == NULL) {
118 etext = dgettext(TEXT_DOMAIN, "cannot access source");
119 goto error;
121 while ((dp = readdir(dirp)) != NULL) {
122 if ((dp->d_name[0] == '.' && dp->d_name[1] == '\0') ||
123 (dp->d_name[0] == '.' && dp->d_name[1] == '.' &&
124 dp->d_name[2] == '\0') ||
125 (sysattr_type(dp->d_name) == _RO_SATTR) ||
126 (sysattr_type(dp->d_name) == _RW_SATTR))
127 continue;
129 if ((sattrfd = openat(indfd, dp->d_name,
130 O_RDONLY)) == -1) {
131 etext = dgettext(TEXT_DOMAIN,
132 "cannot open src attribute file");
133 goto error;
135 if (fstat(sattrfd, &st1) < 0) {
136 etext = dgettext(TEXT_DOMAIN,
137 "could not stat attribute file");
138 goto error;
140 if ((tattrfd = openat(outdfd, dp->d_name,
141 O_RDWR|O_CREAT|O_TRUNC, st1.st_mode)) == -1) {
142 etext = dgettext(TEXT_DOMAIN,
143 "cannot open target attribute file");
144 goto error;
146 if (fstat(tattrfd, &st2) < 0) {
147 etext = dgettext(TEXT_DOMAIN,
148 "could not stat attribute file");
149 goto error;
151 if (writefile(sattrfd, tattrfd, infile, outfile, dp->d_name,
152 dp->d_name, &st1, &st2) != 0) {
153 etext = dgettext(TEXT_DOMAIN,
154 "failed to copy extended attribute "
155 "from source to target");
156 goto error;
159 errno = 0;
160 if (sattr) {
162 * Gets non default extended system attributes from
163 * source to copy to target.
165 if (dp->d_name != NULL)
166 res = sysattr_list(cmd, sattrfd, dp->d_name);
168 if (res != NULL &&
169 get_attrdirs(indfd, outdfd, dp->d_name, &asfd,
170 &atfd) != 0) {
171 etext = dgettext(TEXT_DOMAIN,
172 "Failed to open attribute files");
173 goto error;
176 * Copy extended system attribute from source
177 * attribute file to target attribute file
179 if (res != NULL &&
180 (renameat(asfd, VIEW_READWRITE, atfd,
181 VIEW_READWRITE) != 0)) {
182 if (errno == EPERM)
183 etext = dgettext(TEXT_DOMAIN,
184 "Permission denied -"
185 "failed to move system attribute");
186 else
187 etext = dgettext(TEXT_DOMAIN,
188 "failed to move extended "
189 "system attribute");
190 goto error;
193 if (sattrfd != -1)
194 (void) close(sattrfd);
195 if (tattrfd != -1)
196 (void) close(tattrfd);
197 if (asfd != -1)
198 (void) close(asfd);
199 if (atfd != -1)
200 (void) close(atfd);
201 if (res != NULL) {
202 nvlist_free(res);
203 res = NULL;
206 errno = 0;
207 /* Copy extended system attribute from source to target */
209 if (response != NULL) {
210 if (renameat(indfd, VIEW_READWRITE, outdfd,
211 VIEW_READWRITE) == 0)
212 goto done;
214 if (errno == EPERM)
215 etext = dgettext(TEXT_DOMAIN, "Permission denied");
216 else
217 etext = dgettext(TEXT_DOMAIN,
218 "failed to move system attribute");
220 error:
221 nvlist_free(res);
222 if (silent == 0 && etext != NULL) {
223 if (!sattr)
224 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
225 "%s: %s: cannot move extended attributes, "),
226 cmd, infile);
227 else
228 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
229 "%s: %s: cannot move extended system "
230 "attributes, "), cmd, infile);
231 perror(etext);
233 done:
234 if (dirp)
235 (void) closedir(dirp);
236 if (sattrfd != -1)
237 (void) close(sattrfd);
238 if (tattrfd != -1)
239 (void) close(tattrfd);
240 if (asfd != -1)
241 (void) close(asfd);
242 if (atfd != -1)
243 (void) close(atfd);
244 if (indfd != -1)
245 (void) close(indfd);
246 if (outdfd != -1)
247 (void) close(outdfd);
248 nvlist_free(response);
249 if (etext != NULL)
250 return (1);
251 else
252 return (0);
256 * The function returns non default extended system attribute list
257 * associated with 'fname' and returns NULL when an error has occured
258 * or when only extended system attributes other than archive,
259 * av_modified or crtime are set.
261 * The function returns system attribute list for the following cases:
263 * - any extended system attribute other than the default attributes
264 * ('archive', 'av_modified' and 'crtime') is set
265 * - nvlist has NULL name string
266 * - nvpair has data type of 'nvlist'
267 * - default data type.
270 nvlist_t *
271 sysattr_list(char *cmd, int fd, char *fname)
273 boolean_t value;
274 data_type_t type;
275 nvlist_t *response;
276 nvpair_t *pair;
277 f_attr_t fattr;
278 char *name;
280 if (fgetattr(fd, XATTR_VIEW_READWRITE, &response) != 0) {
281 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
282 "%s: %s: fgetattr failed\n"),
283 cmd, fname);
284 return (NULL);
286 pair = NULL;
287 while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
289 name = nvpair_name(pair);
291 if (name != NULL)
292 fattr = name_to_attr(name);
293 else
294 return (response);
296 type = nvpair_type(pair);
297 switch (type) {
298 case DATA_TYPE_BOOLEAN_VALUE:
299 if (nvpair_value_boolean_value(pair,
300 &value) != 0) {
301 (void) fprintf(stderr,
302 dgettext(TEXT_DOMAIN, "%s "
303 "nvpair_value_boolean_value "
304 "failed\n"), cmd);
305 continue;
307 if (value && fattr != F_ARCHIVE &&
308 fattr != F_AV_MODIFIED)
309 return (response);
310 break;
311 case DATA_TYPE_UINT64_ARRAY:
312 if (fattr != F_CRTIME)
313 return (response);
314 break;
315 case DATA_TYPE_NVLIST:
316 default:
317 return (response);
320 nvlist_free(response);
321 return (NULL);