Path: blob/master/Utilities/cmlibarchive/libarchive/archive_disk_acl_sunos.c
3153 views
/*-1* Copyright (c) 2017 Martin Matuska2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR14* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES15* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.16* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,17* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT18* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,19* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY20* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT21* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF22* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.23*/2425#include "archive_platform.h"2627#if ARCHIVE_ACL_SUNOS2829#ifdef HAVE_ERRNO_H30#include <errno.h>31#endif32#ifdef HAVE_FCNTL_H33#include <fcntl.h>34#endif35#ifdef HAVE_SYS_TYPES_H36#include <sys/types.h>37#endif38#ifdef HAVE_SYS_ACL_H39#define _ACL_PRIVATE /* For debugging */40#include <sys/acl.h>41#endif4243#include "archive_entry.h"44#include "archive_private.h"45#include "archive_read_disk_private.h"46#include "archive_write_disk_private.h"4748typedef struct {49const int a_perm; /* Libarchive permission or flag */50const int p_perm; /* Platform permission or flag */51} acl_perm_map_t;5253static const acl_perm_map_t acl_posix_perm_map[] = {54{ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH },55{ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH },56{ARCHIVE_ENTRY_ACL_READ, S_IROTH }57};5859static const int acl_posix_perm_map_size =60(int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));6162#if ARCHIVE_ACL_SUNOS_NFS463static const acl_perm_map_t acl_nfs4_perm_map[] = {64{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},65{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},66{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},67{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},68{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},69{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},70{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},71{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},72{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},73{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},74{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},75{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},76{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},77{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},78{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},79{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},80{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}81};8283static const int acl_nfs4_perm_map_size =84(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));8586static const acl_perm_map_t acl_nfs4_flag_map[] = {87{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},88{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},89{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},90{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},91{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},92{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},93#ifdef ACE_INHERITED_ACE94{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}95#endif96};9798const int acl_nfs4_flag_map_size =99(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));100101#endif /* ARCHIVE_ACL_SUNOS_NFS4 */102103static void *104sunacl_get(int cmd, int *aclcnt, int fd, const char *path)105{106int cnt, cntcmd;107size_t size;108void *aclp;109110if (cmd == GETACL) {111cntcmd = GETACLCNT;112size = sizeof(aclent_t);113}114#if ARCHIVE_ACL_SUNOS_NFS4115else if (cmd == ACE_GETACL) {116cntcmd = ACE_GETACLCNT;117size = sizeof(ace_t);118}119#endif120else {121errno = EINVAL;122*aclcnt = -1;123return (NULL);124}125126aclp = NULL;127cnt = -2;128129while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {130if (path != NULL)131cnt = acl(path, cntcmd, 0, NULL);132else133cnt = facl(fd, cntcmd, 0, NULL);134135if (cnt > 0) {136if (aclp == NULL)137aclp = malloc(cnt * size);138else139aclp = realloc(NULL, cnt * size);140if (aclp != NULL) {141if (path != NULL)142cnt = acl(path, cmd, cnt, aclp);143else144cnt = facl(fd, cmd, cnt, aclp);145}146} else {147free(aclp);148aclp = NULL;149break;150}151}152153*aclcnt = cnt;154return (aclp);155}156157/*158* Check if acl is trivial159* This is a FreeBSD acl_is_trivial_np() implementation for Solaris160*/161static int162sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,163int is_dir, int *trivialp)164{165#if ARCHIVE_ACL_SUNOS_NFS4166int i, p;167const uint32_t rperm = ACE_READ_DATA;168const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;169const uint32_t eperm = ACE_EXECUTE;170const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |171ACE_READ_ACL | ACE_SYNCHRONIZE;172const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |173ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;174175ace_t *ace;176ace_t tace[6];177#endif178179if (aclp == NULL || trivialp == NULL)180return (-1);181182*trivialp = 0;183184/*185* POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with186* FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,187* including mask.188*/189if (!is_nfs4) {190if (aclcnt == 4)191*trivialp = 1;192return (0);193}194195#if ARCHIVE_ACL_SUNOS_NFS4196/*197* Continue with checking NFSv4 ACLs198*199* Create list of trivial ace's to be compared200*/201202/* owner@ allow pre */203tace[0].a_flags = ACE_OWNER;204tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;205tace[0].a_access_mask = 0;206207/* owner@ deny */208tace[1].a_flags = ACE_OWNER;209tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;210tace[1].a_access_mask = 0;211212/* group@ deny */213tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;214tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;215tace[2].a_access_mask = 0;216217/* owner@ allow */218tace[3].a_flags = ACE_OWNER;219tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;220tace[3].a_access_mask = ownset;221222/* group@ allow */223tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;224tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;225tace[4].a_access_mask = pubset;226227/* everyone@ allow */228tace[5].a_flags = ACE_EVERYONE;229tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;230tace[5].a_access_mask = pubset;231232/* Permissions for everyone@ */233if (mode & 0004)234tace[5].a_access_mask |= rperm;235if (mode & 0002)236tace[5].a_access_mask |= wperm;237if (mode & 0001)238tace[5].a_access_mask |= eperm;239240/* Permissions for group@ */241if (mode & 0040)242tace[4].a_access_mask |= rperm;243else if (mode & 0004)244tace[2].a_access_mask |= rperm;245if (mode & 0020)246tace[4].a_access_mask |= wperm;247else if (mode & 0002)248tace[2].a_access_mask |= wperm;249if (mode & 0010)250tace[4].a_access_mask |= eperm;251else if (mode & 0001)252tace[2].a_access_mask |= eperm;253254/* Permissions for owner@ */255if (mode & 0400) {256tace[3].a_access_mask |= rperm;257if (!(mode & 0040) && (mode & 0004))258tace[0].a_access_mask |= rperm;259} else if ((mode & 0040) || (mode & 0004))260tace[1].a_access_mask |= rperm;261if (mode & 0200) {262tace[3].a_access_mask |= wperm;263if (!(mode & 0020) && (mode & 0002))264tace[0].a_access_mask |= wperm;265} else if ((mode & 0020) || (mode & 0002))266tace[1].a_access_mask |= wperm;267if (mode & 0100) {268tace[3].a_access_mask |= eperm;269if (!(mode & 0010) && (mode & 0001))270tace[0].a_access_mask |= eperm;271} else if ((mode & 0010) || (mode & 0001))272tace[1].a_access_mask |= eperm;273274/* Check if the acl count matches */275p = 3;276for (i = 0; i < 3; i++) {277if (tace[i].a_access_mask != 0)278p++;279}280if (aclcnt != p)281return (0);282283p = 0;284for (i = 0; i < 6; i++) {285if (tace[i].a_access_mask != 0) {286ace = &((ace_t *)aclp)[p];287/*288* Illumos added ACE_DELETE_CHILD to write perms for289* directories. We have to check against that, too.290*/291if (ace->a_flags != tace[i].a_flags ||292ace->a_type != tace[i].a_type ||293(ace->a_access_mask != tace[i].a_access_mask &&294(!is_dir || (tace[i].a_access_mask & wperm) == 0 ||295ace->a_access_mask !=296(tace[i].a_access_mask | ACE_DELETE_CHILD))))297return (0);298p++;299}300}301302*trivialp = 1;303#else /* !ARCHIVE_ACL_SUNOS_NFS4 */304(void)is_dir; /* UNUSED */305(void)aclp; /* UNUSED */306#endif /* !ARCHIVE_ACL_SUNOS_NFS4 */307return (0);308}309310/*311* Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL312*/313static int314translate_acl(struct archive_read_disk *a,315struct archive_entry *entry, void *aclp, int aclcnt,316int default_entry_acl_type)317{318int e, i;319int ae_id, ae_tag, ae_perm;320int entry_acl_type;321const char *ae_name;322aclent_t *aclent;323#if ARCHIVE_ACL_SUNOS_NFS4324ace_t *ace;325#endif326327if (aclcnt <= 0)328return (ARCHIVE_OK);329330for (e = 0; e < aclcnt; e++) {331ae_name = NULL;332ae_tag = 0;333ae_perm = 0;334335#if ARCHIVE_ACL_SUNOS_NFS4336if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {337ace = &((ace_t *)aclp)[e];338ae_id = ace->a_who;339340switch(ace->a_type) {341case ACE_ACCESS_ALLOWED_ACE_TYPE:342entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;343break;344case ACE_ACCESS_DENIED_ACE_TYPE:345entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;346break;347case ACE_SYSTEM_AUDIT_ACE_TYPE:348entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;349break;350case ACE_SYSTEM_ALARM_ACE_TYPE:351entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;352break;353default:354/* Unknown entry type, skip */355continue;356}357358if ((ace->a_flags & ACE_OWNER) != 0)359ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;360else if ((ace->a_flags & ACE_GROUP) != 0)361ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;362else if ((ace->a_flags & ACE_EVERYONE) != 0)363ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;364else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {365ae_tag = ARCHIVE_ENTRY_ACL_GROUP;366ae_name = archive_read_disk_gname(&a->archive,367ae_id);368} else {369ae_tag = ARCHIVE_ENTRY_ACL_USER;370ae_name = archive_read_disk_uname(&a->archive,371ae_id);372}373374for (i = 0; i < acl_nfs4_flag_map_size; ++i) {375if ((ace->a_flags &376acl_nfs4_flag_map[i].p_perm) != 0)377ae_perm |= acl_nfs4_flag_map[i].a_perm;378}379380for (i = 0; i < acl_nfs4_perm_map_size; ++i) {381if ((ace->a_access_mask &382acl_nfs4_perm_map[i].p_perm) != 0)383ae_perm |= acl_nfs4_perm_map[i].a_perm;384}385} else386#endif /* ARCHIVE_ACL_SUNOS_NFS4 */387if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {388aclent = &((aclent_t *)aclp)[e];389if ((aclent->a_type & ACL_DEFAULT) != 0)390entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;391else392entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;393ae_id = aclent->a_id;394395switch(aclent->a_type) {396case DEF_USER:397case USER:398ae_name = archive_read_disk_uname(&a->archive,399ae_id);400ae_tag = ARCHIVE_ENTRY_ACL_USER;401break;402case DEF_GROUP:403case GROUP:404ae_name = archive_read_disk_gname(&a->archive,405ae_id);406ae_tag = ARCHIVE_ENTRY_ACL_GROUP;407break;408case DEF_CLASS_OBJ:409case CLASS_OBJ:410ae_tag = ARCHIVE_ENTRY_ACL_MASK;411break;412case DEF_USER_OBJ:413case USER_OBJ:414ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;415break;416case DEF_GROUP_OBJ:417case GROUP_OBJ:418ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;419break;420case DEF_OTHER_OBJ:421case OTHER_OBJ:422ae_tag = ARCHIVE_ENTRY_ACL_OTHER;423break;424default:425/* Unknown tag type, skip */426continue;427}428429for (i = 0; i < acl_posix_perm_map_size; ++i) {430if ((aclent->a_perm &431acl_posix_perm_map[i].p_perm) != 0)432ae_perm |= acl_posix_perm_map[i].a_perm;433}434} else435return (ARCHIVE_WARN);436437archive_entry_acl_add_entry(entry, entry_acl_type,438ae_perm, ae_tag, ae_id, ae_name);439}440return (ARCHIVE_OK);441}442443static int444set_acl(struct archive *a, int fd, const char *name,445struct archive_acl *abstract_acl, __LA_MODE_T mode,446int ae_requested_type, const char *tname)447{448aclent_t *aclent;449#if ARCHIVE_ACL_SUNOS_NFS4450ace_t *ace;451#endif452int cmd, e, r;453void *aclp;454int ret;455int ae_type, ae_permset, ae_tag, ae_id;456int perm_map_size;457const acl_perm_map_t *perm_map;458uid_t ae_uid;459gid_t ae_gid;460const char *ae_name;461int entries;462int i;463464ret = ARCHIVE_OK;465entries = archive_acl_reset(abstract_acl, ae_requested_type);466if (entries == 0)467return (ARCHIVE_OK);468469switch (ae_requested_type) {470case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:471cmd = SETACL;472aclp = malloc(entries * sizeof(aclent_t));473break;474#if ARCHIVE_ACL_SUNOS_NFS4475case ARCHIVE_ENTRY_ACL_TYPE_NFS4:476cmd = ACE_SETACL;477aclp = malloc(entries * sizeof(ace_t));478479break;480#endif481default:482errno = ENOENT;483archive_set_error(a, errno, "Unsupported ACL type");484return (ARCHIVE_FAILED);485}486487if (aclp == NULL) {488archive_set_error(a, errno,489"Can't allocate memory for acl buffer");490return (ARCHIVE_FAILED);491}492493if (S_ISLNK(mode)) {494/* Skip ACLs on symbolic links */495ret = ARCHIVE_OK;496goto exit_free;497}498499e = 0;500501while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,502&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {503aclent = NULL;504#if ARCHIVE_ACL_SUNOS_NFS4505ace = NULL;506#endif507if (cmd == SETACL) {508aclent = &((aclent_t *)aclp)[e];509aclent->a_id = -1;510aclent->a_type = 0;511aclent->a_perm = 0;512}513#if ARCHIVE_ACL_SUNOS_NFS4514else { /* cmd == ACE_SETACL */515ace = &((ace_t *)aclp)[e];516ace->a_who = -1;517ace->a_access_mask = 0;518ace->a_flags = 0;519}520#endif /* ARCHIVE_ACL_SUNOS_NFS4 */521522switch (ae_tag) {523case ARCHIVE_ENTRY_ACL_USER:524ae_uid = archive_write_disk_uid(a, ae_name, ae_id);525if (aclent != NULL) {526aclent->a_id = ae_uid;527aclent->a_type |= USER;528}529#if ARCHIVE_ACL_SUNOS_NFS4530else {531ace->a_who = ae_uid;532}533#endif534break;535case ARCHIVE_ENTRY_ACL_GROUP:536ae_gid = archive_write_disk_gid(a, ae_name, ae_id);537if (aclent != NULL) {538aclent->a_id = ae_gid;539aclent->a_type |= GROUP;540}541#if ARCHIVE_ACL_SUNOS_NFS4542else {543ace->a_who = ae_gid;544ace->a_flags |= ACE_IDENTIFIER_GROUP;545}546#endif547break;548case ARCHIVE_ENTRY_ACL_USER_OBJ:549if (aclent != NULL)550aclent->a_type |= USER_OBJ;551#if ARCHIVE_ACL_SUNOS_NFS4552else {553ace->a_flags |= ACE_OWNER;554}555#endif556break;557case ARCHIVE_ENTRY_ACL_GROUP_OBJ:558if (aclent != NULL)559aclent->a_type |= GROUP_OBJ;560#if ARCHIVE_ACL_SUNOS_NFS4561else {562ace->a_flags |= ACE_GROUP;563ace->a_flags |= ACE_IDENTIFIER_GROUP;564}565#endif566break;567case ARCHIVE_ENTRY_ACL_MASK:568if (aclent != NULL)569aclent->a_type |= CLASS_OBJ;570break;571case ARCHIVE_ENTRY_ACL_OTHER:572if (aclent != NULL)573aclent->a_type |= OTHER_OBJ;574break;575#if ARCHIVE_ACL_SUNOS_NFS4576case ARCHIVE_ENTRY_ACL_EVERYONE:577if (ace != NULL)578ace->a_flags |= ACE_EVERYONE;579break;580#endif581default:582archive_set_error(a, ARCHIVE_ERRNO_MISC,583"Unsupported ACL tag");584ret = ARCHIVE_FAILED;585goto exit_free;586}587588r = 0;589switch (ae_type) {590#if ARCHIVE_ACL_SUNOS_NFS4591case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:592if (ace != NULL)593ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;594else595r = -1;596break;597case ARCHIVE_ENTRY_ACL_TYPE_DENY:598if (ace != NULL)599ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;600else601r = -1;602break;603case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:604if (ace != NULL)605ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;606else607r = -1;608break;609case ARCHIVE_ENTRY_ACL_TYPE_ALARM:610if (ace != NULL)611ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;612else613r = -1;614break;615#endif616case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:617if (aclent == NULL)618r = -1;619break;620case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:621if (aclent != NULL)622aclent->a_type |= ACL_DEFAULT;623else624r = -1;625break;626default:627archive_set_error(a, ARCHIVE_ERRNO_MISC,628"Unsupported ACL entry type");629ret = ARCHIVE_FAILED;630goto exit_free;631}632633if (r != 0) {634errno = EINVAL;635archive_set_error(a, errno,636"Failed to set ACL entry type");637ret = ARCHIVE_FAILED;638goto exit_free;639}640641#if ARCHIVE_ACL_SUNOS_NFS4642if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {643perm_map_size = acl_nfs4_perm_map_size;644perm_map = acl_nfs4_perm_map;645} else {646#endif647perm_map_size = acl_posix_perm_map_size;648perm_map = acl_posix_perm_map;649#if ARCHIVE_ACL_SUNOS_NFS4650}651#endif652for (i = 0; i < perm_map_size; ++i) {653if (ae_permset & perm_map[i].a_perm) {654#if ARCHIVE_ACL_SUNOS_NFS4655if (ae_requested_type ==656ARCHIVE_ENTRY_ACL_TYPE_NFS4)657ace->a_access_mask |=658perm_map[i].p_perm;659else660#endif661aclent->a_perm |= perm_map[i].p_perm;662}663}664665#if ARCHIVE_ACL_SUNOS_NFS4666if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {667for (i = 0; i < acl_nfs4_flag_map_size; ++i) {668if (ae_permset & acl_nfs4_flag_map[i].a_perm) {669ace->a_flags |=670acl_nfs4_flag_map[i].p_perm;671}672}673}674#endif675e++;676}677678/* Try restoring the ACL through 'fd' if we can. */679if (fd >= 0) {680if (facl(fd, cmd, entries, aclp) == 0)681ret = ARCHIVE_OK;682else {683if (errno == EOPNOTSUPP) {684/* Filesystem doesn't support ACLs */685ret = ARCHIVE_OK;686} else {687archive_set_error(a, errno,688"Failed to set acl on fd: %s", tname);689ret = ARCHIVE_WARN;690}691}692} else if (acl(name, cmd, entries, aclp) != 0) {693if (errno == EOPNOTSUPP) {694/* Filesystem doesn't support ACLs */695ret = ARCHIVE_OK;696} else {697archive_set_error(a, errno, "Failed to set acl: %s",698tname);699ret = ARCHIVE_WARN;700}701}702exit_free:703free(aclp);704return (ret);705}706707int708archive_read_disk_entry_setup_acls(struct archive_read_disk *a,709struct archive_entry *entry, int *fd)710{711const char *accpath;712void *aclp;713int aclcnt;714int r;715716accpath = NULL;717718if (*fd < 0) {719accpath = archive_read_disk_entry_setup_path(a, entry, fd);720if (accpath == NULL)721return (ARCHIVE_WARN);722}723724archive_entry_acl_clear(entry);725726aclp = NULL;727728#if ARCHIVE_ACL_SUNOS_NFS4729if (*fd >= 0)730aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);731else if ((!a->follow_symlinks)732&& (archive_entry_filetype(entry) == AE_IFLNK))733/* We can't get the ACL of a symlink, so we assume it can't734have one. */735aclp = NULL;736else737aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);738739if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,740archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),741&r) == 0 && r == 1) {742free(aclp);743aclp = NULL;744return (ARCHIVE_OK);745}746747if (aclp != NULL) {748r = translate_acl(a, entry, aclp, aclcnt,749ARCHIVE_ENTRY_ACL_TYPE_NFS4);750free(aclp);751aclp = NULL;752753if (r != ARCHIVE_OK) {754archive_set_error(&a->archive, errno,755"Couldn't translate NFSv4 ACLs");756}757return (r);758}759#endif /* ARCHIVE_ACL_SUNOS_NFS4 */760761/* Retrieve POSIX.1e ACLs from file. */762if (*fd >= 0)763aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);764else if ((!a->follow_symlinks)765&& (archive_entry_filetype(entry) == AE_IFLNK))766/* We can't get the ACL of a symlink, so we assume it can't767have one. */768aclp = NULL;769else770aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);771772/* Ignore "trivial" ACLs that just mirror the file mode. */773if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,774archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),775&r) == 0 && r == 1) {776free(aclp);777aclp = NULL;778}779780if (aclp != NULL)781{782r = translate_acl(a, entry, aclp, aclcnt,783ARCHIVE_ENTRY_ACL_TYPE_ACCESS);784free(aclp);785aclp = NULL;786787if (r != ARCHIVE_OK) {788archive_set_error(&a->archive, errno,789"Couldn't translate access ACLs");790return (r);791}792}793794return (ARCHIVE_OK);795}796797int798archive_write_disk_set_acls(struct archive *a, int fd, const char *name,799struct archive_acl *abstract_acl, __LA_MODE_T mode)800{801int ret = ARCHIVE_OK;802803(void)mode; /* UNUSED */804805if ((archive_acl_types(abstract_acl)806& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {807/* Solaris writes POSIX.1e access and default ACLs together */808ret = set_acl(a, fd, name, abstract_acl, mode,809ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");810811/* Simultaneous POSIX.1e and NFSv4 is not supported */812return (ret);813}814#if ARCHIVE_ACL_SUNOS_NFS4815else if ((archive_acl_types(abstract_acl) &816ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {817ret = set_acl(a, fd, name, abstract_acl, mode,818ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");819}820#endif821return (ret);822}823#endif /* ARCHIVE_ACL_SUNOS */824825826