MFV r315633, 315635:

Sync libarchive with vendor

Vendor changes/bugfixes (FreeBSD-related):
  PR 867 (bsdcpio): show numeric uid/gid when names are not found
  PR 870 (seekable zip): accept files with valid ZIP64 EOCD headers
  PR 880 (pax): Fix handling of "size" pax header keyword
  PR 887 (crypto): Discard 3072 bytes instead of 1024 of first keystream
  OSS-Fuzz issue 806 (mtree): rework mtree_atol10 integer parser
  Break ACL read/write code into platform-specific source files
  Unbreak static dependency on libbz2

MFC after:	1 week
This commit is contained in:
Martin Matuska 2017-03-20 13:02:27 +00:00
commit 4657548d18
33 changed files with 1707 additions and 2447 deletions

View File

@ -1,3 +1,5 @@
Mar 16, 2017: NFSv4 ACL support for Linux (librichacl)
Feb 26, 2017: libarchive 3.3.1 released
Security & Feature release
@ -293,7 +295,7 @@ May 04, 2008: libarchive 2.5.3b released
* libarchive: Mark which entry strings are set; be accurate about
distinguishing empty strings ("") from unset ones (NULL)
* tar: Don't crash reading entries with empty filenames
* libarchive_test, bsdtar_test, bsdcpio_test: Better detaults:
* libarchive_test, bsdtar_test, bsdcpio_test: Better defaults:
run all tests, delete temp dirs, summarize repeated failures
* -no-undefined to libtool for Cygwin
* libarchive_test: Skip large file tests on systems with 32-bit off_t

View File

@ -1344,23 +1344,23 @@ lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
cache->cache[slot].name = NULL;
}
if (lookup_fn(cpio, &name, id) == 0) {
if (name == NULL || name[0] == '\0') {
/* If lookup failed, format it as a number. */
snprintf(asnum, sizeof(asnum), "%u", (unsigned)id);
name = asnum;
}
cache->cache[slot].name = strdup(name);
if (cache->cache[slot].name != NULL) {
cache->cache[slot].id = id;
return (cache->cache[slot].name);
}
/*
* Conveniently, NULL marks an empty slot, so
* if the strdup() fails, we've just failed to
* cache it. No recovery necessary.
*/
if (lookup_fn(cpio, &name, id)) {
/* If lookup failed, format it as a number. */
snprintf(asnum, sizeof(asnum), "%u", (unsigned)id);
name = asnum;
}
cache->cache[slot].name = strdup(name);
if (cache->cache[slot].name != NULL) {
cache->cache[slot].id = id;
return (cache->cache[slot].name);
}
/*
* Conveniently, NULL marks an empty slot, so
* if the strdup() fails, we've just failed to
* cache it. No recovery necessary.
*/
return (NULL);
}
@ -1381,15 +1381,14 @@ lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
errno = 0;
pwent = getpwuid((uid_t)id);
if (pwent == NULL) {
*name = NULL;
if (errno != 0 && errno != ENOENT)
if (errno && errno != ENOENT)
lafe_warnc(errno, "getpwuid(%s) failed",
cpio_i64toa((int64_t)id));
return (errno);
return 1;
}
*name = pwent->pw_name;
return (0);
return 0;
}
static const char *
@ -1409,15 +1408,14 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
errno = 0;
grent = getgrgid((gid_t)id);
if (grent == NULL) {
*name = NULL;
if (errno != 0)
if (errno && errno != ENOENT)
lafe_warnc(errno, "getgrgid(%s) failed",
cpio_i64toa((int64_t)id));
return (errno);
return 1;
}
*name = grent->gr_name;
return (0);
return 0;
}
/*

View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#ifndef ARCHIVE_ACL_MAPS_H_INCLUDED
#define ARCHIVE_ACL_MAPS_H_INCLUDED
#include "archive_platform_acl.h"
typedef struct {
const int a_perm; /* Libarchive permission or flag */
const int p_perm; /* Platform permission or flag */
} acl_perm_map_t;
#if ARCHIVE_ACL_POSIX1E
extern const acl_perm_map_t acl_posix_perm_map[];
extern const int acl_posix_perm_map_size;
#endif
#if ARCHIVE_ACL_NFS4
extern const acl_perm_map_t acl_nfs4_perm_map[];
extern const int acl_nfs4_perm_map_size;
extern const acl_perm_map_t acl_nfs4_flag_map[];
extern const int acl_nfs4_flag_map_size;
#endif
#endif /* ARCHIVE_ACL_MAPS_H_INCLUDED */

View File

@ -0,0 +1,86 @@
/*-
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_ACL_H
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_disk_private.h"
#include "archive_acl_maps.h"
const acl_perm_map_t acl_posix_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
};
const int acl_posix_perm_map_size =
(int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
#if ARCHIVE_ACL_FREEBSD_NFS4
const acl_perm_map_t acl_nfs4_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
};
const int acl_nfs4_perm_map_size =
(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
const acl_perm_map_t acl_nfs4_flag_map[] = {
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
};
const int acl_nfs4_flag_map_size =
(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd Feburary 2, 2012
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY 3
.Os
.Sh NAME

View File

@ -267,7 +267,7 @@ Only inherit, do not apply the permission on the directory itself.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
Do not propagate inherit flags. Only first-level entries inherit ACLs.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
Trigger alarm or audit on succesful access.
Trigger alarm or audit on successful access.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
Trigger alarm or audit on failed access.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
@ -279,7 +279,7 @@ and
.Fn archive_entry_acl_add_entry_w
add a single ACL entry.
For the access ACL and non-extended principals, the classic Unix permissions
are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
are updated. An archive entry cannot contain both POSIX.1e and NFSv4 ACL
entries.
.Pp
.Fn archive_entry_acl_clear
@ -303,7 +303,7 @@ for POSIX.1e ACLs and
for NFSv4 ACLs. For POSIX.1e ACLs if
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
is included and at least one extended ACL entry is found,
the three non-extened ACLs are added.
the three non-extended ACLs are added.
.Pp
.Fn archive_entry_acl_from_text
and
@ -367,7 +367,7 @@ and
.Fn archive_entry_acl_to_text_w
convert the ACL entries for the given type into a
.Pq wide
string of ACL entries separated by newline. If the the pointer
string of ACL entries separated by newline. If the pointer
.Fa len_p
is not NULL, then the function shall return the length of the string
.Pq not including the NULL terminator

View File

@ -142,40 +142,6 @@
#define INTMAX_MIN ((intmax_t)(~INTMAX_MAX))
#endif
/*
* If this platform has <sys/acl.h>, acl_create(), acl_init(),
* acl_set_file(), and ACL_USER, we assume it has the rest of the
* POSIX.1e draft functions used in archive_read_extract.c.
*/
#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
#if HAVE_DECL_ACL_USER
#define HAVE_POSIX_ACL 1
#elif HAVE_DECL_ACL_TYPE_EXTENDED && HAVE_MEMBERSHIP_H
#define HAVE_DARWIN_ACL 1
#endif
#if HAVE_DECL_ACL_TYPE_NFS4
#define HAVE_FREEBSD_NFS4_ACL 1
#endif
#endif
/*
* If this platform has <sys/acl.h>, acl(), facl() and ACLENT_T
* facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
*/
#if HAVE_SYS_ACL_H && HAVE_ACL && HAVE_FACL && HAVE_ACLENT_T && \
HAVE_DECL_GETACL && HAVE_DECL_GETACLCNT && HAVE_DECL_SETACL
#define HAVE_SUN_ACL 1
#if HAVE_ACE_T && HAVE_DECL_ACE_GETACL && HAVE_DECL_ACE_GETACLCNT && \
HAVE_DECL_ACE_SETACL
#define HAVE_SUN_NFS4_ACL 1
#endif
#endif
/* Define if platform supports NFSv4 ACLs */
#if HAVE_FREEBSD_NFS4_ACL || HAVE_SUN_NFS4_ACL || HAVE_DARWIN_ACL
#define HAVE_NFS4_ACL 1
#endif
/*
* If we can't restore metadata using a file descriptor, then
* for compatibility's sake, close files before trying to restore metadata.

View File

@ -0,0 +1,49 @@
/*-
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED
#define ARCHIVE_PLATFORM_ACL_H_INCLUDED
/*
* Determine what ACL types are supported
*/
#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL
#define ARCHIVE_ACL_POSIX1E 1
#endif
#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
#define ARCHIVE_ACL_NFS4 1
#endif
#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4
#define ARCHIVE_ACL_SUPPORT 1
#endif
#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */

View File

@ -221,8 +221,11 @@ arc4_stir(void)
/*
* Discard early keystream, as per recommendations in:
* "(Not So) Random Shuffles of RC4" by Ilya Mironov.
* As per the Network Operations Division, cryptographic requirements
* published on wikileaks on March 2017.
*/
for (i = 0; i < 1024; i++)
for (i = 0; i < 3072; i++)
(void)arc4_getbyte();
arc4_count = 1600000;
}

View File

