Path: blob/master/Utilities/cmlibarchive/libarchive/archive_disk_acl_linux.c
3153 views
/*-1* Copyright (c) 2003-2009 Tim Kientzle2* Copyright (c) 2010-2012 Michihiro NAKAJIMA3* Copyright (c) 2017 Martin Matuska4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR16* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* 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, BUT20* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,21* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY22* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT23* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF24* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.25*/2627#include "archive_platform.h"2829#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL3031#ifdef HAVE_ERRNO_H32#include <errno.h>33#endif34#ifdef HAVE_FCNTL_H35#include <fcntl.h>36#endif37#if HAVE_ACL_LIBACL_H38#include <acl/libacl.h>39#endif40#ifdef HAVE_SYS_ACL_H41#include <sys/acl.h>42#endif43#ifdef HAVE_SYS_RICHACL_H44#include <sys/richacl.h>45#endif4647#include "archive_entry.h"48#include "archive_private.h"49#include "archive_read_disk_private.h"50#include "archive_write_disk_private.h"5152typedef struct {53const int a_perm; /* Libarchive permission or flag */54const int p_perm; /* Platform permission or flag */55} acl_perm_map_t;5657#if ARCHIVE_ACL_LIBACL58static const acl_perm_map_t acl_posix_perm_map[] = {59{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},60{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},61{ARCHIVE_ENTRY_ACL_READ, ACL_READ},62};6364static const int acl_posix_perm_map_size =65(int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));66#endif /* ARCHIVE_ACL_LIBACL */6768#if ARCHIVE_ACL_LIBRICHACL69static const acl_perm_map_t acl_nfs4_perm_map[] = {70{ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},71{ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},72{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},73{ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},74{ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},75{ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},76{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},77{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},78{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},79{ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},80{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},81{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},82{ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},83{ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},84{ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},85{ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},86{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}87};8889static const int acl_nfs4_perm_map_size =90(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));9192static const acl_perm_map_t acl_nfs4_flag_map[] = {93{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},94{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},95{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},96{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},97{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}98};99100static const int acl_nfs4_flag_map_size =101(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));102#endif /* ARCHIVE_ACL_LIBRICHACL */103104#if ARCHIVE_ACL_LIBACL105/*106* Translate POSIX.1e ACLs into libarchive internal structure107*/108static int109translate_acl(struct archive_read_disk *a,110struct archive_entry *entry, acl_t acl, int default_entry_acl_type)111{112acl_tag_t acl_tag;113acl_entry_t acl_entry;114acl_permset_t acl_permset;115int i, entry_acl_type;116int r, s, ae_id, ae_tag, ae_perm;117void *q;118const char *ae_name;119120s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);121if (s == -1) {122archive_set_error(&a->archive, errno,123"Failed to get first ACL entry");124return (ARCHIVE_WARN);125}126127while (s == 1) {128ae_id = -1;129ae_name = NULL;130ae_perm = 0;131132if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {133archive_set_error(&a->archive, errno,134"Failed to get ACL tag type");135return (ARCHIVE_WARN);136}137switch (acl_tag) {138case ACL_USER:139q = acl_get_qualifier(acl_entry);140if (q != NULL) {141ae_id = (int)*(uid_t *)q;142acl_free(q);143ae_name = archive_read_disk_uname(&a->archive,144ae_id);145}146ae_tag = ARCHIVE_ENTRY_ACL_USER;147break;148case ACL_GROUP:149q = acl_get_qualifier(acl_entry);150if (q != NULL) {151ae_id = (int)*(gid_t *)q;152acl_free(q);153ae_name = archive_read_disk_gname(&a->archive,154ae_id);155}156ae_tag = ARCHIVE_ENTRY_ACL_GROUP;157break;158case ACL_MASK:159ae_tag = ARCHIVE_ENTRY_ACL_MASK;160break;161case ACL_USER_OBJ:162ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;163break;164case ACL_GROUP_OBJ:165ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;166break;167case ACL_OTHER:168ae_tag = ARCHIVE_ENTRY_ACL_OTHER;169break;170default:171/* Skip types that libarchive can't support. */172s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);173continue;174}175176// XXX acl_type maps to allow/deny/audit/YYYY bits177entry_acl_type = default_entry_acl_type;178179if (acl_get_permset(acl_entry, &acl_permset) != 0) {180archive_set_error(&a->archive, errno,181"Failed to get ACL permission set");182return (ARCHIVE_WARN);183}184185for (i = 0; i < acl_posix_perm_map_size; ++i) {186r = acl_get_perm(acl_permset,187acl_posix_perm_map[i].p_perm);188if (r == -1) {189archive_set_error(&a->archive, errno,190"Failed to check permission in an ACL "191"permission set");192return (ARCHIVE_WARN);193} else if (r)194ae_perm |= acl_posix_perm_map[i].a_perm;195}196197archive_entry_acl_add_entry(entry, entry_acl_type,198ae_perm, ae_tag,199ae_id, ae_name);200201s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);202if (s == -1) {203archive_set_error(&a->archive, errno,204"Failed to get next ACL entry");205return (ARCHIVE_WARN);206}207}208return (ARCHIVE_OK);209}210#endif /* ARCHIVE_ACL_LIBACL */211212#if ARCHIVE_ACL_LIBRICHACL213/*214* Translate RichACL into libarchive internal ACL215*/216static int217translate_richacl(struct archive_read_disk *a, struct archive_entry *entry,218struct richacl *richacl)219{220int ae_id, ae_tag, ae_perm;221int entry_acl_type, i;222const char *ae_name;223224struct richace *richace;225226richacl_for_each_entry(richace, richacl) {227ae_name = NULL;228ae_tag = 0;229ae_perm = 0;230ae_id = -1;231232switch (richace->e_type) {233case RICHACE_ACCESS_ALLOWED_ACE_TYPE:234entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;235break;236case RICHACE_ACCESS_DENIED_ACE_TYPE:237entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;238break;239default: /* Unknown entry type, skip */240continue;241}242243/* Unsupported */244if (richace->e_flags & RICHACE_UNMAPPED_WHO)245continue;246247if (richace->e_flags & RICHACE_SPECIAL_WHO) {248switch (richace->e_id) {249case RICHACE_OWNER_SPECIAL_ID:250ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;251break;252case RICHACE_GROUP_SPECIAL_ID:253ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;254break;255case RICHACE_EVERYONE_SPECIAL_ID:256ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;257break;258default: /* Unknown special ID type */259continue;260}261} else {262ae_id = richace->e_id;263if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {264ae_tag = ARCHIVE_ENTRY_ACL_GROUP;265ae_name = archive_read_disk_gname(&a->archive,266(gid_t)(richace->e_id));267} else {268ae_tag = ARCHIVE_ENTRY_ACL_USER;269ae_name = archive_read_disk_uname(&a->archive,270(uid_t)(richace->e_id));271}272}273for (i = 0; i < acl_nfs4_flag_map_size; ++i) {274if ((richace->e_flags &275acl_nfs4_flag_map[i].p_perm) != 0)276ae_perm |= acl_nfs4_flag_map[i].a_perm;277}278for (i = 0; i < acl_nfs4_perm_map_size; ++i) {279if ((richace->e_mask &280acl_nfs4_perm_map[i].p_perm) != 0)281ae_perm |=282acl_nfs4_perm_map[i].a_perm;283}284285archive_entry_acl_add_entry(entry, entry_acl_type,286ae_perm, ae_tag, ae_id, ae_name);287}288return (ARCHIVE_OK);289}290#endif /* ARCHIVE_ACL_LIBRICHACL */291292#if ARCHIVE_ACL_LIBRICHACL293static int294_richacl_mode_to_mask(short mode)295{296int mask = 0;297298if (mode & S_IROTH)299mask |= RICHACE_POSIX_MODE_READ;300if (mode & S_IWOTH)301mask |= RICHACE_POSIX_MODE_WRITE;302if (mode & S_IXOTH)303mask |= RICHACE_POSIX_MODE_EXEC;304305return (mask);306}307308static void309_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode)310{311richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6);312richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3);313richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007);314}315#endif /* ARCHIVE_ACL_LIBRICHACL */316317#if ARCHIVE_ACL_LIBRICHACL318static int319set_richacl(struct archive *a, int fd, const char *name,320struct archive_acl *abstract_acl, __LA_MODE_T mode,321int ae_requested_type, const char *tname)322{323int ae_type, ae_permset, ae_tag, ae_id;324uid_t ae_uid;325gid_t ae_gid;326const char *ae_name;327int entries;328int i;329int ret;330int e = 0;331struct richacl *richacl = NULL;332struct richace *richace;333334ret = ARCHIVE_OK;335entries = archive_acl_reset(abstract_acl, ae_requested_type);336if (entries == 0)337return (ARCHIVE_OK);338339if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {340errno = ENOENT;341archive_set_error(a, errno, "Unsupported ACL type");342return (ARCHIVE_FAILED);343}344345if (S_ISLNK(mode)) {346/* Linux does not support RichACLs on symbolic links */347return (ARCHIVE_OK);348}349350richacl = richacl_alloc(entries);351if (richacl == NULL) {352archive_set_error(a, errno,353"Failed to initialize RichACL working storage");354return (ARCHIVE_FAILED);355}356357e = 0;358359while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,360&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {361richace = &(richacl->a_entries[e]);362363richace->e_flags = 0;364richace->e_mask = 0;365366switch (ae_tag) {367case ARCHIVE_ENTRY_ACL_USER:368ae_uid = archive_write_disk_uid(a, ae_name, ae_id);369richace->e_id = ae_uid;370break;371case ARCHIVE_ENTRY_ACL_GROUP:372ae_gid = archive_write_disk_gid(a, ae_name, ae_id);373richace->e_id = ae_gid;374richace->e_flags |= RICHACE_IDENTIFIER_GROUP;375break;376case ARCHIVE_ENTRY_ACL_USER_OBJ:377richace->e_flags |= RICHACE_SPECIAL_WHO;378richace->e_id = RICHACE_OWNER_SPECIAL_ID;379break;380case ARCHIVE_ENTRY_ACL_GROUP_OBJ:381richace->e_flags |= RICHACE_SPECIAL_WHO;382richace->e_id = RICHACE_GROUP_SPECIAL_ID;383break;384case ARCHIVE_ENTRY_ACL_EVERYONE:385richace->e_flags |= RICHACE_SPECIAL_WHO;386richace->e_id = RICHACE_EVERYONE_SPECIAL_ID;387break;388default:389archive_set_error(a, ARCHIVE_ERRNO_MISC,390"Unsupported ACL tag");391ret = ARCHIVE_FAILED;392goto exit_free;393}394395switch (ae_type) {396case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:397richace->e_type =398RICHACE_ACCESS_ALLOWED_ACE_TYPE;399break;400case ARCHIVE_ENTRY_ACL_TYPE_DENY:401richace->e_type =402RICHACE_ACCESS_DENIED_ACE_TYPE;403break;404case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:405case ARCHIVE_ENTRY_ACL_TYPE_ALARM:406break;407default:408archive_set_error(a, ARCHIVE_ERRNO_MISC,409"Unsupported ACL entry type");410ret = ARCHIVE_FAILED;411goto exit_free;412}413414for (i = 0; i < acl_nfs4_perm_map_size; ++i) {415if (ae_permset & acl_nfs4_perm_map[i].a_perm)416richace->e_mask |= acl_nfs4_perm_map[i].p_perm;417}418419for (i = 0; i < acl_nfs4_flag_map_size; ++i) {420if (ae_permset &421acl_nfs4_flag_map[i].a_perm)422richace->e_flags |= acl_nfs4_flag_map[i].p_perm;423}424e++;425}426427/* Fill RichACL masks */428_richacl_mode_to_masks(richacl, mode);429430if (fd >= 0) {431if (richacl_set_fd(fd, richacl) == 0)432ret = ARCHIVE_OK;433else {434if (errno == EOPNOTSUPP) {435/* Filesystem doesn't support ACLs */436ret = ARCHIVE_OK;437} else {438archive_set_error(a, errno,439"Failed to set richacl on fd: %s", tname);440ret = ARCHIVE_WARN;441}442}443} else if (richacl_set_file(name, richacl) != 0) {444if (errno == EOPNOTSUPP) {445/* Filesystem doesn't support ACLs */446ret = ARCHIVE_OK;447} else {448archive_set_error(a, errno, "Failed to set richacl: %s",449tname);450ret = ARCHIVE_WARN;451}452}453exit_free:454richacl_free(richacl);455return (ret);456}457#endif /* ARCHIVE_ACL_RICHACL */458459#if ARCHIVE_ACL_LIBACL460static int461set_acl(struct archive *a, int fd, const char *name,462struct archive_acl *abstract_acl, __LA_MODE_T mode,463int ae_requested_type, const char *tname)464{465int acl_type = 0;466int ae_type, ae_permset, ae_tag, ae_id;467uid_t ae_uid;468gid_t ae_gid;469const char *ae_name;470int entries;471int i;472int ret;473acl_t acl = NULL;474acl_entry_t acl_entry;475acl_permset_t acl_permset;476477ret = ARCHIVE_OK;478entries = archive_acl_reset(abstract_acl, ae_requested_type);479if (entries == 0)480return (ARCHIVE_OK);481482switch (ae_requested_type) {483case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:484acl_type = ACL_TYPE_ACCESS;485break;486case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:487acl_type = ACL_TYPE_DEFAULT;488break;489default:490errno = ENOENT;491archive_set_error(a, errno, "Unsupported ACL type");492return (ARCHIVE_FAILED);493}494495if (S_ISLNK(mode)) {496/* Linux does not support ACLs on symbolic links */497return (ARCHIVE_OK);498}499500if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {501errno = EINVAL;502archive_set_error(a, errno,503"Cannot set default ACL on non-directory");504return (ARCHIVE_WARN);505}506507acl = acl_init(entries);508if (acl == (acl_t)NULL) {509archive_set_error(a, errno,510"Failed to initialize ACL working storage");511return (ARCHIVE_FAILED);512}513514while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,515&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {516517if (acl_create_entry(&acl, &acl_entry) != 0) {518archive_set_error(a, errno,519"Failed to create a new ACL entry");520ret = ARCHIVE_FAILED;521goto exit_free;522}523524switch (ae_tag) {525case ARCHIVE_ENTRY_ACL_USER:526ae_uid = archive_write_disk_uid(a, ae_name, ae_id);527acl_set_tag_type(acl_entry, ACL_USER);528acl_set_qualifier(acl_entry, &ae_uid);529break;530case ARCHIVE_ENTRY_ACL_GROUP:531ae_gid = archive_write_disk_gid(a, ae_name, ae_id);532acl_set_tag_type(acl_entry, ACL_GROUP);533acl_set_qualifier(acl_entry, &ae_gid);534break;535case ARCHIVE_ENTRY_ACL_USER_OBJ:536acl_set_tag_type(acl_entry, ACL_USER_OBJ);537break;538case ARCHIVE_ENTRY_ACL_GROUP_OBJ:539acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);540break;541case ARCHIVE_ENTRY_ACL_MASK:542acl_set_tag_type(acl_entry, ACL_MASK);543break;544case ARCHIVE_ENTRY_ACL_OTHER:545acl_set_tag_type(acl_entry, ACL_OTHER);546break;547default:548archive_set_error(a, ARCHIVE_ERRNO_MISC,549"Unsupported ACL tag");550ret = ARCHIVE_FAILED;551goto exit_free;552}553554if (acl_get_permset(acl_entry, &acl_permset) != 0) {555archive_set_error(a, errno,556"Failed to get ACL permission set");557ret = ARCHIVE_FAILED;558goto exit_free;559}560if (acl_clear_perms(acl_permset) != 0) {561archive_set_error(a, errno,562"Failed to clear ACL permissions");563ret = ARCHIVE_FAILED;564goto exit_free;565}566567for (i = 0; i < acl_posix_perm_map_size; ++i) {568if (ae_permset & acl_posix_perm_map[i].a_perm) {569if (acl_add_perm(acl_permset,570acl_posix_perm_map[i].p_perm) != 0) {571archive_set_error(a, errno,572"Failed to add ACL permission");573ret = ARCHIVE_FAILED;574goto exit_free;575}576}577}578579}580581if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {582if (acl_set_fd(fd, acl) == 0)583ret = ARCHIVE_OK;584else {585if (errno == EOPNOTSUPP) {586/* Filesystem doesn't support ACLs */587ret = ARCHIVE_OK;588} else {589archive_set_error(a, errno,590"Failed to set acl on fd: %s", tname);591ret = ARCHIVE_WARN;592}593}594} else if (acl_set_file(name, acl_type, acl) != 0) {595if (errno == EOPNOTSUPP) {596/* Filesystem doesn't support ACLs */597ret = ARCHIVE_OK;598} else {599archive_set_error(a, errno, "Failed to set acl: %s",600tname);601ret = ARCHIVE_WARN;602}603}604exit_free:605acl_free(acl);606return (ret);607}608#endif /* ARCHIVE_ACL_LIBACL */609610int611archive_read_disk_entry_setup_acls(struct archive_read_disk *a,612struct archive_entry *entry, int *fd)613{614const char *accpath;615int r;616#if ARCHIVE_ACL_LIBACL617acl_t acl;618#endif619#if ARCHIVE_ACL_LIBRICHACL620struct richacl *richacl;621mode_t mode;622#endif623624accpath = NULL;625r = ARCHIVE_OK;626627/* For default ACLs we need reachable accpath */628if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {629accpath = archive_read_disk_entry_setup_path(a, entry, fd);630if (accpath == NULL)631return (ARCHIVE_WARN);632}633634archive_entry_acl_clear(entry);635636#if ARCHIVE_ACL_LIBACL637acl = NULL;638#endif639#if ARCHIVE_ACL_LIBRICHACL640richacl = NULL;641#endif642643#if ARCHIVE_ACL_LIBRICHACL644/* Try NFSv4 ACL first. */645if (*fd >= 0)646richacl = richacl_get_fd(*fd);647else if ((!a->follow_symlinks)648&& (archive_entry_filetype(entry) == AE_IFLNK))649/* We can't get the ACL of a symlink, so we assume it can't650have one */651richacl = NULL;652else653richacl = richacl_get_file(accpath);654655/* Ignore "trivial" ACLs that just mirror the file mode. */656if (richacl != NULL) {657mode = archive_entry_mode(entry);658if (richacl_equiv_mode(richacl, &mode) == 0) {659richacl_free(richacl);660richacl = NULL;661return (ARCHIVE_OK);662}663}664665if (richacl != NULL) {666r = translate_richacl(a, entry, richacl);667richacl_free(richacl);668richacl = NULL;669670if (r != ARCHIVE_OK) {671archive_set_error(&a->archive, errno,672"Couldn't translate NFSv4 ACLs");673}674675return (r);676}677#endif /* ARCHIVE_ACL_LIBRICHACL */678679#if ARCHIVE_ACL_LIBACL680/* Retrieve access ACL from file. */681if (*fd >= 0)682acl = acl_get_fd(*fd);683else if ((!a->follow_symlinks)684&& (archive_entry_filetype(entry) == AE_IFLNK))685/* We can't get the ACL of a symlink, so we assume it can't686have one. */687acl = NULL;688else689acl = acl_get_file(accpath, ACL_TYPE_ACCESS);690691if (acl != NULL) {692r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);693acl_free(acl);694acl = NULL;695696if (r != ARCHIVE_OK) {697archive_set_error(&a->archive, errno,698"Couldn't translate access ACLs");699return (r);700}701}702703/* Only directories can have default ACLs. */704if (S_ISDIR(archive_entry_mode(entry))) {705acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);706if (acl != NULL) {707r = translate_acl(a, entry, acl,708ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);709acl_free(acl);710if (r != ARCHIVE_OK) {711archive_set_error(&a->archive, errno,712"Couldn't translate default ACLs");713return (r);714}715}716}717#endif /* ARCHIVE_ACL_LIBACL */718return (r);719}720721int722archive_write_disk_set_acls(struct archive *a, int fd, const char *name,723struct archive_acl *abstract_acl, __LA_MODE_T mode)724{725int ret = ARCHIVE_OK;726727#if !ARCHIVE_ACL_LIBRICHACL728(void)mode; /* UNUSED */729#endif730731#if ARCHIVE_ACL_LIBRICHACL732if ((archive_acl_types(abstract_acl)733& ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {734ret = set_richacl(a, fd, name, abstract_acl, mode,735ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");736}737#if ARCHIVE_ACL_LIBACL738else739#endif740#endif /* ARCHIVE_ACL_LIBRICHACL */741#if ARCHIVE_ACL_LIBACL742if ((archive_acl_types(abstract_acl)743& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {744if ((archive_acl_types(abstract_acl)745& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {746ret = set_acl(a, fd, name, abstract_acl, mode,747ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");748if (ret != ARCHIVE_OK)749return (ret);750}751if ((archive_acl_types(abstract_acl)752& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)753ret = set_acl(a, fd, name, abstract_acl, mode,754ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");755}756#endif /* ARCHIVE_ACL_LIBACL */757return (ret);758}759#endif /* ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL */760761762