1 /*-
2 * Copyright (c) 2003-2010 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $");
29
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33 #ifdef HAVE_SYS_ACL_H
34 #define _ACL_PRIVATE /* For debugging */
35 #include <sys/acl.h>
36 #endif
37 #if HAVE_DARWIN_ACL
38 #include <membership.h>
39 #endif
40 #ifdef HAVE_ERRNO_H
41 #include <errno.h>
42 #endif
43
44 #include "archive.h"
45 #include "archive_entry.h"
46 #include "archive_acl_private.h"
47 #include "archive_write_disk_private.h"
48
49 #if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
50 /* Default empty function body to satisfy mainline code. */
51 int
archive_write_disk_set_acls(struct archive * a,int fd,const char * name,struct archive_acl * abstract_acl)52 archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
53 struct archive_acl *abstract_acl)
54 {
55 (void)a; /* UNUSED */
56 (void)fd; /* UNUSED */
57 (void)name; /* UNUSED */
58 (void)abstract_acl; /* UNUSED */
59 return (ARCHIVE_OK);
60 }
61
62 #else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
63
64 #if HAVE_SUN_ACL
65 #define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T
66 #elif HAVE_DARWIN_ACL
67 #define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
68 #elif HAVE_ACL_TYPE_NFS4
69 #define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
70 #endif
71
72 static int set_acl(struct archive *, int fd, const char *,
73 struct archive_acl *,
74 acl_type_t, int archive_entry_acl_type, const char *tn);
75
76 int
archive_write_disk_set_acls(struct archive * a,int fd,const char * name,struct archive_acl * abstract_acl)77 archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
78 struct archive_acl *abstract_acl)
79 {
80 int ret = ARCHIVE_OK;
81
82 #if !HAVE_DARWIN_ACL
83 if ((archive_acl_types(abstract_acl)
84 & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
85 #if HAVE_SUN_ACL
86 /* Solaris writes POSIX.1e access and default ACLs together */
87 ret = set_acl(a, fd, name, abstract_acl, ACLENT_T,
88 ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
89 #else /* HAVE_POSIX_ACL */
90 if ((archive_acl_types(abstract_acl)
91 & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
92 ret = set_acl(a, fd, name, abstract_acl,
93 ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
94 "access");
95 if (ret != ARCHIVE_OK)
96 return (ret);
97 }
98 if ((archive_acl_types(abstract_acl)
99 & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
100 ret = set_acl(a, fd, name, abstract_acl,
101 ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
102 "default");
103 #endif /* !HAVE_SUN_ACL */
104 /* Simultaneous POSIX.1e and NFSv4 is not supported */
105 return (ret);
106 }
107 #endif /* !HAVE_DARWIN_ACL */
108 #if HAVE_NFS4_ACL
109 if ((archive_acl_types(abstract_acl) &
110 ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
111 ret = set_acl(a, fd, name, abstract_acl,
112 ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
113 ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
114 }
115 #endif /* HAVE_NFS4_ACL */
116 return (ret);
117 }
118
119 /*
120 * Translate system ACL permissions into libarchive internal structure
121 */
122 static const struct {
123 const int archive_perm;
124 const int platform_perm;
125 } acl_perm_map[] = {
126 #if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
127 {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
128 {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
129 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
130 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
131 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
132 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
133 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
134 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
135 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
136 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
137 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
138 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
139 {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
140 {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
141 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
142 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
143 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
144 #elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
145 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
146 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
147 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
148 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
149 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
150 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
151 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
152 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
153 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
154 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
155 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
156 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
157 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
158 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
159 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
160 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
161 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
162 #else /* POSIX.1e ACL permissions */
163 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
164 {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
165 {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
166 #if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
167 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
168 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
169 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
170 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
171 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
172 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
173 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
174 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
175 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
176 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
177 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
178 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
179 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
180 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
181 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
182 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
183 #endif
184 #endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
185 };
186
187 #if HAVE_NFS4_ACL
188 /*
189 * Translate system NFSv4 inheritance flags into libarchive internal structure
190 */
191 static const struct {
192 const int archive_inherit;
193 const int platform_inherit;
194 } acl_inherit_map[] = {
195 #if HAVE_SUN_ACL /* Solaris NFSv4 inheritance flags */
196 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
197 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
198 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
199 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
200 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
201 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
202 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
203 #elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
204 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
205 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
206 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
207 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
208 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
209 #else /* FreeBSD NFSv4 ACL inheritance flags */
210 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
211 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
212 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
213 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
214 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
215 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
216 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
217 #endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
218 };
219 #endif /* HAVE_NFS4_ACL */
220
221 static int
set_acl(struct archive * a,int fd,const char * name,struct archive_acl * abstract_acl,acl_type_t acl_type,int ae_requested_type,const char * tname)222 set_acl(struct archive *a, int fd, const char *name,
223 struct archive_acl *abstract_acl,
224 acl_type_t acl_type, int ae_requested_type, const char *tname)
225 {
226 #if HAVE_SUN_ACL
227 aclent_t *aclent;
228 ace_t *ace;
229 int e, r;
230 acl_t *acl;
231 #else
232 acl_t acl;
233 acl_entry_t acl_entry;
234 acl_permset_t acl_permset;
235 #if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
236 acl_flagset_t acl_flagset;
237 #endif
238 #endif /* HAVE_SUN_ACL */
239 #if HAVE_ACL_TYPE_NFS4
240 int r;
241 #endif
242 int ret;
243 int ae_type, ae_permset, ae_tag, ae_id;
244 #if HAVE_DARWIN_ACL
245 uuid_t ae_uuid;
246 #endif
247 uid_t ae_uid;
248 gid_t ae_gid;
249 const char *ae_name;
250 int entries;
251 int i;
252
253 ret = ARCHIVE_OK;
254 entries = archive_acl_reset(abstract_acl, ae_requested_type);
255 if (entries == 0)
256 return (ARCHIVE_OK);
257
258 #if HAVE_SUN_ACL
259 acl = NULL;
260 acl = malloc(sizeof(acl_t));
261 if (acl == NULL) {
262 archive_set_error(a, ARCHIVE_ERRNO_MISC,
263 "Invalid ACL type");
264 return (ARCHIVE_FAILED);
265 }
266 if (acl_type == ACE_T)
267 acl->acl_entry_size = sizeof(ace_t);
268 else if (acl_type == ACLENT_T)
269 acl->acl_entry_size = sizeof(aclent_t);
270 else {
271 archive_set_error(a, ARCHIVE_ERRNO_MISC,
272 "Invalid ACL type");
273 acl_free(acl);
274 return (ARCHIVE_FAILED);
275 }
276 acl->acl_type = acl_type;
277 acl->acl_cnt = entries;
278
279 acl->acl_aclp = malloc(entries * acl->acl_entry_size);
280 if (acl->acl_aclp == NULL) {
281 archive_set_error(a, errno,
282 "Can't allocate memory for acl buffer");
283 acl_free(acl);
284 return (ARCHIVE_FAILED);
285 }
286 #else /* !HAVE_SUN_ACL */
287 acl = acl_init(entries);
288 if (acl == (acl_t)NULL) {
289 archive_set_error(a, errno,
290 "Failed to initialize ACL working storage");
291 return (ARCHIVE_FAILED);
292 }
293 #endif /* !HAVE_SUN_ACL */
294 #if HAVE_SUN_ACL
295 e = 0;
296 #endif
297 while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
298 &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
299 #if HAVE_SUN_ACL
300 ace = NULL;
301 aclent = NULL;
302 if (acl->acl_type == ACE_T) {
303 ace = &((ace_t *)acl->acl_aclp)[e];
304 ace->a_who = -1;
305 ace->a_access_mask = 0;
306 ace->a_flags = 0;
307 } else {
308 aclent = &((aclent_t *)acl->acl_aclp)[e];
309 aclent->a_id = -1;
310 aclent->a_type = 0;
311 aclent->a_perm = 0;
312 }
313 #else /* !HAVE_SUN_ACL */
314 #if HAVE_DARWIN_ACL
315 /*
316 * Mac OS doesn't support NFSv4 ACLs for
317 * owner@, group@ and everyone@.
318 * We skip any of these ACLs found.
319 */
320 if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
321 ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
322 ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
323 continue;
324 #endif
325 if (acl_create_entry(&acl, &acl_entry) != 0) {
326 archive_set_error(a, errno,
327 "Failed to create a new ACL entry");
328 ret = ARCHIVE_FAILED;
329 goto exit_free;
330 }
331 #endif /* !HAVE_SUN_ACL */
332 #if HAVE_DARWIN_ACL
333 switch (ae_type) {
334 case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
335 acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
336 break;
337 case ARCHIVE_ENTRY_ACL_TYPE_DENY:
338 acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
339 break;
340 default:
341 /* We don't support any other types on MacOS */
342 continue;
343 }
344 #endif
345 switch (ae_tag) {
346 #if HAVE_SUN_ACL
347 case ARCHIVE_ENTRY_ACL_USER:
348 ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
349 if (acl->acl_type == ACE_T)
350 ace->a_who = ae_uid;
351 else {
352 aclent->a_id = ae_uid;
353 aclent->a_type |= USER;
354 }
355 break;
356 case ARCHIVE_ENTRY_ACL_GROUP:
357 ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
358 if (acl->acl_type == ACE_T) {
359 ace->a_who = ae_gid;
360 ace->a_flags |= ACE_IDENTIFIER_GROUP;
361 } else {
362 aclent->a_id = ae_gid;
363 aclent->a_type |= GROUP;
364 }
365 break;
366 case ARCHIVE_ENTRY_ACL_USER_OBJ:
367 if (acl->acl_type == ACE_T)
368 ace->a_flags |= ACE_OWNER;
369 else
370 aclent->a_type |= USER_OBJ;
371 break;
372 case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
373 if (acl->acl_type == ACE_T) {
374 ace->a_flags |= ACE_GROUP;
375 ace->a_flags |= ACE_IDENTIFIER_GROUP;
376 } else
377 aclent->a_type |= GROUP_OBJ;
378 break;
379 case ARCHIVE_ENTRY_ACL_MASK:
380 aclent->a_type |= CLASS_OBJ;
381 break;
382 case ARCHIVE_ENTRY_ACL_OTHER:
383 aclent->a_type |= OTHER_OBJ;
384 break;
385 case ARCHIVE_ENTRY_ACL_EVERYONE:
386 ace->a_flags |= ACE_EVERYONE;
387 break;
388 #else /* !HAVE_SUN_ACL */
389 case ARCHIVE_ENTRY_ACL_USER:
390 ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
391 #if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
392 acl_set_tag_type(acl_entry, ACL_USER);
393 acl_set_qualifier(acl_entry, &ae_uid);
394 #else /* MacOS */
395 if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
396 sizeof(uid_t), ae_uuid) != 0)
397 continue;
398 if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
399 continue;
400 #endif /* HAVE_DARWIN_ACL */
401 break;
402 case ARCHIVE_ENTRY_ACL_GROUP:
403 ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
404 #if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
405 acl_set_tag_type(acl_entry, ACL_GROUP);
406 acl_set_qualifier(acl_entry, &ae_gid);
407 #else /* MacOS */
408 if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
409 sizeof(gid_t), ae_uuid) != 0)
410 continue;
411 if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
412 continue;
413 #endif /* HAVE_DARWIN_ACL */
414 break;
415 #if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
416 case ARCHIVE_ENTRY_ACL_USER_OBJ:
417 acl_set_tag_type(acl_entry, ACL_USER_OBJ);
418 break;
419 case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
420 acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
421 break;
422 case ARCHIVE_ENTRY_ACL_MASK:
423 acl_set_tag_type(acl_entry, ACL_MASK);
424 break;
425 case ARCHIVE_ENTRY_ACL_OTHER:
426 acl_set_tag_type(acl_entry, ACL_OTHER);
427 break;
428 #if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */
429 case ARCHIVE_ENTRY_ACL_EVERYONE:
430 acl_set_tag_type(acl_entry, ACL_EVERYONE);
431 break;
432 #endif
433 #endif /* !HAVE_DARWIN_ACL */
434 #endif /* !HAVE_SUN_ACL */
435 default:
436 archive_set_error(a, ARCHIVE_ERRNO_MISC,
437 "Unknown ACL tag");
438 ret = ARCHIVE_FAILED;
439 goto exit_free;
440 }
441
442 #if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
443 r = 0;
444 switch (ae_type) {
445 #if HAVE_SUN_ACL
446 case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
447 if (ace != NULL)
448 ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
449 else
450 r = -1;
451 break;
452 case ARCHIVE_ENTRY_ACL_TYPE_DENY:
453 if (ace != NULL)
454 ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
455 else
456 r = -1;
457 break;
458 case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
459 if (ace != NULL)
460 ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
461 else
462 r = -1;
463 break;
464 case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
465 if (ace != NULL)
466 ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
467 else
468 r = -1;
469 break;
470 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
471 if (aclent == NULL)
472 r = -1;
473 break;
474 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
475 if (aclent != NULL)
476 aclent->a_type |= ACL_DEFAULT;
477 else
478 r = -1;
479 break;
480 #else /* !HAVE_SUN_ACL */
481 case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
482 r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
483 break;
484 case ARCHIVE_ENTRY_ACL_TYPE_DENY:
485 r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
486 break;
487 case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
488 r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
489 break;
490 case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
491 r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
492 break;
493 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
494 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
495 // These don't translate directly into the system ACL.
496 break;
497 #endif /* !HAVE_SUN_ACL */
498 default:
499 archive_set_error(a, ARCHIVE_ERRNO_MISC,
500 "Unknown ACL entry type");
501 ret = ARCHIVE_FAILED;
502 goto exit_free;
503 }
504
505 if (r != 0) {
506 #if HAVE_SUN_ACL
507 errno = EINVAL;
508 #endif
509 archive_set_error(a, errno,
510 "Failed to set ACL entry type");
511 ret = ARCHIVE_FAILED;
512 goto exit_free;
513 }
514 #endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */
515
516 #if HAVE_SUN_ACL
517 if (acl->acl_type == ACLENT_T) {
518 if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
519 aclent->a_perm |= 1;
520 if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
521 aclent->a_perm |= 2;
522 if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
523 aclent->a_perm |= 4;
524 } else
525 #else
526 if (acl_get_permset(acl_entry, &acl_permset) != 0) {
527 archive_set_error(a, errno,
528 "Failed to get ACL permission set");
529 ret = ARCHIVE_FAILED;
530 goto exit_free;
531 }
532 if (acl_clear_perms(acl_permset) != 0) {
533 archive_set_error(a, errno,
534 "Failed to clear ACL permissions");
535 ret = ARCHIVE_FAILED;
536 goto exit_free;
537 }
538 #endif /* !HAVE_SUN_ACL */
539 for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
540 if (ae_permset & acl_perm_map[i].archive_perm) {
541 #if HAVE_SUN_ACL
542 ace->a_access_mask |=
543 acl_perm_map[i].platform_perm;
544 #else
545 if (acl_add_perm(acl_permset,
546 acl_perm_map[i].platform_perm) != 0) {
547 archive_set_error(a, errno,
548 "Failed to add ACL permission");
549 ret = ARCHIVE_FAILED;
550 goto exit_free;
551 }
552 #endif
553 }
554 }
555
556 #if HAVE_NFS4_ACL
557 #if HAVE_SUN_ACL
558 if (acl_type == ACE_T)
559 #elif HAVE_DARWIN_ACL
560 if (acl_type == ACL_TYPE_EXTENDED)
561 #else /* FreeBSD */
562 if (acl_type == ACL_TYPE_NFS4)
563 #endif
564 {
565 #if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
566 /*
567 * acl_get_flagset_np() fails with non-NFSv4 ACLs
568 */
569 if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
570 archive_set_error(a, errno,
571 "Failed to get flagset from an NFSv4 ACL entry");
572 ret = ARCHIVE_FAILED;
573 goto exit_free;
574 }
575 if (acl_clear_flags_np(acl_flagset) != 0) {
576 archive_set_error(a, errno,
577 "Failed to clear flags from an NFSv4 ACL flagset");
578 ret = ARCHIVE_FAILED;
579 goto exit_free;
580 }
581 #endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
582 for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
583 if (ae_permset & acl_inherit_map[i].archive_inherit) {
584 #if HAVE_SUN_ACL
585 ace->a_flags |=
586 acl_inherit_map[i].platform_inherit;
587 #else /* !HAVE_SUN_ACL */
588 if (acl_add_flag_np(acl_flagset,
589 acl_inherit_map[i].platform_inherit) != 0) {
590 archive_set_error(a, errno,
591 "Failed to add flag to NFSv4 ACL flagset");
592 ret = ARCHIVE_FAILED;
593 goto exit_free;
594 }
595 #endif /* HAVE_SUN_ACL */
596 }
597 }
598 }
599 #endif /* HAVE_NFS4_ACL */
600 #if HAVE_SUN_ACL
601 e++;
602 #endif
603 }
604
605 #if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
606 /* Try restoring the ACL through 'fd' if we can. */
607 #if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
608 if (fd >= 0)
609 #else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
610 if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
611 #endif
612 {
613 #if HAVE_SUN_ACL
614 if (facl_set(fd, acl) == 0)
615 #elif HAVE_ACL_SET_FD_NP
616 if (acl_set_fd_np(fd, acl, acl_type) == 0)
617 #else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
618 if (acl_set_fd(fd, acl) == 0)
619 #endif
620 ret = ARCHIVE_OK;
621 else {
622 if (errno == EOPNOTSUPP) {
623 /* Filesystem doesn't support ACLs */
624 ret = ARCHIVE_OK;
625 } else {
626 archive_set_error(a, errno,
627 "Failed to set %s acl on fd", tname);
628 }
629 }
630 } else
631 #endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
632 #if HAVE_SUN_ACL
633 if (acl_set(name, acl) != 0)
634 #elif HAVE_ACL_SET_LINK_NP
635 if (acl_set_link_np(name, acl_type, acl) != 0)
636 #else
637 /* TODO: Skip this if 'name' is a symlink. */
638 if (acl_set_file(name, acl_type, acl) != 0)
639 #endif
640 {
641 if (errno == EOPNOTSUPP) {
642 /* Filesystem doesn't support ACLs */
643 ret = ARCHIVE_OK;
644 } else {
645 archive_set_error(a, errno, "Failed to set %s acl",
646 tname);
647 ret = ARCHIVE_WARN;
648 }
649 }
650 exit_free:
651 acl_free(acl);
652 return (ret);
653 }
654 #endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
655