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 51 typedef 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 56 static 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 62 static 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 66 static 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 86 static const int acl_nfs4_perm_map_size = 87 (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); 88 89 static 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 101 static 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 105 static int 106 translate_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 320 static int 321 set_acl(struct archive *a, int fd, const char *name, 322 struct archive_acl *abstract_acl, __LA_MODE_T mode, 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 if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) { 368 errno = EINVAL; 369 archive_set_error(a, errno, 370 "Cannot set default ACL on non-directory"); 371 return (ARCHIVE_WARN); 372 } 373 374 acl = acl_init(entries); 375 if (acl == (acl_t)NULL) { 376 archive_set_error(a, errno, 377 "Failed to initialize ACL working storage"); 378 return (ARCHIVE_FAILED); 379 } 380 381 while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, 382 &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { 383 if (acl_create_entry(&acl, &acl_entry) != 0) { 384 archive_set_error(a, errno, 385 "Failed to create a new ACL entry"); 386 ret = ARCHIVE_FAILED; 387 goto exit_free; 388 } 389 switch (ae_tag) { 390 case ARCHIVE_ENTRY_ACL_USER: 391 ae_uid = archive_write_disk_uid(a, ae_name, ae_id); 392 acl_set_tag_type(acl_entry, ACL_USER); 393 acl_set_qualifier(acl_entry, &ae_uid); 394 break; 395 case ARCHIVE_ENTRY_ACL_GROUP: 396 ae_gid = archive_write_disk_gid(a, ae_name, ae_id); 397 acl_set_tag_type(acl_entry, ACL_GROUP); 398 acl_set_qualifier(acl_entry, &ae_gid); 399 break; 400 case ARCHIVE_ENTRY_ACL_USER_OBJ: 401 acl_set_tag_type(acl_entry, ACL_USER_OBJ); 402 break; 403 case ARCHIVE_ENTRY_ACL_GROUP_OBJ: 404 acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); 405 break; 406 case ARCHIVE_ENTRY_ACL_MASK: 407 acl_set_tag_type(acl_entry, ACL_MASK); 408 break; 409 case ARCHIVE_ENTRY_ACL_OTHER: 410 acl_set_tag_type(acl_entry, ACL_OTHER); 411 break; 412 #if ARCHIVE_ACL_FREEBSD_NFS4 413 case ARCHIVE_ENTRY_ACL_EVERYONE: 414 acl_set_tag_type(acl_entry, ACL_EVERYONE); 415 break; 416 #endif 417 default: 418 archive_set_error(a, ARCHIVE_ERRNO_MISC, 419 "Unsupported ACL tag"); 420 ret = ARCHIVE_FAILED; 421 goto exit_free; 422 } 423 424 #if ARCHIVE_ACL_FREEBSD_NFS4 425 r = 0; 426 switch (ae_type) { 427 case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: 428 r = acl_set_entry_type_np(acl_entry, 429 ACL_ENTRY_TYPE_ALLOW); 430 break; 431 case ARCHIVE_ENTRY_ACL_TYPE_DENY: 432 r = acl_set_entry_type_np(acl_entry, 433 ACL_ENTRY_TYPE_DENY); 434 break; 435 case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: 436 r = acl_set_entry_type_np(acl_entry, 437 ACL_ENTRY_TYPE_AUDIT); 438 break; 439 case ARCHIVE_ENTRY_ACL_TYPE_ALARM: 440 r = acl_set_entry_type_np(acl_entry, 441 ACL_ENTRY_TYPE_ALARM); 442 break; 443 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 444 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 445 // These don't translate directly into the system ACL. 446 break; 447 default: 448 archive_set_error(a, ARCHIVE_ERRNO_MISC, 449 "Unsupported ACL entry type"); 450 ret = ARCHIVE_FAILED; 451 goto exit_free; 452 } 453 454 if (r != 0) { 455 archive_set_error(a, errno, 456 "Failed to set ACL entry type"); 457 ret = ARCHIVE_FAILED; 458 goto exit_free; 459 } 460 #endif 461 462 if (acl_get_permset(acl_entry, &acl_permset) != 0) { 463 archive_set_error(a, errno, 464 "Failed to get ACL permission set"); 465 ret = ARCHIVE_FAILED; 466 goto exit_free; 467 } 468 if (acl_clear_perms(acl_permset) != 0) { 469 archive_set_error(a, errno, 470 "Failed to clear ACL permissions"); 471 ret = ARCHIVE_FAILED; 472 goto exit_free; 473 } 474 #if ARCHIVE_ACL_FREEBSD_NFS4 475 if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 476 perm_map_size = acl_nfs4_perm_map_size; 477 perm_map = acl_nfs4_perm_map; 478 } else { 479 #endif 480 perm_map_size = acl_posix_perm_map_size; 481 perm_map = acl_posix_perm_map; 482 #if ARCHIVE_ACL_FREEBSD_NFS4 483 } 484 #endif 485 486 for (i = 0; i < perm_map_size; ++i) { 487 if (ae_permset & perm_map[i].a_perm) { 488 if (acl_add_perm(acl_permset, 489 perm_map[i].p_perm) != 0) { 490 archive_set_error(a, errno, 491 "Failed to add ACL permission"); 492 ret = ARCHIVE_FAILED; 493 goto exit_free; 494 } 495 } 496 } 497 498 #if ARCHIVE_ACL_FREEBSD_NFS4 499 if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 500 /* 501 * acl_get_flagset_np() fails with non-NFSv4 ACLs 502 */ 503 if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { 504 archive_set_error(a, errno, 505 "Failed to get flagset from an NFSv4 " 506 "ACL entry"); 507 ret = ARCHIVE_FAILED; 508 goto exit_free; 509 } 510 if (acl_clear_flags_np(acl_flagset) != 0) { 511 archive_set_error(a, errno, 512 "Failed to clear flags from an NFSv4 " 513 "ACL flagset"); 514 ret = ARCHIVE_FAILED; 515 goto exit_free; 516 } 517 for (i = 0; i < acl_nfs4_flag_map_size; ++i) { 518 if (ae_permset & acl_nfs4_flag_map[i].a_perm) { 519 if (acl_add_flag_np(acl_flagset, 520 acl_nfs4_flag_map[i].p_perm) != 0) { 521 archive_set_error(a, errno, 522 "Failed to add flag to " 523 "NFSv4 ACL flagset"); 524 ret = ARCHIVE_FAILED; 525 goto exit_free; 526 } 527 } 528 } 529 } 530 #endif 531 } 532 533 /* Try restoring the ACL through 'fd' if we can. */ 534 if (fd >= 0) { 535 if (acl_set_fd_np(fd, acl, acl_type) == 0) 536 ret = ARCHIVE_OK; 537 else { 538 if (errno == EOPNOTSUPP) { 539 /* Filesystem doesn't support ACLs */ 540 ret = ARCHIVE_OK; 541 } else { 542 archive_set_error(a, errno, 543 "Failed to set acl on fd: %s", tname); 544 ret = ARCHIVE_WARN; 545 } 546 } 547 } 548 #if HAVE_ACL_SET_LINK_NP 549 else if (acl_set_link_np(name, acl_type, acl) != 0) 550 #else 551 /* FreeBSD older than 8.0 */ 552 else if (S_ISLNK(mode)) { 553 /* acl_set_file() follows symbolic links, skip */ 554 ret = ARCHIVE_OK; 555 } else if (acl_set_file(name, acl_type, acl) != 0) 556 #endif 557 { 558 if (errno == EOPNOTSUPP) { 559 /* Filesystem doesn't support ACLs */ 560 ret = ARCHIVE_OK; 561 } else { 562 archive_set_error(a, errno, "Failed to set acl: %s", 563 tname); 564 ret = ARCHIVE_WARN; 565 } 566 } 567 exit_free: 568 acl_free(acl); 569 return (ret); 570 } 571 572 int 573 archive_read_disk_entry_setup_acls(struct archive_read_disk *a, 574 struct archive_entry *entry, int *fd) 575 { 576 const char *accpath; 577 acl_t acl; 578 int r; 579 580 accpath = NULL; 581 582 if (*fd < 0) { 583 accpath = archive_read_disk_entry_setup_path(a, entry, fd); 584 if (accpath == NULL) 585 return (ARCHIVE_WARN); 586 } 587 588 archive_entry_acl_clear(entry); 589 590 acl = NULL; 591 592 #if ARCHIVE_ACL_FREEBSD_NFS4 593 /* Try NFSv4 ACL first. */ 594 if (*fd >= 0) 595 acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4); 596 else if (!a->follow_symlinks) 597 acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); 598 else 599 acl = acl_get_file(accpath, ACL_TYPE_NFS4); 600 601 /* Ignore "trivial" ACLs that just mirror the file mode. */ 602 if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { 603 acl_free(acl); 604 acl = NULL; 605 return (ARCHIVE_OK); 606 } 607 608 if (acl != NULL) { 609 r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); 610 acl_free(acl); 611 acl = NULL; 612 613 if (r != ARCHIVE_OK) { 614 archive_set_error(&a->archive, errno, 615 "Couldn't translate NFSv4 ACLs"); 616 } 617 618 return (r); 619 } 620 #endif 621 622 /* Retrieve access ACL from file. */ 623 if (*fd >= 0) 624 acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS); 625 #if HAVE_ACL_GET_LINK_NP 626 else if (!a->follow_symlinks) 627 acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); 628 #else 629 else if ((!a->follow_symlinks) 630 && (archive_entry_filetype(entry) == AE_IFLNK)) 631 /* We can't get the ACL of a symlink, so we assume it can't 632 have one. */ 633 acl = NULL; 634 #endif 635 else 636 acl = acl_get_file(accpath, ACL_TYPE_ACCESS); 637 638 #if HAVE_ACL_IS_TRIVIAL_NP 639 /* Ignore "trivial" ACLs that just mirror the file mode. */ 640 if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { 641 acl_free(acl); 642 acl = NULL; 643 } 644 #endif 645 646 if (acl != NULL) { 647 r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); 648 acl_free(acl); 649 acl = NULL; 650 651 if (r != ARCHIVE_OK) { 652 archive_set_error(&a->archive, errno, 653 "Couldn't translate access ACLs"); 654 return (r); 655 } 656 } 657 658 /* Only directories can have default ACLs. */ 659 if (S_ISDIR(archive_entry_mode(entry))) { 660 if (*fd >= 0) 661 acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); 662 else 663 acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); 664 if (acl != NULL) { 665 r = translate_acl(a, entry, acl, 666 ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); 667 acl_free(acl); 668 if (r != ARCHIVE_OK) { 669 archive_set_error(&a->archive, errno, 670 "Couldn't translate default ACLs"); 671 return (r); 672 } 673 } 674 } 675 return (ARCHIVE_OK); 676 } 677 678 int 679 archive_write_disk_set_acls(struct archive *a, int fd, const char *name, 680 struct archive_acl *abstract_acl, __LA_MODE_T mode) 681 { 682 int ret = ARCHIVE_OK; 683 684 (void)mode; /* UNUSED */ 685 686 if ((archive_acl_types(abstract_acl) 687 & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { 688 if ((archive_acl_types(abstract_acl) 689 & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { 690 ret = set_acl(a, fd, name, abstract_acl, mode, 691 ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); 692 if (ret != ARCHIVE_OK) 693 return (ret); 694 } 695 if ((archive_acl_types(abstract_acl) 696 & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) 697 ret = set_acl(a, fd, name, abstract_acl, mode, 698 ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); 699 700 /* Simultaneous POSIX.1e and NFSv4 is not supported */ 701 return (ret); 702 } 703 #if ARCHIVE_ACL_FREEBSD_NFS4 704 else if ((archive_acl_types(abstract_acl) & 705 ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { 706 ret = set_acl(a, fd, name, abstract_acl, mode, 707 ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); 708 } 709 #endif 710 return (ret); 711 } 712 #endif /* ARCHIVE_ACL_FREEBSD */ 713