@ -0,0 +1,371 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* Copyright (c) 2016-2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_ACL_H
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_disk_private.h"
#include "archive_acl_maps.h"
/*
* Translate FreeBSD ACLs into libarchive internal structure
*/
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
#if ARCHIVE_ACL_FREEBSD_NFS4
int brand;
acl_flagset_t acl_flagset;
#endif
acl_tag_t acl_tag;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
acl_entry_type_t acl_type;
int i, entry_acl_type, perm_map_size;
const acl_perm_map_t *perm_map;
int r, s, ae_id, ae_tag, ae_perm;
void *q;
const char *ae_name;
#if ARCHIVE_ACL_FREEBSD_NFS4
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
// Make sure the "brand" on this ACL is consistent
// with the default_entry_acl_type bits provided.
if (acl_get_brand_np(acl, &brand) != 0) {
archive_set_error(&a->archive, errno,
"Failed to read ACL brand");
return (ARCHIVE_WARN);
}
switch (brand) {
case ACL_BRAND_POSIX:
switch (default_entry_acl_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid ACL entry type for POSIX.1e ACL");
return (ARCHIVE_WARN);
}
break;
case ACL_BRAND_NFS4:
if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid ACL entry type for NFSv4 ACL");
return (ARCHIVE_WARN);
}
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unknown ACL brand");
return (ARCHIVE_WARN);
}
#endif
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
if (s == -1) {
archive_set_error(&a->archive, errno,
"Failed to get first ACL entry");
return (ARCHIVE_WARN);
}
while (s == 1) {
ae_id = -1;
ae_name = NULL;
ae_perm = 0;
if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL tag type");
return (ARCHIVE_WARN);
}
switch (acl_tag) {
case ACL_USER:
q = acl_get_qualifier(acl_entry);
if (q != NULL) {
ae_id = (int)*(uid_t *)q;
acl_free(q);
ae_name = archive_read_disk_uname(&a->archive,
ae_id);
}
ae_tag = ARCHIVE_ENTRY_ACL_USER;
break;
case ACL_GROUP:
q = acl_get_qualifier(acl_entry);
if (q != NULL) {
ae_id = (int)*(gid_t *)q;
acl_free(q);
ae_name = archive_read_disk_gname(&a->archive,
ae_id);
}
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
break;
case ACL_MASK:
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
break;
case ACL_USER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
break;
case ACL_GROUP_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
break;
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
#if ARCHIVE_ACL_FREEBSD_NFS4
case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
#endif
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
// XXX acl_type maps to allow/deny/audit/YYYY bits
entry_acl_type = default_entry_acl_type;
#if ARCHIVE_ACL_FREEBSD_NFS4
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
/*
* acl_get_entry_type_np() fails with non-NFSv4 ACLs
*/
if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
archive_set_error(&a->archive, errno, "Failed "
"to get ACL type from a NFSv4 ACL entry");
return (ARCHIVE_WARN);
}
switch (acl_type) {
case ACL_ENTRY_TYPE_ALLOW:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
break;
case ACL_ENTRY_TYPE_DENY:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
break;
case ACL_ENTRY_TYPE_AUDIT:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
break;
case ACL_ENTRY_TYPE_ALARM:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
break;
default:
archive_set_error(&a->archive, errno,
"Invalid NFSv4 ACL entry type");
return (ARCHIVE_WARN);
}
/*
* Libarchive stores "flag" (NFSv4 inheritance bits)
* in the ae_perm bitmap.
*
* acl_get_flagset_np() fails with non-NFSv4 ACLs
*/
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get flagset from a NFSv4 "
"ACL entry");
return (ARCHIVE_WARN);
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
r = acl_get_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check flag in a NFSv4 "
"ACL flagset");
return (ARCHIVE_WARN);
} else if (r)
ae_perm |= acl_nfs4_flag_map[i].a_perm;
}
}
#endif
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL permission set");
return (ARCHIVE_WARN);
}
#if ARCHIVE_ACL_FREEBSD_NFS4
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
perm_map_size = acl_nfs4_perm_map_size;
perm_map = acl_nfs4_perm_map;
} else {
#endif
perm_map_size = acl_posix_perm_map_size;
perm_map = acl_posix_perm_map;
#if ARCHIVE_ACL_FREEBSD_NFS4
}
#endif
for (i = 0; i < perm_map_size; ++i) {
r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check permission in an ACL "
"permission set");
return (ARCHIVE_WARN);
} else if (r)
ae_perm |= perm_map[i].a_perm;
}
archive_entry_acl_add_entry(entry, entry_acl_type,
ae_perm, ae_tag,
ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
if (s == -1) {
archive_set_error(&a->archive, errno,
"Failed to get next ACL entry");
return (ARCHIVE_WARN);
}
}
return (ARCHIVE_OK);
}
int
archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
acl_t acl;
int r;
accpath = NULL;
if (*fd < 0) {
accpath = archive_read_disk_entry_setup_path(a, entry, fd);
if (accpath == NULL)
return (ARCHIVE_WARN);
}
archive_entry_acl_clear(entry);
acl = NULL;
#if ARCHIVE_ACL_FREEBSD_NFS4
/* Try NFSv4 ACL first. */
if (*fd >= 0)
acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
else
acl = acl_get_file(accpath, ACL_TYPE_NFS4);
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
acl_free(acl);
acl = NULL;
return (ARCHIVE_OK);
}
if (acl != NULL) {
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
acl_free(acl);
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate NFSv4 ACLs");
}
return (r);
}
#endif
/* Retrieve access ACL from file. */
if (*fd >= 0)
acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
#else
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
/* We can't get the ACL of a symlink, so we assume it can't
have one. */
acl = NULL;
#endif
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
#if HAVE_ACL_IS_TRIVIAL_NP
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
acl_free(acl);
acl = NULL;
}
#endif
if (acl != NULL) {
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate access ACLs");
return (r);
}
}
/* Only directories can have default ACLs. */
if (S_ISDIR(archive_entry_mode(entry))) {
if (*fd >= 0)
acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
else
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
r = translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
acl_free(acl);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate default ACLs");
return (r);
}
}
}
return (ARCHIVE_OK);
}

View File

@ -33,6 +33,8 @@
#ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
#include "archive_platform_acl.h"
struct tree;
struct archive_entry;
@ -86,4 +88,11 @@ struct archive_read_disk {
void *excluded_cb_data;
};
const char *
archive_read_disk_entry_setup_path(struct archive_read_disk *,
struct archive_entry *, int *);
int
archive_read_disk_entry_setup_acls(struct archive_read_disk *,
struct archive_entry *, int *);
#endif

View File

@ -67,7 +67,7 @@ Streaming Archive Library (libarchive, -larchive)
.Fa "size_t block_size"
.Fc
.Ft int
.Fn archive_read_open_memory "struct archive *" "void *buff" "size_t size"
.Fn archive_read_open_memory "struct archive *" "const void *buff" "size_t size"
.Sh DESCRIPTION
.Bl -tag -compact -width indent
.It Fn archive_read_open

View File

