archive_disk_acl_freebsd.c revision 328828
1/*- 2 * Copyright (c) 2003-2009 Tim Kientzle 3 * Copyright (c) 2010-2012 Michihiro NAKAJIMA 4 * Copyright (c) 2017 Martin Matuska 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(S) ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "archive_platform.h" 29 30#if ARCHIVE_ACL_FREEBSD 31 32#ifdef HAVE_ERRNO_H 33#include <errno.h> 34#endif 35#ifdef HAVE_FCNTL_H 36#include <fcntl.h> 37#endif 38#ifdef HAVE_SYS_TYPES_H 39#include <sys/types.h> 40#endif 41#ifdef HAVE_SYS_ACL_H 42#define _ACL_PRIVATE /* For debugging */ 43#include <sys/acl.h> 44#endif 45 46#include "archive_entry.h" 47#include "archive_private.h" 48#include "archive_read_disk_private.h" 49#include "archive_write_disk_private.h" 50 51typedef struct { 52 const int a_perm; /* Libarchive permission or flag */ 53 const int p_perm; /* Platform permission or flag */ 54} acl_perm_map_t; 55 56static const acl_perm_map_t acl_posix_perm_map[] = { 57 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, 58 {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, 59 {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, 60}; 61 62static const int acl_posix_perm_map_size = 63 (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); 64 65#if ARCHIVE_ACL_FREEBSD_NFS4 66static const acl_perm_map_t acl_nfs4_perm_map[] = { 67 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, 68 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, 69 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, 70 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, 71 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, 72 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, 73 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, 74 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 75 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 76 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, 77 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 78 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 79 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, 80 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, 81 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, 82 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, 83 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} 84}; 85 86static const int acl_nfs4_perm_map_size = 87 (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); 88 89static const acl_perm_map_t acl_nfs4_flag_map[] = { 90 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, 91 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, 92 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, 93 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, 94 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, 95 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, 96#ifdef ACL_ENTRY_INHERITED 97 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} 98#endif 99}; 100 101static const int acl_nfs4_flag_map_size = 102 (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); 103#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ 104 105static int 106translate_acl(struct archive_read_disk *a, 107 struct archive_entry *entry, acl_t acl, int default_entry_acl_type) 108{ 109#if ARCHIVE_ACL_FREEBSD_NFS4 110 int brand; 111 acl_flagset_t acl_flagset; 112 acl_entry_type_t acl_type; 113#endif 114 acl_tag_t acl_tag; 115 acl_entry_t acl_entry; 116 acl_permset_t acl_permset; 117 int i, entry_acl_type, perm_map_size; 118 const acl_perm_map_t *perm_map; 119 int r, s, ae_id, ae_tag, ae_perm; 120 void *q; 121 const char *ae_name; 122 123#if ARCHIVE_ACL_FREEBSD_NFS4 124 // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 125 // Make sure the "brand" on this ACL is consistent 126 // with the default_entry_acl_type bits provided. 127 if (acl_get_brand_np(acl, &brand) != 0) { 128 archive_set_error(&a->archive, errno, 129 "Failed to read ACL brand"); 130 return (ARCHIVE_WARN); 131 } 132 switch (brand) { 133 case ACL_BRAND_POSIX: 134 switch (default_entry_acl_type) { 135 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 136 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 137 break; 138 default: 139 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 140 "Invalid ACL entry type for POSIX.1e ACL"); 141 return (ARCHIVE_WARN); 142 } 143 break; 144 case ACL_BRAND_NFS4: 145 if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 146 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 147 "Invalid ACL entry type for NFSv4 ACL"); 148 return (ARCHIVE_WARN); 149 } 150 break; 151 default: 152 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 153 "Unknown ACL brand"); 154 return (ARCHIVE_WARN); 155 } 156#endif 157 158 s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); 159 if (s == -1) { 160 archive_set_error(&a->archive, errno, 161 "Failed to get first ACL entry"); 162 return (ARCHIVE_WARN); 163 } 164 165 while (s == 1) { 166 ae_id = -1; 167 ae_name = NULL; 168 ae_perm = 0; 169 170 if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { 171 archive_set_error(&a->archive, errno, 172 "Failed to get ACL tag type"); 173 return (ARCHIVE_WARN); 174 } 175 switch (acl_tag) { 176 case ACL_USER: 177 q = acl_get_qualifier(acl_entry); 178 if (q != NULL) { 179 ae_id = (int)*(uid_t *)q; 180 acl_free(q); 181 ae_name = archive_read_disk_uname(&a->archive, 182 ae_id); 183 } 184 ae_tag = ARCHIVE_ENTRY_ACL_USER; 185 break; 186 case ACL_GROUP: 187 q = acl_get_qualifier(acl_entry); 188 if (q != NULL) { 189 ae_id = (int)*(gid_t *)q; 190 acl_free(q); 191 ae_name = archive_read_disk_gname(&a->archive, 192 ae_id); 193 } 194 ae_tag = ARCHIVE_ENTRY_ACL_GROUP; 195 break; 196 case ACL_MASK: 197 ae_tag = ARCHIVE_ENTRY_ACL_MASK; 198 break; 199 case ACL_USER_OBJ: 200 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; 201 break; 202 case ACL_GROUP_OBJ: 203 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; 204 break; 205 case ACL_OTHER: 206 ae_tag = ARCHIVE_ENTRY_ACL_OTHER; 207 break; 208#if ARCHIVE_ACL_FREEBSD_NFS4 209 case ACL_EVERYONE: 210 ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; 211 break; 212#endif 213 default: 214 /* Skip types that libarchive can't support. */ 215 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 216 continue; 217 } 218 219 // XXX acl_type maps to allow/deny/audit/YYYY bits 220 entry_acl_type = default_entry_acl_type; 221 222#if ARCHIVE_ACL_FREEBSD_NFS4 223 if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 224 /* 225 * acl_get_entry_type_np() fails with non-NFSv4 ACLs 226 */ 227 if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) { 228 archive_set_error(&a->archive, errno, "Failed " 229 "to get ACL type from a NFSv4 ACL entry"); 230 return (ARCHIVE_WARN); 231 } 232 switch (acl_type) { 233 case ACL_ENTRY_TYPE_ALLOW: 234 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; 235 break; 236 case ACL_ENTRY_TYPE_DENY: 237 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; 238 break; 239 case ACL_ENTRY_TYPE_AUDIT: 240 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; 241 break; 242 case ACL_ENTRY_TYPE_ALARM: 243 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; 244 break; 245 default: 246 archive_set_error(&a->archive, errno, 247 "Invalid NFSv4 ACL entry type"); 248 return (ARCHIVE_WARN); 249 } 250 251 /* 252 * Libarchive stores "flag" (NFSv4 inheritance bits) 253 * in the ae_perm bitmap. 254 * 255 * acl_get_flagset_np() fails with non-NFSv4 ACLs 256 */ 257 if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { 258 archive_set_error(&a->archive, errno, 259 "Failed to get flagset from a NFSv4 " 260 "ACL entry"); 261 return (ARCHIVE_WARN); 262 } 263 for (i = 0; i < acl_nfs4_flag_map_size; ++i) { 264 r = acl_get_flag_np(acl_flagset, 265 acl_nfs4_flag_map[i].p_perm); 266 if (r == -1) { 267 archive_set_error(&a->archive, errno, 268 "Failed to check flag in a NFSv4 " 269 "ACL flagset"); 270 return (ARCHIVE_WARN); 271 } else if (r) 272 ae_perm |= acl_nfs4_flag_map[i].a_perm; 273 } 274 } 275#endif 276 277 if (acl_get_permset(acl_entry, &acl_permset) != 0) { 278 archive_set_error(&a->archive, errno, 279 "Failed to get ACL permission set"); 280 return (ARCHIVE_WARN); 281 } 282 283#if ARCHIVE_ACL_FREEBSD_NFS4 284 if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 285 perm_map_size = acl_nfs4_perm_map_size; 286 perm_map = acl_nfs4_perm_map; 287 } else { 288#endif 289 perm_map_size = acl_posix_perm_map_size; 290 perm_map = acl_posix_perm_map; 291#if ARCHIVE_ACL_FREEBSD_NFS4 292 } 293#endif 294 295 for (i = 0; i < perm_map_size; ++i) { 296 r = acl_get_perm_np(acl_permset, perm_map[i].p_perm); 297 if (r == -1) { 298 archive_set_error(&a->archive, errno, 299 "Failed to check permission in an ACL " 300 "permission set"); 301 return (ARCHIVE_WARN); 302 } else if (r) 303 ae_perm |= perm_map[i].a_perm; 304 } 305 306 archive_entry_acl_add_entry(entry, entry_acl_type, 307 ae_perm, ae_tag, 308 ae_id, ae_name); 309 310 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 311 if (s == -1) { 312 archive_set_error(&a->archive, errno, 313 "Failed to get next ACL entry"); 314 return (ARCHIVE_WARN); 315 } 316 } 317 return (ARCHIVE_OK); 318} 319 320static int 321set_acl(struct archive *a, int fd, const char *name, 322 struct archive_acl *abstract_acl, 323 int ae_requested_type, const char *tname) 324{ 325 int acl_type = 0; 326 acl_t acl; 327 acl_entry_t acl_entry; 328 acl_permset_t acl_permset; 329#if ARCHIVE_ACL_FREEBSD_NFS4 330 acl_flagset_t acl_flagset; 331 int r; 332#endif 333 int ret; 334 int ae_type, ae_permset, ae_tag, ae_id; 335 int perm_map_size; 336 const acl_perm_map_t *perm_map; 337 uid_t ae_uid; 338 gid_t ae_gid; 339 const char *ae_name; 340 int entries; 341 int i; 342 343 ret = ARCHIVE_OK; 344 entries = archive_acl_reset(abstract_acl, ae_requested_type); 345 if (entries == 0) 346 return (ARCHIVE_OK); 347 348 349 switch (ae_requested_type) { 350 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 351 acl_type = ACL_TYPE_ACCESS; 352 break; 353 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 354 acl_type = ACL_TYPE_DEFAULT; 355 break; 356#if ARCHIVE_ACL_FREEBSD_NFS4 357 case ARCHIVE_ENTRY_ACL_TYPE_NFS4: 358 acl_type = ACL_TYPE_NFS4; 359 break; 360#endif 361 default: 362 errno = ENOENT; 363 archive_set_error(a, errno, "Unsupported ACL type"); 364 return (ARCHIVE_FAILED); 365 } 366 367 acl = acl_init(entries); 368 if (acl == (acl_t)NULL) { 369 archive_set_error(a, errno, 370 "Failed to initialize ACL working storage"); 371 return (ARCHIVE_FAILED); 372 } 373 374 while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, 375 &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { 376 if (acl_create_entry(&acl, &acl_entry) != 0) { 377 archive_set_error(a, errno, 378 "Failed to create a new ACL entry"); 379 ret = ARCHIVE_FAILED; 380 goto exit_free; 381 } 382 switch (ae_tag) { 383 case ARCHIVE_ENTRY_ACL_USER: 384 ae_uid = archive_write_disk_uid(a, ae_name, ae_id); 385 acl_set_tag_type(acl_entry, ACL_USER); 386 acl_set_qualifier(acl_entry, &ae_uid); 387 break; 388 case ARCHIVE_ENTRY_ACL_GROUP: 389 ae_gid = archive_write_disk_gid(a, ae_name, ae_id); 390 acl_set_tag_type(acl_entry, ACL_GROUP); 391 acl_set_qualifier(acl_entry, &ae_gid); 392 break; 393 case ARCHIVE_ENTRY_ACL_USER_OBJ: 394 acl_set_tag_type(acl_entry, ACL_USER_OBJ); 395 break; 396 case ARCHIVE_ENTRY_ACL_GROUP_OBJ: 397 acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); 398 break; 399 case ARCHIVE_ENTRY_ACL_MASK: 400 acl_set_tag_type(acl_entry, ACL_MASK); 401 break; 402 case ARCHIVE_ENTRY_ACL_OTHER: 403 acl_set_tag_type(acl_entry, ACL_OTHER); 404 break; 405#if ARCHIVE_ACL_FREEBSD_NFS4 406 case ARCHIVE_ENTRY_ACL_EVERYONE: 407 acl_set_tag_type(acl_entry, ACL_EVERYONE); 408 break; 409#endif 410 default: 411 archive_set_error(a, ARCHIVE_ERRNO_MISC, 412 "Unsupported ACL tag"); 413 ret = ARCHIVE_FAILED; 414 goto exit_free; 415 } 416 417#if ARCHIVE_ACL_FREEBSD_NFS4 418 r = 0; 419 switch (ae_type) { 420 case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: 421 r = acl_set_entry_type_np(acl_entry, 422 ACL_ENTRY_TYPE_ALLOW); 423 break; 424 case ARCHIVE_ENTRY_ACL_TYPE_DENY: 425 r = acl_set_entry_type_np(acl_entry, 426 ACL_ENTRY_TYPE_DENY); 427 break; 428 case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: 429 r = acl_set_entry_type_np(acl_entry, 430 ACL_ENTRY_TYPE_AUDIT); 431 break; 432 case ARCHIVE_ENTRY_ACL_TYPE_ALARM: 433 r = acl_set_entry_type_np(acl_entry, 434 ACL_ENTRY_TYPE_ALARM); 435 break; 436 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 437 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 438 // These don't translate directly into the system ACL. 439 break; 440 default: 441 archive_set_error(a, ARCHIVE_ERRNO_MISC, 442 "Unsupported ACL entry type"); 443 ret = ARCHIVE_FAILED; 444 goto exit_free; 445 } 446 447 if (r != 0) { 448 archive_set_error(a, errno, 449 "Failed to set ACL entry type"); 450 ret = ARCHIVE_FAILED; 451 goto exit_free; 452 } 453#endif 454 455 if (acl_get_permset(acl_entry, &acl_permset) != 0) { 456 archive_set_error(a, errno, 457 "Failed to get ACL permission set"); 458 ret = ARCHIVE_FAILED; 459 goto exit_free; 460 } 461 if (acl_clear_perms(acl_permset) != 0) { 462 archive_set_error(a, errno, 463 "Failed to clear ACL permissions"); 464 ret = ARCHIVE_FAILED; 465 goto exit_free; 466 } 467#if ARCHIVE_ACL_FREEBSD_NFS4 468 if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 469 perm_map_size = acl_nfs4_perm_map_size; 470 perm_map = acl_nfs4_perm_map; 471 } else { 472#endif 473 perm_map_size = acl_posix_perm_map_size; 474 perm_map = acl_posix_perm_map; 475#if ARCHIVE_ACL_FREEBSD_NFS4 476 } 477#endif 478 479 for (i = 0; i < perm_map_size; ++i) { 480 if (ae_permset & perm_map[i].a_perm) { 481 if (acl_add_perm(acl_permset, 482 perm_map[i].p_perm) != 0) { 483 archive_set_error(a, errno, 484 "Failed to add ACL permission"); 485 ret = ARCHIVE_FAILED; 486 goto exit_free; 487 } 488 } 489 } 490 491#if ARCHIVE_ACL_FREEBSD_NFS4 492 if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 493 /* 494 * acl_get_flagset_np() fails with non-NFSv4 ACLs 495 */ 496 if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { 497 archive_set_error(a, errno, 498 "Failed to get flagset from an NFSv4 " 499 "ACL entry"); 500 ret = ARCHIVE_FAILED; 501 goto exit_free; 502 } 503 if (acl_clear_flags_np(acl_flagset) != 0) { 504 archive_set_error(a, errno, 505 "Failed to clear flags from an NFSv4 " 506 "ACL flagset"); 507 ret = ARCHIVE_FAILED; 508 goto exit_free; 509 } 510 for (i = 0; i < acl_nfs4_flag_map_size; ++i) { 511 if (ae_permset & acl_nfs4_flag_map[i].a_perm) { 512 if (acl_add_flag_np(acl_flagset, 513 acl_nfs4_flag_map[i].p_perm) != 0) { 514 archive_set_error(a, errno, 515 "Failed to add flag to " 516 "NFSv4 ACL flagset"); 517 ret = ARCHIVE_FAILED; 518 goto exit_free; 519 } 520 } 521 } 522 } 523#endif 524 } 525 526 /* Try restoring the ACL through 'fd' if we can. */ 527 if (fd >= 0) { 528 if (acl_set_fd_np(fd, acl, acl_type) == 0) 529 ret = ARCHIVE_OK; 530 else { 531 if (errno == EOPNOTSUPP) { 532 /* Filesystem doesn't support ACLs */ 533 ret = ARCHIVE_OK; 534 } else { 535 archive_set_error(a, errno, 536 "Failed to set acl on fd: %s", tname); 537 ret = ARCHIVE_WARN; 538 } 539 } 540 } 541#if HAVE_ACL_SET_LINK_NP 542 else if (acl_set_link_np(name, acl_type, acl) != 0) 543#else 544 /* FreeBSD older than 8.0 */ 545 else if (acl_set_file(name, acl_type, acl) != 0) 546#endif 547 { 548 if (errno == EOPNOTSUPP) { 549 /* Filesystem doesn't support ACLs */ 550 ret = ARCHIVE_OK; 551 } else { 552 archive_set_error(a, errno, "Failed to set acl: %s", 553 tname); 554 ret = ARCHIVE_WARN; 555 } 556 } 557exit_free: 558 acl_free(acl); 559 return (ret); 560} 561 562int 563archive_read_disk_entry_setup_acls(struct archive_read_disk *a, 564 struct archive_entry *entry, int *fd) 565{ 566 const char *accpath; 567 acl_t acl; 568 int r; 569 570 accpath = NULL; 571 572 if (*fd < 0) { 573 accpath = archive_read_disk_entry_setup_path(a, entry, fd); 574 if (accpath == NULL) 575 return (ARCHIVE_WARN); 576 } 577 578 archive_entry_acl_clear(entry); 579 580 acl = NULL; 581 582#if ARCHIVE_ACL_FREEBSD_NFS4 583 /* Try NFSv4 ACL first. */ 584 if (*fd >= 0) 585 acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4); 586 else if (!a->follow_symlinks) 587 acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); 588 else 589 acl = acl_get_file(accpath, ACL_TYPE_NFS4); 590 591 /* Ignore "trivial" ACLs that just mirror the file mode. */ 592 if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { 593 acl_free(acl); 594 acl = NULL; 595 return (ARCHIVE_OK); 596 } 597 598 if (acl != NULL) { 599 r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); 600 acl_free(acl); 601 acl = NULL; 602 603 if (r != ARCHIVE_OK) { 604 archive_set_error(&a->archive, errno, 605 "Couldn't translate NFSv4 ACLs"); 606 } 607 608 return (r); 609 } 610#endif 611 612 /* Retrieve access ACL from file. */ 613 if (*fd >= 0) 614 acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS); 615#if HAVE_ACL_GET_LINK_NP 616 else if (!a->follow_symlinks) 617 acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); 618#else 619 else if ((!a->follow_symlinks) 620 && (archive_entry_filetype(entry) == AE_IFLNK)) 621 /* We can't get the ACL of a symlink, so we assume it can't 622 have one. */ 623 acl = NULL; 624#endif 625 else 626 acl = acl_get_file(accpath, ACL_TYPE_ACCESS); 627 628#if HAVE_ACL_IS_TRIVIAL_NP 629 /* Ignore "trivial" ACLs that just mirror the file mode. */ 630 if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { 631 acl_free(acl); 632 acl = NULL; 633 } 634#endif 635 636 if (acl != NULL) { 637 r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); 638 acl_free(acl); 639 acl = NULL; 640 641 if (r != ARCHIVE_OK) { 642 archive_set_error(&a->archive, errno, 643 "Couldn't translate access ACLs"); 644 return (r); 645 } 646 } 647 648 /* Only directories can have default ACLs. */ 649 if (S_ISDIR(archive_entry_mode(entry))) { 650 if (*fd >= 0) 651 acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); 652 else 653 acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); 654 if (acl != NULL) { 655 r = translate_acl(a, entry, acl, 656 ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); 657 acl_free(acl); 658 if (r != ARCHIVE_OK) { 659 archive_set_error(&a->archive, errno, 660 "Couldn't translate default ACLs"); 661 return (r); 662 } 663 } 664 } 665 return (ARCHIVE_OK); 666} 667 668int 669archive_write_disk_set_acls(struct archive *a, int fd, const char *name, 670 struct archive_acl *abstract_acl, __LA_MODE_T mode) 671{ 672 int ret = ARCHIVE_OK; 673 674 (void)mode; /* UNUSED */ 675 676 if ((archive_acl_types(abstract_acl) 677 & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { 678 if ((archive_acl_types(abstract_acl) 679 & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { 680 ret = set_acl(a, fd, name, abstract_acl, 681 ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); 682 if (ret != ARCHIVE_OK) 683 return (ret); 684 } 685 if ((archive_acl_types(abstract_acl) 686 & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) 687 ret = set_acl(a, fd, name, abstract_acl, 688 ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); 689 690 /* Simultaneous POSIX.1e and NFSv4 is not supported */ 691 return (ret); 692 } 693#if ARCHIVE_ACL_FREEBSD_NFS4 694 else if ((archive_acl_types(abstract_acl) & 695 ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { 696 ret = set_acl(a, fd, name, abstract_acl, 697 ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); 698 } 699#endif 700 return (ret); 701} 702#endif /* ARCHIVE_ACL_FREEBSD */ 703