@ -1857,33 +1857,38 @@ mtree_atol8(char **p)
* Note that this implementation does not (and should not!) obey
* locale settings; you cannot simply substitute strtol here, since
* it does obey locale.
*
* Convert the number pointed to by 'p' into a 64-bit signed integer.
* On return, 'p' points to the first non-digit following the number.
* On overflow, the function returns INT64_MIN or INT64_MAX.
*/
static int64_t
mtree_atol10(char **p)
{
int64_t l, limit, last_digit_limit;
int base, digit, sign;
base = 10;
const int base = 10;
const int64_t limit = INT64_MAX / base;
const int64_t last_digit_limit = INT64_MAX % base;
int64_t l;
int sign;
if (**p == '-') {
sign = -1;
limit = ((uint64_t)(INT64_MAX) + 1) / base;
last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
++(*p);
} else {
sign = 1;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
}
l = 0;
digit = **p - '0';
while (digit >= 0 && digit < base) {
if (l > limit || (l == limit && digit > last_digit_limit))
while (**p >= '0' && **p < '0' + base) {
int digit = **p - '0';
if (l > limit || (l == limit && digit > last_digit_limit)) {
while (**p >= '0' && **p < '0' + base) {
++(*p);
}
return (sign < 0) ? INT64_MIN : INT64_MAX;
}
l = (l * base) + digit;
digit = *++(*p) - '0';
++(*p);
}
return (sign < 0) ? -l : l;
}

View File

@ -155,6 +155,7 @@ struct tar {
int compat_2x;
int process_mac_extensions;
int read_concatenated_archives;
int realsize_override;
};
static int archive_block_is_null(const char *p);
@ -527,6 +528,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
tar->entry_offset = 0;
gnu_clear_sparse_list(tar);
tar->realsize = -1; /* Mark this as "unset" */
tar->realsize_override = 0;
/* Setup default string conversion. */
tar->sconv = tar->opt_sconv;
@ -1896,6 +1898,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
if (strcmp(key, "GNU.sparse.size") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
}
/* GNU "0.1" sparse pax format. */
@ -1927,6 +1930,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
if (strcmp(key, "GNU.sparse.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
}
break;
case 'L':
@ -1979,6 +1983,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
tar->realsize_override = 1;
archive_entry_set_size(entry, tar->realsize);
} else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
pax_attribute_schily_xattr(entry, key, value,
@ -2057,14 +2062,12 @@ pax_attribute(struct archive_read *a, struct tar *tar,
tar->entry_bytes_remaining
= tar_atol10(value, strlen(value));
/*
* But, "size" is not necessarily the size of
* the file on disk; if this is a sparse file,
* the disk size may have already been set from
* GNU.sparse.realsize or GNU.sparse.size or
* an old GNU header field or SCHILY.realsize
* or ....
* The "size" pax header keyword always overrides the
* "size" field in the tar header.
* GNU.sparse.realsize, GNU.sparse.size and
* SCHILY.realsize override this value.
*/
if (tar->realsize < 0) {
if (!tar->realsize_override) {
archive_entry_set_size(entry,
tar->entry_bytes_remaining);
tar->realsize
@ -2208,6 +2211,7 @@ header_gnutar(struct archive_read *a, struct tar *tar,
tar->realsize
= tar_atol(header->realsize, sizeof(header->realsize));
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
}
if (header->sparse[0].offset[0] != 0) {

View File

@ -2407,7 +2407,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset)
* Examine Zip64 EOCD locator: If it's valid, store the information
* from it.
*/
static void
static int
read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
{
int64_t eocd64_offset;
@ -2417,35 +2417,37 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
/* Central dir must be on first volume. */
if (archive_le32dec(p + 4) != 0)
return;
return 0;
/* Must be only a single volume. */
if (archive_le32dec(p + 16) != 1)
return;
return 0;
/* Find the Zip64 EOCD record. */
eocd64_offset = archive_le64dec(p + 8);
if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0)
return;
return 0;
if ((p = __archive_read_ahead(a, 56, NULL)) == NULL)
return;
return 0;
/* Make sure we can read all of it. */
eocd64_size = archive_le64dec(p + 4) + 12;
if (eocd64_size < 56 || eocd64_size > 16384)
return;
return 0;
if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL)
return;
return 0;
/* Sanity-check the EOCD64 */
if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */
return;
return 0;
if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */
return;
return 0;
/* CD can't be split. */
if (archive_le64dec(p + 24) != archive_le64dec(p + 32))
return;
return 0;
/* Save the central directory offset for later use. */
zip->central_directory_offset = archive_le64dec(p + 48);
return 32;
}
static int
@ -2483,15 +2485,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
if (memcmp(p + i, "PK\005\006", 4) == 0) {
int ret = read_eocd(zip, p + i,
current_offset + i);
if (ret > 0) {
/* Zip64 EOCD locator precedes
* regular EOCD if present. */
if (i >= 20
&& memcmp(p + i - 20, "PK\006\007", 4) == 0) {
read_zip64_eocd(a, zip, p + i - 20);
}
return (ret);
/* Zip64 EOCD locator precedes
* regular EOCD if present. */
if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20);
if (ret_zip64 > ret)
ret = ret_zip64;
}
return (ret);
}
i -= 4;
break;

View File

@ -89,88 +89,6 @@ archive_version_string(void)
return (ARCHIVE_VERSION_STRING);
}
const char *
archive_version_details(void)
{
static struct archive_string str;
static int init = 0;
const char *zlib = archive_zlib_version();
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
if (zlib != NULL) {
archive_strcat(&str, " zlib/");
archive_strcat(&str, zlib);
}
if (liblzma) {
archive_strcat(&str, " liblzma/");
archive_strcat(&str, liblzma);
}
if (bzlib) {
const char *p = bzlib;
const char *sep = strchr(p, ',');
if (sep == NULL)
sep = p + strlen(p);
archive_strcat(&str, " bz2lib/");
archive_strncat(&str, p, sep - p);
}
if (liblz4) {
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
}
return str.s;
}
const char *
archive_zlib_version(void)
{
#ifdef HAVE_ZLIB_H
return ZLIB_VERSION;
#else
return NULL;
#endif
}
const char *
archive_liblzma_version(void)
{
#ifdef HAVE_LZMA_H
return LZMA_VERSION_STRING;
#else
return NULL;
#endif
}
const char *
archive_bzlib_version(void)
{
#ifdef HAVE_BZLIB_H
return BZ2_bzlibVersion();
#else
return NULL;
#endif
}
const char *
archive_liblz4_version(void)
{
#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
#define str(s) #s
#define NUMBER(x) str(x)
return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
#undef NUMBER
#undef str
#else
return NULL;
#endif
}
int
archive_errno(struct archive *a)
{

View File

@ -0,0 +1,133 @@
/*-
* Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#ifdef HAVE_LZMA_H
#include <lzma.h>
#endif
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
#endif
#ifdef HAVE_LZ4_H
#include <lz4.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_string.h"
const char *
archive_version_details(void)
{
static struct archive_string str;
static int init = 0;
const char *zlib = archive_zlib_version();
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
if (zlib != NULL) {
archive_strcat(&str, " zlib/");
archive_strcat(&str, zlib);
}
if (liblzma) {
archive_strcat(&str, " liblzma/");
archive_strcat(&str, liblzma);
}
if (bzlib) {
const char *p = bzlib;
const char *sep = strchr(p, ',');
if (sep == NULL)
sep = p + strlen(p);
archive_strcat(&str, " bz2lib/");
archive_strncat(&str, p, sep - p);
}
if (liblz4) {
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
}
return str.s;
}
const char *
archive_zlib_version(void)
{
#ifdef HAVE_ZLIB_H
return ZLIB_VERSION;
#else
return NULL;
#endif
}
const char *
archive_liblzma_version(void)
{
#ifdef HAVE_LZMA_H
return LZMA_VERSION_STRING;
#else
return NULL;
#endif
}
const char *
archive_bzlib_version(void)
{
#ifdef HAVE_BZLIB_H
return BZ2_bzlibVersion();
#else
return NULL;
#endif
}
const char *
archive_liblz4_version(void)
{
#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
#define str(s) #s
#define NUMBER(x) str(x)
return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
#undef NUMBER
#undef str
#else
return NULL;
#endif
}

View File

@ -1,697 +0,0 @@
/*-
* Copyright (c) 2003-2010 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_ACL_H
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
#if HAVE_DARWIN_ACL
#include <membership.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "archive.h"
#include "archive_entry.h"
#include "archive_acl_private.h"
#include "archive_write_disk_private.h"
#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
/* Default empty function body to satisfy mainline code. */
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl)
{
(void)a; /* UNUSED */
(void)fd; /* UNUSED */
(void)name; /* UNUSED */
(void)abstract_acl; /* UNUSED */
return (ARCHIVE_OK);
}
#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
#if HAVE_DARWIN_ACL
#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
#elif HAVE_FREEBSD_NFS4_ACL
#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
#endif
static int set_acl(struct archive *, int fd, const char *,
struct archive_acl *,
#if !HAVE_SUN_ACL
acl_type_t,
#endif
int archive_entry_acl_type, const char *tn);
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl)
{
int ret = ARCHIVE_OK;
#if !HAVE_DARWIN_ACL
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
#if HAVE_SUN_ACL
/* Solaris writes POSIX.1e access and default ACLs together */
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
#else /* HAVE_POSIX_ACL */
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
"access");
if (ret != ARCHIVE_OK)
return (ret);
}
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
ret = set_acl(a, fd, name, abstract_acl,
ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
"default");
#endif /* !HAVE_SUN_ACL */
/* Simultaneous POSIX.1e and NFSv4 is not supported */
return (ret);
}
#endif /* !HAVE_DARWIN_ACL */
#if HAVE_NFS4_ACL
if ((archive_acl_types(abstract_acl) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
#if !HAVE_SUN_ACL
ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
#endif
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
#endif /* HAVE_NFS4_ACL */
return (ret);
}
#if !HAVE_SUN_ACL || HAVE_SUN_NFS4_ACL
/*
* Translate system ACL permissions into libarchive internal structure
*/
static const struct {
const int archive_perm;
const int platform_perm;
} acl_perm_map[] = {
#if HAVE_SUN_NFS4_ACL /* Solaris NFSv4 ACL permissions */
{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
#if HAVE_DECL_ACL_SYNCHRONIZE
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
#else /* POSIX.1e ACL permissions */
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
#if HAVE_FREEBSD_NFS4_ACL /* FreeBSD NFSv4 ACL permissions */
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
#endif /* !HAVE_SUN_ACL || HAVE_SUN_NFS4_ACL */
#if HAVE_NFS4_ACL
/*
* Translate system NFSv4 inheritance flags into libarchive internal structure
*/
static const struct {
const int archive_inherit;
const int platform_inherit;
} acl_inherit_map[] = {
#if HAVE_SUN_NFS4_ACL /* Solaris NFSv4 inheritance flags */
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
#ifdef ACE_INHERITED_ACE
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
#endif
#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
#else /* FreeBSD NFSv4 ACL inheritance flags */
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
#endif /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */
};
#endif /* HAVE_NFS4_ACL */
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
#if !HAVE_SUN_ACL
acl_type_t acl_type,
#endif
int ae_requested_type, const char *tname)
{
#if HAVE_SUN_ACL
aclent_t *aclent;
#if HAVE_SUN_NFS4_ACL
ace_t *ace;
#endif
int cmd, e, r;
void *aclp;
#else
acl_t acl;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL
acl_flagset_t acl_flagset;
#endif
#endif /* HAVE_SUN_ACL */
#if HAVE_FREEBSD_NFS4_ACL
int r;
#endif
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
#if HAVE_DARWIN_ACL
uuid_t ae_uuid;
#endif
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
int entries;
int i;
ret = ARCHIVE_OK;
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
#if HAVE_SUN_ACL
switch (ae_requested_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
cmd = SETACL;
aclp = malloc(entries * sizeof(aclent_t));
break;
#if HAVE_SUN_NFS4_ACL
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
cmd = ACE_SETACL;
aclp = malloc(entries * sizeof(ace_t));
break;
#endif
default:
errno = ENOENT;
archive_set_error(a, errno, "Invalid ACL type");
return (ARCHIVE_FAILED);
}
if (aclp == NULL) {
archive_set_error(a, errno,
"Can't allocate memory for acl buffer");
return (ARCHIVE_FAILED);
}
#else /* !HAVE_SUN_ACL */
acl = acl_init(entries);
if (acl == (acl_t)NULL) {
archive_set_error(a, errno,
"Failed to initialize ACL working storage");
return (ARCHIVE_FAILED);
}
#endif /* !HAVE_SUN_ACL */
#if HAVE_SUN_ACL
e = 0;
#endif
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
#if HAVE_SUN_ACL
aclent = NULL;
#if HAVE_SUN_NFS4_ACL
ace = NULL;
#endif
if (cmd == SETACL) {
aclent = &((aclent_t *)aclp)[e];
aclent->a_id = -1;
aclent->a_type = 0;
aclent->a_perm = 0;
}
#if HAVE_SUN_NFS4_ACL
else { /* cmd == ACE_SETACL */
ace = &((ace_t *)aclp)[e];
ace->a_who = -1;
ace->a_access_mask = 0;
ace->a_flags = 0;
}
#endif /* HAVE_SUN_NFS4_ACL */
#else /* !HAVE_SUN_ACL */
#if HAVE_DARWIN_ACL
/*
* Mac OS doesn't support NFSv4 ACLs for
* owner@, group@ and everyone@.
* We skip any of these ACLs found.
*/
if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
continue;
#endif
if (acl_create_entry(&acl, &acl_entry) != 0) {
archive_set_error(a, errno,
"Failed to create a new ACL entry");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif /* !HAVE_SUN_ACL */
#if HAVE_DARWIN_ACL
switch (ae_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
break;
default:
/* We don't support any other types on MacOS */
continue;
}
#endif
switch (ae_tag) {
#if HAVE_SUN_ACL
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
if (aclent != NULL) {
aclent->a_id = ae_uid;
aclent->a_type |= USER;
}
#if HAVE_SUN_NFS4_ACL
else {
ace->a_who = ae_uid;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
if (aclent != NULL) {
aclent->a_id = ae_gid;
aclent->a_type |= GROUP;
}
#if HAVE_SUN_NFS4_ACL
else {
ace->a_who = ae_gid;
ace->a_flags |= ACE_IDENTIFIER_GROUP;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_USER_OBJ:
if (aclent != NULL)
aclent->a_type |= USER_OBJ;
#if HAVE_SUN_NFS4_ACL
else {
ace->a_flags |= ACE_OWNER;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
if (aclent != NULL)
aclent->a_type |= GROUP_OBJ;
#if HAVE_SUN_NFS4_ACL
else {
ace->a_flags |= ACE_GROUP;
ace->a_flags |= ACE_IDENTIFIER_GROUP;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_MASK:
if (aclent != NULL)
aclent->a_type |= CLASS_OBJ;
break;
case ARCHIVE_ENTRY_ACL_OTHER:
if (aclent != NULL)
aclent->a_type |= OTHER_OBJ;
break;
#if HAVE_SUN_NFS4_ACL
case ARCHIVE_ENTRY_ACL_EVERYONE:
if (ace != NULL)
ace->a_flags |= ACE_EVERYONE;
break;
#endif
#else /* !HAVE_SUN_ACL */
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
acl_set_tag_type(acl_entry, ACL_USER);
acl_set_qualifier(acl_entry, &ae_uid);
#else /* MacOS */
if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
sizeof(uid_t), ae_uuid) != 0)
continue;
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
continue;
#endif /* HAVE_DARWIN_ACL */
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
acl_set_tag_type(acl_entry, ACL_GROUP);
acl_set_qualifier(acl_entry, &ae_gid);
#else /* MacOS */
if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
sizeof(gid_t), ae_uuid) != 0)
continue;
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
continue;
#endif /* HAVE_DARWIN_ACL */
break;
#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
case ARCHIVE_ENTRY_ACL_USER_OBJ:
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
break;
case ARCHIVE_ENTRY_ACL_MASK:
acl_set_tag_type(acl_entry, ACL_MASK);
break;
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
#if HAVE_FREEBSD_NFS4_ACL /* FreeBSD only */
case ARCHIVE_ENTRY_ACL_EVERYONE:
acl_set_tag_type(acl_entry, ACL_EVERYONE);
break;
#endif
#endif /* !HAVE_DARWIN_ACL */
#endif /* !HAVE_SUN_ACL */
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unknown ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#if HAVE_FREEBSD_NFS4_ACL || HAVE_SUN_ACL
r = 0;
switch (ae_type) {
#if HAVE_SUN_ACL
#if HAVE_SUN_NFS4_ACL
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
if (ace != NULL)
ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
if (ace != NULL)
ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
if (ace != NULL)
ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
if (ace != NULL)
ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
else
r = -1;
break;
#endif
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
if (aclent == NULL)
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
if (aclent != NULL)
aclent->a_type |= ACL_DEFAULT;
else
r = -1;
break;
#else /* !HAVE_SUN_ACL */
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
break;
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
break;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
// These don't translate directly into the system ACL.
break;
#endif /* !HAVE_SUN_ACL */
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (r != 0) {
#if HAVE_SUN_ACL
errno = EINVAL;
#endif
archive_set_error(a, errno,
"Failed to set ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif /* HAVE_FREEBSD_NFS4_ACL || HAVE_SUN_ACL */
#if HAVE_SUN_ACL
if (aclent != NULL) {
if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
aclent->a_perm |= 1;
if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
aclent->a_perm |= 2;
if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
aclent->a_perm |= 4;
}
#if HAVE_SUN_NFS4_ACL
else /* falls through to for statement below, ace != NULL */
#endif
#else
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
archive_set_error(a, errno,
"Failed to get ACL permission set");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (acl_clear_perms(acl_permset) != 0) {
archive_set_error(a, errno,
"Failed to clear ACL permissions");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif /* !HAVE_SUN_ACL */
#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
if (ae_permset & acl_perm_map[i].archive_perm) {
#if HAVE_SUN_ACL
ace->a_access_mask |=
acl_perm_map[i].platform_perm;
#else
if (acl_add_perm(acl_permset,
acl_perm_map[i].platform_perm) != 0) {
archive_set_error(a, errno,
"Failed to add ACL permission");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif
}
}
#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
#if HAVE_NFS4_ACL
#if HAVE_SUN_NFS4_ACL
if (ace != NULL)
#elif HAVE_DARWIN_ACL
if (acl_type == ACL_TYPE_EXTENDED)
#else /* FreeBSD */
if (acl_type == ACL_TYPE_NFS4)
#endif
{
#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
/*
* acl_get_flagset_np() fails with non-NFSv4 ACLs
*/
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
archive_set_error(a, errno,
"Failed to get flagset from an NFSv4 ACL entry");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (acl_clear_flags_np(acl_flagset) != 0) {
archive_set_error(a, errno,
"Failed to clear flags from an NFSv4 ACL flagset");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
if (ae_permset & acl_inherit_map[i].archive_inherit) {
#if HAVE_SUN_ACL
ace->a_flags |=
acl_inherit_map[i].platform_inherit;
#else /* !HAVE_SUN_ACL */
if (acl_add_flag_np(acl_flagset,
acl_inherit_map[i].platform_inherit) != 0) {
archive_set_error(a, errno,
"Failed to add flag to NFSv4 ACL flagset");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif /* HAVE_SUN_ACL */
}
}
}
#endif /* HAVE_NFS4_ACL */
#if HAVE_SUN_ACL
e++;
#endif
}
#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
/* Try restoring the ACL through 'fd' if we can. */
#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
if (fd >= 0)
#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
#endif
{
#if HAVE_SUN_ACL
if (facl(fd, cmd, entries, aclp) == 0)
#elif HAVE_ACL_SET_FD_NP
if (acl_set_fd_np(fd, acl, acl_type) == 0)
#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
if (acl_set_fd(fd, acl) == 0)
#endif
ret = ARCHIVE_OK;
else {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno,
"Failed to set %s acl on fd", tname);
}
}
} else
#endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
#if HAVE_SUN_ACL
if (acl(name, cmd, entries, aclp) != 0)
#elif HAVE_ACL_SET_LINK_NP
if (acl_set_link_np(name, acl_type, acl) != 0)
#else
/* TODO: Skip this if 'name' is a symlink. */
if (acl_set_file(name, acl_type, acl) != 0)
#endif
{
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno, "Failed to set %s acl",
tname);
ret = ARCHIVE_WARN;
}
}
exit_free:
#if HAVE_SUN_ACL
free(aclp);
#else
acl_free(acl);
#endif
return (ret);
}
#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */

View File

@ -0,0 +1,321 @@
/*-
* Copyright (c) 2003-2010 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_SYS_ACL_H
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
#include "archive.h"
#include "archive_entry.h"
#include "archive_write_disk_private.h"
#include "archive_acl_maps.h"
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
int ae_requested_type, const char *tname)
{
int acl_type = 0;
acl_t acl;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
#if ARCHIVE_ACL_FREEBSD_NFS4
acl_flagset_t acl_flagset;
int r;
#endif
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
int perm_map_size;
const acl_perm_map_t *perm_map;
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
int entries;
int i;
ret = ARCHIVE_OK;
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
switch (ae_requested_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
acl_type = ACL_TYPE_ACCESS;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
acl_type = ACL_TYPE_DEFAULT;
break;
#if ARCHIVE_ACL_FREEBSD_NFS4
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
acl_type = ACL_TYPE_NFS4;
break;
#endif
default:
errno = ENOENT;
archive_set_error(a, errno, "Unsupported ACL type");
return (ARCHIVE_FAILED);
}
acl = acl_init(entries);
if (acl == (acl_t)NULL) {
archive_set_error(a, errno,
"Failed to initialize ACL working storage");
return (ARCHIVE_FAILED);
}
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
if (acl_create_entry(&acl, &acl_entry) != 0) {
archive_set_error(a, errno,
"Failed to create a new ACL entry");
ret = ARCHIVE_FAILED;
goto exit_free;
}
switch (ae_tag) {
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
acl_set_tag_type(acl_entry, ACL_USER);
acl_set_qualifier(acl_entry, &ae_uid);
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
acl_set_tag_type(acl_entry, ACL_GROUP);
acl_set_qualifier(acl_entry, &ae_gid);
break;
case ARCHIVE_ENTRY_ACL_USER_OBJ:
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
break;
case ARCHIVE_ENTRY_ACL_MASK:
acl_set_tag_type(acl_entry, ACL_MASK);
break;
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
#if ARCHIVE_ACL_FREEBSD_NFS4
case ARCHIVE_ENTRY_ACL_EVERYONE:
acl_set_tag_type(acl_entry, ACL_EVERYONE);
break;
#endif
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#if ARCHIVE_ACL_FREEBSD_NFS4
r = 0;
switch (ae_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
r = acl_set_entry_type_np(acl_entry,
ACL_ENTRY_TYPE_ALLOW);
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
r = acl_set_entry_type_np(acl_entry,
ACL_ENTRY_TYPE_DENY);
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
r = acl_set_entry_type_np(acl_entry,
ACL_ENTRY_TYPE_AUDIT);
break;
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
r = acl_set_entry_type_np(acl_entry,
ACL_ENTRY_TYPE_ALARM);
break;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
// These don't translate directly into the system ACL.
break;
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (r != 0) {
archive_set_error(a, errno,
"Failed to set ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
archive_set_error(a, errno,
"Failed to get ACL permission set");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (acl_clear_perms(acl_permset) != 0) {
archive_set_error(a, errno,
"Failed to clear ACL permissions");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#if ARCHIVE_ACL_FREEBSD_NFS4
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
perm_map_size = acl_nfs4_perm_map_size;
perm_map = acl_nfs4_perm_map;
} else {
#endif
perm_map_size = acl_posix_perm_map_size;
perm_map = acl_posix_perm_map;
#if ARCHIVE_ACL_FREEBSD_NFS4
}
#endif
for (i = 0; i < perm_map_size; ++i) {
if (ae_permset & perm_map[i].a_perm) {
if (acl_add_perm(acl_permset,
perm_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add ACL permission");
ret = ARCHIVE_FAILED;
goto exit_free;
}
}
}
#if ARCHIVE_ACL_FREEBSD_NFS4
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
/*
* acl_get_flagset_np() fails with non-NFSv4 ACLs
*/
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
archive_set_error(a, errno,
"Failed to get flagset from an NFSv4 "
"ACL entry");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (acl_clear_flags_np(acl_flagset) != 0) {
archive_set_error(a, errno,
"Failed to clear flags from an NFSv4 "
"ACL flagset");
ret = ARCHIVE_FAILED;
goto exit_free;
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
if (acl_add_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add flag to "
"NFSv4 ACL flagset");
ret = ARCHIVE_FAILED;
goto exit_free;
}
}
}
}
#endif
}
/* Try restoring the ACL through 'fd' if we can. */
if (fd >= 0) {
if (acl_set_fd_np(fd, acl, acl_type) == 0)
ret = ARCHIVE_OK;
else {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno,
"Failed to set acl on fd: %s", tname);
ret = ARCHIVE_WARN;
}
}
}
#if HAVE_ACL_SET_LINK_NP
else if (acl_set_link_np(name, acl_type, acl) != 0)
#else
/* FreeBSD older than 8.0 */
else if (acl_set_file(name, acl_type, acl) != 0)
#endif
{
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno, "Failed to set acl: %s",
tname);
ret = ARCHIVE_WARN;
}
}
exit_free:
acl_free(acl);
return (ret);
}
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode)
{
int ret = ARCHIVE_OK;
(void)mode; /* UNUSED */
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
if (ret != ARCHIVE_OK)
return (ret);
}
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
/* Simultaneous POSIX.1e and NFSv4 is not supported */
return (ret);
}
#if ARCHIVE_ACL_FREEBSD_NFS4
else if ((archive_acl_types(abstract_acl) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
#endif
return (ret);
}

View File

@ -575,10 +575,55 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
if (a->flags & ARCHIVE_EXTRACT_TIME)
a->todo |= TODO_TIMES;
if (a->flags & ARCHIVE_EXTRACT_ACL) {
#if ARCHIVE_ACL_DARWIN
/*
* On MacOS, platform ACLs get stored in mac_metadata, too.
* If we intend to extract mac_metadata and it is present
* we skip extracting libarchive NFSv4 ACLs.
*/
size_t metadata_size;
if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
archive_entry_mac_metadata(a->entry,
&metadata_size) == NULL || metadata_size == 0)
#endif
#if ARCHIVE_ACL_LIBRICHACL
/*
* RichACLs are stored in an extended attribute.
* If we intend to extract extended attributes and have this
* attribute we skip extracting libarchive NFSv4 ACLs.
*/
short extract_acls = 1;
if (a->flags & ARCHIVE_EXTRACT_XATTR && (
archive_entry_acl_types(a->entry) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4)) {
const char *attr_name;
const void *attr_value;
size_t attr_size;
int i = archive_entry_xattr_reset(a->entry);
while (i--) {
archive_entry_xattr_next(a->entry, &attr_name,
&attr_value, &attr_size);
if (attr_name != NULL && attr_value != NULL &&
attr_size > 0 && strcmp(attr_name,
"trusted.richacl") == 0) {
extract_acls = 0;
break;
}
}
}
if (extract_acls)
#endif
#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
{
#endif
if (archive_entry_filetype(a->entry) == AE_IFDIR)
a->deferred |= TODO_ACLS;
else
a->todo |= TODO_ACLS;
#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
}
#endif
}
if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
if (archive_entry_filetype(a->entry) == AE_IFDIR)
@ -1703,25 +1748,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
*/
if (a->todo & TODO_ACLS) {
int r2;
#ifdef HAVE_DARWIN_ACL
/*
* On Mac OS, platform ACLs are stored also in mac_metadata by
* the operating system. If mac_metadata is present it takes
* precedence and we skip extracting libarchive NFSv4 ACLs
*/
const void *metadata;
size_t metadata_size;
metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
if ((a->todo & TODO_MAC_METADATA) == 0 ||
metadata == NULL || metadata_size == 0) {
#endif
r2 = archive_write_disk_set_acls(&a->archive, a->fd,
archive_entry_pathname(a->entry),
archive_entry_acl(a->entry));
archive_entry_acl(a->entry),
archive_entry_mode(a->entry));
if (r2 < ret) ret = r2;
#ifdef HAVE_DARWIN_ACL
}
#endif
}
finish_metadata:
@ -2293,13 +2324,8 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MODE_BASE)
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
#ifdef HAVE_DARWIN_ACL
if ((p->fixup & TODO_MAC_METADATA) == 0 ||
p->mac_metadata == NULL ||
p->mac_metadata_size == 0)
#endif
archive_write_disk_set_acls(&a->archive,
-1, p->name, &p->acl);
archive_write_disk_set_acls(&a->archive, -1, p->name,
&p->acl, p->mode);
if (p->fixup & TODO_FFLAGS)
set_fflags_platform(a, -1, p->name,
p->mode, p->fflags_set, 0);
@ -4239,5 +4265,19 @@ older(struct stat *st, struct archive_entry *entry)
return (0);
}
#ifndef ARCHIVE_ACL_SUPPORT
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode)
{
(void)a; /* UNUSED */
(void)fd; /* UNUSED */
(void)name; /* UNUSED */
(void)abstract_acl; /* UNUSED */
(void)mode; /* UNUSED */
return (ARCHIVE_OK);
}
#endif
#endif /* !_WIN32 || __CYGWIN__ */

View File

@ -33,11 +33,13 @@
#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
#include "archive_platform_acl.h"
#include "archive_acl_private.h"
#include "archive_entry.h"
struct archive_write_disk;
int
archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *);
int archive_write_disk_set_acls(struct archive *, int, const char *,
struct archive_acl *, __LA_MODE_T);
#endif

View File

@ -26,15 +26,18 @@
#include "test.h"
__FBSDID("$FreeBSD$");
#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
#if ARCHIVE_ACL_NFS4
#if HAVE_SYS_ACL_H
#define _ACL_PRIVATE
#include <sys/acl.h>
#if HAVE_DARWIN_ACL
#endif
#if HAVE_SYS_RICHACL_H
#include <sys/richacl.h>
#endif
#if HAVE_MEMBERSHIP_H
#include <membership.h>
#endif
#endif
#if HAVE_NFS4_ACL
struct myacl_t {
int type;
int permset;
@ -44,7 +47,7 @@ struct myacl_t {
};
static struct myacl_t acls_reg[] = {
#if !HAVE_DARWIN_ACL
#if !ARCHIVE_ACL_DARWIN
/* For this test, we need the file owner to be able to read and write the ACL. */
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL | ARCHIVE_ENTRY_ACL_WRITE_ACL | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
@ -91,7 +94,7 @@ static struct myacl_t acls_reg[] = {
// ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
#if !HAVE_DARWIN_ACL
#if !ARCHIVE_ACL_DARWIN
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
@ -134,7 +137,7 @@ static const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0]));
static struct myacl_t acls_dir[] = {
/* For this test, we need to be able to read and write the ACL. */
#if !HAVE_DARWIN_ACL
#if !ARCHIVE_ACL_DARWIN
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
#endif
@ -180,13 +183,17 @@ static struct myacl_t acls_dir[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
#if 0
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
#if !defined(ARCHIVE_ACL_SUNOS_NFS4) || defined(ACE_INHERITED_ACE)
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
ARCHIVE_ENTRY_ACL_USER, 305, "user305" },
@ -207,7 +214,7 @@ static struct myacl_t acls_dir[] = {
ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
#if !HAVE_DARWIN_ACL
#if !ARCHIVE_ACL_DARWIN
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
@ -254,7 +261,7 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
int i;
archive_entry_acl_clear(ae);
#if !HAVE_DARWIN_ACL
#if !ARCHIVE_ACL_DARWIN
if (start > 0) {
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_add_entry(ae,
@ -271,78 +278,96 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
}
static int
#ifdef HAVE_SUN_NFS4_ACL
acl_permset_to_bitmap(uint32_t a_access_mask)
#if ARCHIVE_ACL_SUNOS_NFS4
acl_permset_to_bitmap(uint32_t mask)
#elif ARCHIVE_ACL_LIBRICHACL
acl_permset_to_bitmap(unsigned int mask)
#else
acl_permset_to_bitmap(acl_permset_t opaque_ps)
#endif
{
static struct { int machine; int portable; } perms[] = {
#ifdef HAVE_SUN_NFS4_ACL /* Solaris NFSv4 ACL permissions */
{ACE_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
{ACE_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
{ACE_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
{ACE_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
{ACE_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
{ACE_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
{ACE_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
{ACE_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
{ACE_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
{ACE_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
{ACE_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
{ACE_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
{ACE_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
{ACE_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
{ACE_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
{ACE_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
{ACE_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
#elif HAVE_DARWIN_ACL /* MacOS NFSv4 ACL permissions */
{ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
{ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
{ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
{ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
{ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
{ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
{ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
{ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
{ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
{ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
{ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
{ACL_READ_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
{ACL_WRITE_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
{ACL_READ_SECURITY, ARCHIVE_ENTRY_ACL_READ_ACL},
{ACL_WRITE_SECURITY, ARCHIVE_ENTRY_ACL_WRITE_ACL},
{ACL_CHANGE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
static struct { int portable; int machine; } perms[] = {
#ifdef ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL permissions */
{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
#elif ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL permissions */
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
#if HAVE_DECL_ACL_SYNCHRONIZE
{ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
#elif ARCHIVE_ACL_LIBRICHACL
{ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
{ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
#else /* FreeBSD NFSv4 ACL permissions */
{ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
{ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
{ACL_READ, ARCHIVE_ENTRY_ACL_READ},
{ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
{ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
{ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
{ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
{ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
{ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
{ACL_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
{ACL_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
{ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
{ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
{ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
{ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
{ACL_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
{ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
{ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
{ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
};
int i, permset = 0;
for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
#if HAVE_SUN_NFS4_ACL
if (a_access_mask & perms[i].machine)
#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
if (mask & perms[i].machine)
#else
if (acl_get_perm_np(opaque_ps, perms[i].machine))
#endif
@ -351,90 +376,70 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps)
}
static int
#if HAVE_SUN_NFS4_ACL
acl_flagset_to_bitmap(uint16_t a_flags)
#if ARCHIVE_ACL_SUNOS_NFS4
acl_flagset_to_bitmap(uint16_t flags)
#elif ARCHIVE_ACL_LIBRICHACL
acl_flagset_to_bitmap(int flags)
#else
acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
#endif
{
static struct { int machine; int portable; } flags[] = {
#if HAVE_SUN_NFS4_ACL /* Solaris NFSv4 ACL inheritance flags */
{ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
{ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
{ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
{ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
{ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
static struct { int portable; int machine; } perms[] = {
#if ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL inheritance flags */
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
#ifdef ACE_INHERITED_ACE
{ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
#endif
#elif HAVE_DARWIN_ACL /* MacOS NFSv4 ACL inheritance flags */
{ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED},
{ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
{ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
{ACL_ENTRY_LIMIT_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ACL_ENTRY_ONLY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY}
#elif ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL inheritance flags */
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
#elif ARCHIVE_ACL_LIBRICHACL
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
#else /* FreeBSD NFSv4 ACL inheritance flags */
{ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
{ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
{ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
{ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
{ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
#endif
};
int i, flagset = 0;
for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
#if HAVE_SUN_NFS4_ACL
if (a_flags & flags[i].machine)
for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
if (flags & perms[i].machine)
#else
if (acl_get_flag_np(opaque_fs, flags[i].machine))
if (acl_get_flag_np(opaque_fs, perms[i].machine))
#endif
flagset |= flags[i].portable;
flagset |= perms[i].portable;
return flagset;
}
#if ARCHIVE_ACL_SUNOS_NFS4
static int
#if HAVE_SUN_NFS4_ACL
acl_match(ace_t *ace, struct myacl_t *myacl)
#else
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
#endif
{
#if !HAVE_SUN_NFS4_ACL
#if HAVE_DARWIN_ACL
void *q;
uid_t ugid;
int r, idtype;
#else
gid_t g, *gp;
uid_t u, *up;
acl_entry_type_t entry_type;
#endif /* !HAVE_DARWIN_ACL */
acl_tag_t tag_type;
acl_permset_t opaque_ps;
acl_flagset_t opaque_fs;
#endif /* !HAVE_SUN_NFS4_ACL */
int perms;
#if HAVE_SUN_NFS4_ACL
perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
#else
acl_get_tag_type(aclent, &tag_type);
#if !HAVE_DARWIN_ACL
acl_get_entry_type_np(aclent, &entry_type);
#endif
/* translate the silly opaque permset to a bitmap */
acl_get_permset(aclent, &opaque_ps);
acl_get_flagset_np(aclent, &opaque_fs);
perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
#endif
if (perms != myacl->permset)
return (0);
#if HAVE_SUN_NFS4_ACL
switch (ace->a_type) {
case ACE_ACCESS_ALLOWED_ACE_TYPE:
if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
@ -476,7 +481,85 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
if ((uid_t)myacl->qual != ace->a_who)
return (0);
}
#elif HAVE_DARWIN_ACL
return (1);
}
#elif ARCHIVE_ACL_LIBRICHACL
static int
acl_match(struct richace *richace, struct myacl_t *myacl)
{
int perms;
perms = acl_permset_to_bitmap(richace->e_mask) |
acl_flagset_to_bitmap(richace->e_flags);
if (perms != myacl->permset)
return (0);
switch (richace->e_type) {
case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
return (0);
break;
case RICHACE_ACCESS_DENIED_ACE_TYPE:
if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
return (0);
break;
default:
return (0);
}
if (richace->e_flags & RICHACE_SPECIAL_WHO) {
switch (richace->e_id) {
case RICHACE_OWNER_SPECIAL_ID:
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
return (0);
break;
case RICHACE_GROUP_SPECIAL_ID:
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
return (0);
break;
case RICHACE_EVERYONE_SPECIAL_ID:
if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
return (0);
break;
default:
/* Invalid e_id */
return (0);
}
} else if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
return (0);
if ((gid_t)myacl->qual != richace->e_id)
return (0);
} else {
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
return (0);
if ((uid_t)myacl->qual != richace->e_id)
return (0);
}
return (1);
}
#elif ARCHIVE_ACL_DARWIN
static int
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
{
void *q;
uid_t ugid;
int r, idtype;
acl_tag_t tag_type;
acl_permset_t opaque_ps;
acl_flagset_t opaque_fs;
int perms;
acl_get_tag_type(aclent, &tag_type);
/* translate the silly opaque permset to a bitmap */
acl_get_permset(aclent, &opaque_ps);
acl_get_flagset_np(aclent, &opaque_fs);
perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
if (perms != myacl->permset)
return (0);
r = 0;
switch (tag_type) {
case ACL_EXTENDED_ALLOW:
@ -513,7 +596,30 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
default:
return (0);
}
#else /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */
return (1);
}
#else /* ARCHIVE_ACL_FREEBSD_NFS4 */
static int
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
{
gid_t g, *gp;
uid_t u, *up;
acl_entry_type_t entry_type;
acl_tag_t tag_type;
acl_permset_t opaque_ps;
acl_flagset_t opaque_fs;
int perms;
acl_get_tag_type(aclent, &tag_type);
acl_get_entry_type_np(aclent, &entry_type);
/* translate the silly opaque permset to a bitmap */
acl_get_permset(aclent, &opaque_ps);
acl_get_flagset_np(aclent, &opaque_fs);
perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
if (perms != myacl->permset)
return (0);
switch (entry_type) {
case ACL_ENTRY_TYPE_ALLOW:
if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
@ -565,15 +671,17 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
break;
}
#endif /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */
return (1);
}
#endif /* various ARCHIVE_ACL_NFS4 implementations */
static void
compare_acls(
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
void *aclp,
int aclcnt,
#elif ARCHIVE_ACL_LIBRICHACL
struct richacl *richacl,
#else
acl_t acl,
#endif
@ -582,19 +690,40 @@ compare_acls(
int *marker;
int matched;
int i, n;
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
int e;
ace_t *acl_entry;
#elif ARCHIVE_ACL_LIBRICHACL
int e;
struct richace *acl_entry;
int aclcnt;
#else
int entry_id = ACL_FIRST_ENTRY;
acl_entry_t acl_entry;
#if ARCHIVE_ACL_DARWIN
const int acl_get_entry_ret = 0;
#else
const int acl_get_entry_ret = 1;
#endif
#endif
#if ARCHIVE_ACL_SUNOS_NFS4
if (aclp == NULL)
return;
#elif ARCHIVE_ACL_LIBRICHACL
if (richacl == NULL)
return;
aclcnt = richacl->a_count;
#else
if (acl == NULL)
return;
#endif
n = end - start;
marker = malloc(sizeof(marker[0]) * (n + 1));
for (i = 0; i < n; i++)
marker[i] = i + start;
#if !HAVE_DARWIN_ACL
#if !ARCHIVE_ACL_DARWIN
/* Always include the first ACE. */
if (start > 0) {
marker[n] = 0;
@ -606,16 +735,16 @@ compare_acls(
* Iterate over acls in system acl object, try to match each
* one with an item in the myacls array.
*/
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
for (e = 0; e < aclcnt; e++)
#elif HAVE_DARWIN_ACL
while (0 == acl_get_entry(acl, entry_id, &acl_entry))
#else
while (1 == acl_get_entry(acl, entry_id, &acl_entry))
while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry))
#endif
{
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
acl_entry = &((ace_t *)aclp)[e];
#elif ARCHIVE_ACL_LIBRICHACL
acl_entry = &(richacl->a_entries[e]);
#else
/* After the first time... */
entry_id = ACL_NEXT_ENTRY;
@ -708,7 +837,7 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
}
free(marker);
}
#endif /* HAVE_NFS4_ACL */
#endif /* ARCHIVE_ACL_NFS4 */
/*
* Verify ACL restore-to-disk. This test is Platform-specific.
@ -716,25 +845,27 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
DEFINE_TEST(test_acl_platform_nfs4)
{
#if !HAVE_NFS4_ACL
#if !ARCHIVE_ACL_NFS4
skipping("NFS4 ACLs are not supported on this platform");
#else
#else /* ARCHIVE_ACL_NFS4 */
char buff[64];
int i;
struct stat st;
struct archive *a;
struct archive_entry *ae;
#if HAVE_DARWIN_ACL /* On MacOS we skip trivial ACLs in some tests */
#if ARCHIVE_ACL_DARWIN /* On MacOS we skip trivial ACLs in some tests */
const int regcnt = acls_reg_cnt - 4;
const int dircnt = acls_dir_cnt - 4;
#else
const int regcnt = acls_reg_cnt;
const int dircnt = acls_dir_cnt;
#endif
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
void *aclp;
int aclcnt;
#else /* !HAVE_SUN_NFS4_ACL */
#elif ARCHIVE_ACL_LIBRICHACL
struct richacl *richacl;
#else /* !ARCHIVE_ACL_SUNOS_NFS4 */
acl_t acl;
#endif
@ -790,23 +921,33 @@ DEFINE_TEST(test_acl_platform_nfs4)
/* Verify the data on disk. */
assertEqualInt(0, stat("testall", &st));
assertEqualInt(st.st_mtime, 123456);
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
failure("acl(): errno = %d (%s)", errno, strerror(errno));
failure("acl(\"%s\"): errno = %d (%s)", "testall", errno,
strerror(errno));
assert(aclp != NULL);
#elif ARCHIVE_ACL_LIBRICHACL
richacl = richacl_get_file("testall");
failure("richacl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
strerror(errno));
assert(richacl != NULL);
#else
#if HAVE_DARWIN_ACL
#if ARCHIVE_ACL_DARWIN
acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
#else
acl = acl_get_file("testall", ACL_TYPE_NFS4);
#endif
failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
failure("acl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
strerror(errno));
assert(acl != (acl_t)NULL);
#endif
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt);
free(aclp);
aclp = NULL;
#elif ARCHIVE_ACL_LIBRICHACL
compare_acls(richacl, acls_reg, "testall", 0, regcnt);
richacl_free(richacl);
#else
compare_acls(acl, acls_reg, "testall", 0, regcnt);
acl_free(acl);
@ -818,24 +959,37 @@ DEFINE_TEST(test_acl_platform_nfs4)
sprintf(buff, "dir%d", i);
assertEqualInt(0, stat(buff, &st));
assertEqualInt(st.st_mtime, 123456 + i);
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
failure("acl(): errno = %d (%s)", errno, strerror(errno));
failure("acl(\"%s\"): errno = %d (%s)", buff, errno,
strerror(errno));
assert(aclp != NULL);
#elif ARCHIVE_ACL_LIBRICHACL
richacl = richacl_get_file(buff);
/* First and last two dir do not return a richacl */
if ((i == 0 || i >= dircnt - 2) && richacl == NULL &&
errno == ENODATA)
continue;
failure("richacl_get_file(\"%s\"): errno = %d (%s)", buff,
errno, strerror(errno));
assert(richacl != NULL);
#else
#if HAVE_DARWIN_ACL
#if ARCHIVE_ACL_DARWIN
acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
#else
acl = acl_get_file(buff, ACL_TYPE_NFS4);
#endif
failure("acl_get_file(): errno = %d (%s)", errno,
failure("acl_get_file(\"%s\"): errno = %d (%s)", buff, errno,
strerror(errno));
assert(acl != (acl_t)NULL);
#endif
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1);
free(aclp);
aclp = NULL;
#elif ARCHIVE_ACL_LIBRICHACL
compare_acls(richacl, acls_dir, buff, i, i + 1);
richacl_free(richacl);
#else
compare_acls(acl, acls_dir, buff, i, i + 1);
acl_free(acl);
@ -845,23 +999,33 @@ DEFINE_TEST(test_acl_platform_nfs4)
/* Verify "dirall" on disk. */
assertEqualInt(0, stat("dirall", &st));
assertEqualInt(st.st_mtime, 123456);
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
failure("acl(): errno = %d (%s)", errno, strerror(errno));
failure("acl(\"%s\"): errno = %d (%s)", "dirall", errno,
strerror(errno));
assert(aclp != NULL);
#elif ARCHIVE_ACL_LIBRICHACL
richacl = richacl_get_file("dirall");
failure("richacl_get_file(\"%s\"): errno = %d (%s)", "dirall",
errno, strerror(errno));
assert(richacl != NULL);
#else
#if HAVE_DARWIN_ACL
#if ARCHIVE_ACL_DARWIN
acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
#else
acl = acl_get_file("dirall", ACL_TYPE_NFS4);
#endif
failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
failure("acl_get_file(\"%s\"): errno = %d (%s)", "dirall", errno,
strerror(errno));
assert(acl != (acl_t)NULL);
#endif
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt);
free(aclp);
aclp = NULL;
#elif ARCHIVE_ACL_LIBRICHACL
compare_acls(richacl, acls_dir, "dirall", 0, dircnt);
richacl_free(richacl);
#else
compare_acls(acl, acls_dir, "dirall", 0, dircnt);
acl_free(acl);
@ -890,5 +1054,5 @@ DEFINE_TEST(test_acl_platform_nfs4)
compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt);
archive_entry_free(ae);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
#endif /* HAVE_NFS4_ACL */
#endif /* ARCHIVE_ACL_NFS4 */
}

View File

@ -26,7 +26,7 @@
#include "test.h"
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $");
#if HAVE_POSIX_ACL || HAVE_SUN_ACL
#if ARCHIVE_ACL_POSIX1E
#include <sys/acl.h>
#if HAVE_ACL_GET_PERM
#include <acl/libacl.h>
@ -55,18 +55,18 @@ static struct archive_test_acl_t acls2[] = {
};
static int
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
acl_entry_get_perm(aclent_t *aclent)
#else
acl_entry_get_perm(acl_entry_t aclent)
#endif
{
int permset = 0;
#if HAVE_POSIX_ACL
#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
acl_permset_t opaque_ps;
#endif
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
if (aclent->a_perm & 1)
permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
if (aclent->a_perm & 2)
@ -127,114 +127,108 @@ acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_ta
}
#endif
#if ARCHIVE_ACL_SUNOS
static int
#if HAVE_SUN_ACL
acl_match(aclent_t *aclent, struct archive_test_acl_t *myacl)
#else
acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
#endif
{
#if HAVE_POSIX_ACL
gid_t g, *gp;
uid_t u, *up;
acl_tag_t tag_type;
#endif
if (myacl->permset != acl_entry_get_perm(aclent))
return (0);
#if HAVE_SUN_ACL
switch (aclent->a_type)
#else
acl_get_tag_type(aclent, &tag_type);
switch (tag_type)
#endif
{
#if HAVE_SUN_ACL
switch (aclent->a_type) {
case DEF_USER_OBJ:
case USER_OBJ:
#else
case ACL_USER_OBJ:
#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
break;
#if HAVE_SUN_ACL
case DEF_USER:
case USER:
#else
case ACL_USER:
#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
return (0);
#if HAVE_SUN_ACL
if ((uid_t)myacl->qual != aclent->a_id)
return (0);
#else
up = acl_get_qualifier(aclent);
u = *up;
acl_free(up);
if ((uid_t)myacl->qual != u)
return (0);
#endif
break;
#if HAVE_SUN_ACL
case DEF_GROUP_OBJ:
case GROUP_OBJ:
#else
case ACL_GROUP_OBJ:
#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
break;
#if HAVE_SUN_ACL
case DEF_GROUP:
case GROUP:
#else
case ACL_GROUP:
#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
return (0);
#if HAVE_SUN_ACL
if ((gid_t)myacl->qual != aclent->a_id)
return (0);
#else
gp = acl_get_qualifier(aclent);
g = *gp;
acl_free(gp);
if ((gid_t)myacl->qual != g)
return (0);
#endif
break;
#if HAVE_SUN_ACL
case DEF_CLASS_OBJ:
case CLASS_OBJ:
#else
case ACL_MASK:
#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
break;
#if HAVE_SUN_ACL
case DEF_OTHER_OBJ:
case OTHER_OBJ:
#else
case ACL_OTHER:
#endif
if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
break;
}
return (1);
}
static void
#if HAVE_SUN_ACL
compare_acls(void *aclp, int aclcnt, struct archive_test_acl_t *myacls, int n)
#else
compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
#else /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */
static int
acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
{
gid_t g, *gp;
uid_t u, *up;
acl_tag_t tag_type;
if (myacl->permset != acl_entry_get_perm(aclent))
return (0);
acl_get_tag_type(aclent, &tag_type);
switch (tag_type) {
case ACL_USER_OBJ:
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
break;
case ACL_USER:
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
return (0);
up = acl_get_qualifier(aclent);
u = *up;
acl_free(up);
if ((uid_t)myacl->qual != u)
return (0);
break;
case ACL_GROUP_OBJ:
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
break;
case ACL_GROUP:
if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
return (0);
gp = acl_get_qualifier(aclent);
g = *gp;
acl_free(gp);
if ((gid_t)myacl->qual != g)
return (0);
break;
case ACL_MASK:
if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
break;
case ACL_OTHER:
if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
break;
}
return (1);
}
#endif
static void
compare_acls(
#if ARCHIVE_ACL_SUNOS
void *aclp, int aclcnt,
#else
acl_t acl,
#endif
struct archive_test_acl_t *myacls, int n)
{
int *marker;
int matched;
int i;
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
int e;
aclent_t *acl_entry;
#else
@ -253,7 +247,7 @@ compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
* Iterate over acls in system acl object, try to match each
* one with an item in the myacls array.
*/
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
for(e = 0; e < aclcnt; e++) {
acl_entry = &((aclent_t *)aclp)[e];
#else
@ -288,23 +282,21 @@ compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
}
free(marker);
}
#endif
/*
* Verify ACL restore-to-disk. This test is Platform-specific.
*/
DEFINE_TEST(test_acl_platform_posix1e_restore)
{
#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
#if !ARCHIVE_ACL_POSIX1E
skipping("POSIX.1e ACLs are not supported on this platform");
#else /* HAVE_SUN_ACL || HAVE_POSIX_ACL */
#else /* ARCHIVE_ACL_POSIX1E */
struct stat st;
struct archive *a;
struct archive_entry *ae;
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
void *aclp;
int aclcnt;
#else
@ -340,7 +332,7 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
/* Verify the data on disk. */
assertEqualInt(0, stat("test0", &st));
assertEqualInt(st.st_mtime, 123456);
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
aclp = sunacl_get(GETACL, &aclcnt, 0, "test0");
failure("acl(): errno = %d (%s)", errno, strerror(errno));
assert(aclp != NULL);
@ -349,7 +341,7 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
assert(acl != (acl_t)NULL);
#endif
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
compare_acls(aclp, aclcnt, acls2, sizeof(acls2)/sizeof(acls2[0]));
free(aclp);
aclp = NULL;
@ -358,7 +350,7 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
acl_free(acl);
#endif
#endif /* HAVE_SUN_ACL || HAVE_POSIX_ACL */
#endif /* ARCHIVE_ACL_POSIX1E */
}
/*
@ -366,15 +358,15 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
*/
DEFINE_TEST(test_acl_platform_posix1e_read)
{
#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
#if !ARCHIVE_ACL_POSIX1E
skipping("POSIX.1e ACLs are not supported on this platform");
#else
#else /* ARCHIVE_ACL_POSIX1E */
struct archive *a;
struct archive_entry *ae;
int n, fd, flags, dflags;
char *func, *acl_text;
const char *acl1_text, *acl2_text, *acl3_text;
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
void *aclp;
int aclcnt;
#else
@ -388,7 +380,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
*/
/* Create a test file f1 with acl1 */
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
acl1_text = "user::rwx,"
"group::rwx,"
"other:rwx,"
@ -417,12 +409,12 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
failure("Could not create test file?!");
if (!assert(fd >= 0)) {
#if !HAVE_SUN_ACL
#if !ARCHIVE_ACL_SUNOS
acl_free(acl1);
#endif
return;
}
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
/* Check if Solaris filesystem supports POSIX.1e ACLs */
aclp = sunacl_get(GETACL, &aclcnt, fd, NULL);
if (aclp == 0)
@ -440,12 +432,12 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
func = "acl_set_fd()";
n = acl_set_fd(fd, acl1);
#endif
#if !HAVE_SUN_ACL
#if !ARCHIVE_ACL_SUNOS
acl_free(acl1);
#endif
if (n != 0) {
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
if (errno == ENOSYS || errno == ENOTSUP)
#else
if (errno == EOPNOTSUPP || errno == EINVAL)
@ -474,7 +466,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
* to read ACLs, resulting in reading the ACL from a like-named
* file in the wrong directory.
*/
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
acl2_text = "user::rwx,"
"group::rwx,"
"other:---,"
@ -503,12 +495,12 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
failure("Could not create test file?!");
if (!assert(fd >= 0)) {
#if !HAVE_SUN_ACL
#if !ARCHIVE_ACL_SUNOS
acl_free(acl2);
#endif
return;
}
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
func = "facl()";
n = facl(fd, SETACL, (int)(sizeof(aclp2) / sizeof(aclp2[0])), aclp2);
#else
@ -525,7 +517,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
/* Create nested directory d2 with default ACLs */
assertMakeDir("d/d2", 0755);
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
acl3_text = "user::rwx,"
"group::r-x,"
"other:r-x,"
@ -564,7 +556,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
assert((void *)acl3 != NULL);
#endif
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
func = "acl()";
n = acl("d/d2", SETACL, (int)(sizeof(aclp3) / sizeof(aclp3[0])), aclp3);
#else
@ -580,7 +572,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
assert(NULL != (ae = archive_entry_new()));
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E
| ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
| ARCHIVE_ENTRY_ACL_STYLE_SOLARIS;
@ -610,5 +602,5 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
archive_entry_free(ae);
assertEqualInt(ARCHIVE_OK, archive_free(a));
#endif
#endif /* ARCHIVE_ACL_POSIX1E */
}

View File

@ -640,7 +640,7 @@ This option suppresses these behaviors.
(x mode only)
Preserve file permissions.
Attempt to restore the full permissions, including owner, file modes, ACLs,
extended atributes and extended file flags, if available, for each item
extended attributes and extended file flags, if available, for each item
extracted from the archive. This is te reverse of
.Fl Fl no-same-permissions
and the default if

View File

@ -73,8 +73,6 @@ static const acl_perm_t acl_perms[] = {
#if HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL
static const acl_flag_t acl_flags[] = {
#if HAVE_DARWIN_ACL
ACL_FLAG_DEFER_INHERIT,
ACL_FLAG_NO_INHERIT,
ACL_ENTRY_INHERITED,
ACL_ENTRY_FILE_INHERIT,
ACL_ENTRY_DIRECTORY_INHERIT,

View File

@ -127,43 +127,11 @@
#define O_BINARY 0
#endif
/*
* If this platform has <sys/acl.h>, acl_create(), acl_init(),
* acl_set_file(), and ACL_USER, we assume it has the rest of the
* POSIX.1e draft functions used in archive_read_extract.c.
*/
#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
#if HAVE_DECL_ACL_USER
#define HAVE_POSIX_ACL 1
#elif HAVE_DECL_ACL_TYPE_EXTENDED
#define HAVE_DARWIN_ACL 1
#endif
#if HAVE_DECL_ACL_TYPE_NFS4
#define HAVE_FREEBSD_NFS4_ACL 1
#endif
#endif
/*
* If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
* facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
*/
#if HAVE_SYS_ACL_H && HAVE_ACL && HAVE_FACL && HAVE_ACLENT_T && \
HAVE_DECL_GETACL && HAVE_DECL_GETACLCNT && HAVE_DECL_SETACL
#define HAVE_SUN_ACL 1
#if HAVE_ACE_T && HAVE_DECL_ACE_GETACL && HAVE_DECL_ACE_GETACLCNT && \
HAVE_DECL_ACE_SETACL
#define HAVE_SUN_NFS4_ACL 1
#endif
#endif
/* Define if platform supports NFSv4 ACLs */
#if HAVE_FREEBSD_NFS4_ACL || HAVE_SUN_NFS4_ACL || HAVE_DARWIN_ACL
#define HAVE_NFS4_ACL 1
#endif
#include "archive_platform_acl.h"
#define ARCHIVE_TEST_ACL_TYPE_POSIX1E 1
#define ARCHIVE_TEST_ACL_TYPE_NFS4 2
/*
* Redefine DEFINE_TEST for use in defining the test functions.
*/
@ -378,7 +346,7 @@ int setTestAcl(const char *path);
/* Return true if the file has large i-node number(>0xffffffff). */
int is_LargeInode(const char *);
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
/* Fetch ACLs on Solaris using acl() or facl() */
void *sunacl_get(int cmd, int *aclcnt, int fd, const char *path);
#endif

View File

@ -56,7 +56,8 @@
#include <stdarg.h>
#include <time.h>
/* ACL support */
#ifdef HAVE_SIGNAL_H
#endif
#ifdef HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
@ -66,7 +67,10 @@
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
#if HAVE_DARWIN_ACL
#ifdef HAVE_SYS_RICHACL_H
#include <sys/richacl.h>
#endif
#if HAVE_MEMBERSHIP_H
#include <membership.h>
#endif
@ -2436,7 +2440,7 @@ canNodump(void)
return (0);
}
#if HAVE_SUN_ACL
#if ARCHIVE_ACL_SUNOS
/* Fetch ACLs on Solaris using acl() or facl() */
void *
sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
@ -2449,7 +2453,7 @@ sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
cntcmd = GETACLCNT;
size = sizeof(aclent_t);
}
#if HAVE_SUN_NFS4_ACL
#if ARCHIVE_ACL_SUNOS_NFS4
else if (cmd == ACE_GETACL) {
cntcmd = ACE_GETACLCNT;
size = sizeof(ace_t);
@ -2492,7 +2496,7 @@ sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
*aclcnt = cnt;
return (aclp);
}
#endif /* HAVE_SUN_ACL */
#endif /* ARCHIVE_ACL_SUNOS */
/*
* Set test ACLs on a path
@ -2504,19 +2508,22 @@ sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
int
setTestAcl(const char *path)
{
#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
#if ARCHIVE_ACL_SUPPORT
int r = 1;
#if !HAVE_SUN_ACL
#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN
acl_t acl;
#endif
#if HAVE_POSIX_ACL /* Linux, FreeBSD POSIX.1e */
#if ARCHIVE_ACL_LIBRICHACL
struct richacl *richacl;
#endif
#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD
const char *acltext_posix1e = "user:1:rw-,"
"group:15:r-x,"
"user::rwx,"
"group::rwx,"
"other::r-x,"
"mask::rwx";
#elif HAVE_SUN_ACL /* Solaris POSIX.1e */
#elif ARCHIVE_ACL_SUNOS /* Solaris POSIX.1e */
aclent_t aclp_posix1e[] = {
{ USER_OBJ, -1, 4 | 2 | 1 },
{ USER, 1, 4 | 2 },
@ -2526,13 +2533,22 @@ setTestAcl(const char *path)
{ OTHER_OBJ, -1, 4 | 2 | 1 }
};
#endif
#if HAVE_FREEBSD_NFS4_ACL /* FreeBSD NFS4 */
#if ARCHIVE_ACL_FREEBSD /* FreeBSD NFS4 */
const char *acltext_nfs4 = "user:1:rwpaRcs::allow:1,"
"group:15:rxaRcs::allow:15,"
"owner@:rwpxaARWcCos::allow,"
"group@:rwpxaRcs::allow,"
"everyone@:rxaRcs::allow";
#elif HAVE_SUN_NFS4_ACL /* Solaris NFS4 */
#elif ARCHIVE_ACL_LIBRICHACL
const char *acltext_nfs4 = "owner:rwpxaARWcCoS::mask,"
"group:rwpxaRcS::mask,"
"other:rxaRcS::mask,"
"user:1:rwpaRcS::allow,"
"group:15:rxaRcS::allow,"
"owner@:rwpxaARWcCoS::allow,"
"group@:rwpxaRcS::allow,"
"everyone@:rxaRcS::allow";
#elif ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFS4 */
ace_t aclp_nfs4[] = {
{ 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL |
@ -2553,7 +2569,7 @@ setTestAcl(const char *path)
ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE,
ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE }
};
#elif HAVE_DARWIN_ACL /* Mac OS X */
#elif ARCHIVE_ACL_DARWIN /* Mac OS X */
acl_entry_t aclent;
acl_permset_t permset;
const uid_t uid = 1;
@ -2571,14 +2587,19 @@ setTestAcl(const char *path)
ACL_SYNCHRONIZE
#endif
};
#endif /* HAVE_DARWIN_ACL */
#endif /* ARCHIVE_ACL_DARWIN */
#if HAVE_FREEBSD_NFS4_ACL
#if ARCHIVE_ACL_FREEBSD
acl = acl_from_text(acltext_nfs4);
failure("acl_from_text() error: %s", strerror(errno));
if (assert(acl != NULL) == 0)
return (0);
#elif HAVE_DARWIN_ACL
#elif ARCHIVE_ACL_LIBRICHACL
richacl = richacl_from_text(acltext_nfs4, NULL, NULL);
failure("richacl_from_text() error: %s", strerror(errno));
if (assert(richacl != NULL) == 0)
return (0);
#elif ARCHIVE_ACL_DARWIN
acl = acl_init(1);
failure("acl_init() error: %s", strerror(errno));
if (assert(acl != NULL) == 0)
@ -2605,33 +2626,36 @@ setTestAcl(const char *path)
failure("acl_set_permset() error: %s", strerror(errno));
if (assertEqualInt(r, 0) == 0)
goto testacl_free;
r = mbr_identifier_to_uuid(ID_TYPE_UID, &uid, sizeof(uid_t), uuid);
failure("mbr_identifier_to_uuid() error: %s", strerror(errno));
r = mbr_uid_to_uuid(uid, uuid);
failure("mbr_uid_to_uuid() error: %s", strerror(errno));
if (assertEqualInt(r, 0) == 0)
goto testacl_free;
r = acl_set_qualifier(aclent, uuid);
failure("acl_set_qualifier() error: %s", strerror(errno));
if (assertEqualInt(r, 0) == 0)
goto testacl_free;
#endif /* HAVE_DARWIN_ACL */
#endif /* ARCHIVE_ACL_DARWIN */
#if HAVE_NFS4_ACL
#if HAVE_FREEBSD_NFS4_ACL
#if ARCHIVE_ACL_NFS4
#if ARCHIVE_ACL_FREEBSD
r = acl_set_file(path, ACL_TYPE_NFS4, acl);
acl_free(acl);
#elif HAVE_SUN_NFS4_ACL
#elif ARCHIVE_ACL_LIBRICHACL
r = richacl_set_file(path, richacl);
richacl_free(richacl);
#elif ARCHIVE_ACL_SUNOS_NFS4
r = acl(path, ACE_SETACL,
(int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4);
#elif HAVE_DARWIN_ACL
#elif ARCHIVE_ACL_DARWIN
r = acl_set_file(path, ACL_TYPE_EXTENDED, acl);
acl_free(acl);
#endif
if (r == 0)
return (ARCHIVE_TEST_ACL_TYPE_NFS4);
#endif /* HAVE_NFS4_ACL */
#endif /* ARCHIVE_ACL_NFS4 */
#if HAVE_POSIX_ACL || HAVE_SUN_ACL
#if HAVE_POSIX_ACL
#if ARCHIVE_ACL_POSIX1E
#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
acl = acl_from_text(acltext_posix1e);
failure("acl_from_text() error: %s", strerror(errno));
if (assert(acl != NULL) == 0)
@ -2639,7 +2663,7 @@ setTestAcl(const char *path)
r = acl_set_file(path, ACL_TYPE_ACCESS, acl);
acl_free(acl);
#elif HAVE_SUN_ACL
#elif ARCHIVE_ACL_SUNOS
r = acl(path, SETACL,
(int)(sizeof(aclp_posix1e)/sizeof(aclp_posix1e[0])), aclp_posix1e);
#endif
@ -2647,12 +2671,12 @@ setTestAcl(const char *path)
return (ARCHIVE_TEST_ACL_TYPE_POSIX1E);
else
return (0);
#endif /* HAVE_POSIX_ACL || HAVE_SUN_ACL */
#if HAVE_DARWIN_ACL
#endif /* ARCHIVE_ACL_POSIX1E */
#if ARCHIVE_ACL_DARWIN
testacl_free:
acl_free(acl);
#endif
#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
#endif /* ARCHIVE_ACL_SUPPORT */
(void)path; /* UNUSED */
return (0);
}

View File

@ -45,6 +45,7 @@ INCS= archive.h archive_entry.h
# Sources to be compiled.
SRCS= archive_acl.c \
archive_acl_maps_freebsd.c \
archive_check_magic.c \
archive_cmdline.c \
archive_cryptor.c \
@ -69,6 +70,7 @@ SRCS= archive_acl.c \
archive_read_add_passphrase.c \
archive_read_append_filter.c \
archive_read_data_into_fd.c \
archive_read_disk_acl_freebsd.c \
archive_read_disk_entry_from_file.c \
archive_read_disk_posix.c \
archive_read_disk_set_standard_lookup.c \
@ -112,10 +114,11 @@ SRCS= archive_acl.c \
archive_string.c \
archive_string_sprintf.c \
archive_util.c \
archive_version_details.c \
archive_virtual.c \
archive_write.c \
archive_write_add_filter.c \
archive_write_disk_acl.c \
archive_write_disk_acl_freebsd.c \
archive_write_disk_set_standard_lookup.c \
archive_write_disk_posix.c \
archive_write_open_fd.c \

View File

@ -27,22 +27,11 @@
#include <osreldate.h>
/* FreeBSD 5.0 and later have ACL and extattr support. */
/* FreeBSD 5.0 and later has ACL and extattr support. */
#if __FreeBSD__ > 4
#define HAVE_ACL_CREATE_ENTRY 1
#define HAVE_ACL_GET_FD_NP 1
#define HAVE_ACL_GET_LINK_NP 1
#define ARCHIVE_ACL_FREEBSD 1
#define HAVE_ACL_GET_PERM_NP 1
#define HAVE_ACL_INIT 1
#define HAVE_ACL_IS_TRIVIAL_NP 1
#define HAVE_ACL_PERMSET_T 1
#define HAVE_ACL_SET_FD 1
#define HAVE_ACL_SET_FD_NP 1
#define HAVE_ACL_SET_FILE 1
#define HAVE_ACL_SET_LINK_NP 1
#define HAVE_ARC4RANDOM_BUF 1
#define HAVE_DECL_ACL_USER 1
#define HAVE_DECL_ACL_TYPE_NFS4 1
#define HAVE_EXTATTR_GET_FILE 1
#define HAVE_EXTATTR_LIST_FILE 1
#define HAVE_EXTATTR_SET_FD 1
@ -50,7 +39,14 @@
#define HAVE_STRUCT_XVFSCONF 1
#define HAVE_SYS_ACL_H 1
#define HAVE_SYS_EXTATTR_H 1
#endif
#if __FreeBSD__ > 7
/* FreeBSD 8.0 and later has NFSv4 ACL support */
#define ARCHIVE_ACL_FREEBSD_NFS4 1
#define HAVE_ACL_GET_LINK_NP 1
#define HAVE_ACL_IS_TRIVIAL_NP 1
#define HAVE_ACL_SET_LINK_NP 1
#endif /* __FreeBSD__ > 7 */
#endif /* __FreeBSD__ > 4 */
#ifdef WITH_OPENSSL
#define HAVE_LIBCRYPTO 1

View File

@ -15,6 +15,7 @@ CFLAGS+= -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
CFLAGS+= -I${.OBJDIR}
CFLAGS+= -I${_LIBARCHIVEDIR}/cat -I${_LIBARCHIVEDIR}/cat/test
CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive
CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive_fe -I${_LIBARCHIVEDIR}/test_utils
# Uncomment to link against dmalloc

View File

@ -15,6 +15,7 @@ CFLAGS+= -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
CFLAGS+= -I${.OBJDIR}
CFLAGS+= -I${_LIBARCHIVEDIR}/cpio -I${_LIBARCHIVEDIR}/cpio/test
CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive
CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive_fe -I${_LIBARCHIVEDIR}/test_utils
# Uncomment to link against dmalloc

View File

@ -10,6 +10,7 @@ BINDIR= ${TESTSDIR}
CFLAGS+= -DPLATFORM_CONFIG_H=\"${SRCTOP}/lib/libarchive/config_freebsd.h\"
CFLAGS+= -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive
CFLAGS+= -I${_LIBARCHIVEDIR}/tar -I${_LIBARCHIVEDIR}/tar/test
CFLAGS+= -I${_LIBARCHIVEDIR}/test_utils