diff options
author | Martin Matuska <martin@matuska.org> | 2017-03-13 15:49:38 +0100 |
---|---|---|
committer | Martin Matuska <martin@matuska.org> | 2017-03-14 12:48:53 +0100 |
commit | f57d129d828f411d6f1eb81ca51dfd9e1fead353 (patch) | |
tree | 2683fbe533ae01206a3e0a2365ae2d263eb5e697 /libarchive | |
parent | 500b90526996eb64b9cb5a02ac9de61f0a2ec14f (diff) | |
download | libarchive-f57d129d828f411d6f1eb81ca51dfd9e1fead353.tar.gz |
Move platform-specific ACL code to individual source files.
This makes the code much more readable and eases the addition of new
ACL implementatons in the future.
Additional changes:
- most of ACL detection is now done at configure stage
- configuration now reports what ACL was detected
- NFSv4 ACL tests now test INHERIT_ONLY and NO_PROPAGATE_INHERIT
Diffstat (limited to 'libarchive')
23 files changed, 3183 insertions, 2020 deletions
diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index d55fa2d8..0ed3fa48 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -14,6 +14,7 @@ SET(include_HEADERS # Sources and private headers SET(libarchive_SOURCES archive_acl.c + archive_acl_private.h archive_check_magic.c archive_cmdline.c archive_cmdline_private.h @@ -47,6 +48,7 @@ SET(libarchive_SOURCES archive_pathmatch.c archive_pathmatch.h archive_platform.h + archive_platform_acl.h archive_ppmd_private.h archive_ppmd7.c archive_ppmd7_private.h @@ -109,7 +111,6 @@ SET(libarchive_SOURCES archive_version_details.c archive_virtual.c archive_write.c - archive_write_disk_acl.c archive_write_disk_posix.c archive_write_disk_private.h archive_write_disk_set_standard_lookup.c @@ -211,6 +212,28 @@ IF(WIN32 AND NOT CYGWIN) LIST(APPEND libarchive_SOURCES filter_fork_windows.c) ENDIF(WIN32 AND NOT CYGWIN) +IF(ARCHIVE_ACL_DARWIN) + LIST(APPEND libarchive_SOURCES archive_acl_maps.h) + LIST(APPEND libarchive_SOURCES archive_acl_maps_darwin.c) + LIST(APPEND libarchive_SOURCES archive_read_disk_acl_darwin.c) + LIST(APPEND libarchive_SOURCES archive_write_disk_acl_darwin.c) +ELSEIF(ARCHIVE_ACL_FREEBSD) + LIST(APPEND libarchive_SOURCES archive_acl_maps.h) + LIST(APPEND libarchive_SOURCES archive_acl_maps_freebsd.c) + LIST(APPEND libarchive_SOURCES archive_read_disk_acl_freebsd.c) + LIST(APPEND libarchive_SOURCES archive_write_disk_acl_freebsd.c) +ELSEIF(ARCHIVE_ACL_LIBACL) + LIST(APPEND libarchive_SOURCES archive_acl_maps.h) + LIST(APPEND libarchive_SOURCES archive_acl_maps_linux.c) + LIST(APPEND libarchive_SOURCES archive_read_disk_acl_linux.c) + LIST(APPEND libarchive_SOURCES archive_write_disk_acl_linux.c) +ELSEIF(ARCHIVE_ACL_SUNOS) + LIST(APPEND libarchive_SOURCES archive_acl_maps.h) + LIST(APPEND libarchive_SOURCES archive_acl_maps_sunos.c) + LIST(APPEND libarchive_SOURCES archive_read_disk_acl_sunos.c) + LIST(APPEND libarchive_SOURCES archive_write_disk_acl_sunos.c) +ENDIF() + # Libarchive is a shared library ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS}) TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS}) diff --git a/libarchive/archive_acl_maps.h b/libarchive/archive_acl_maps.h new file mode 100644 index 00000000..c9dba525 --- /dev/null +++ b/libarchive/archive_acl_maps.h @@ -0,0 +1,52 @@ +/*- + * 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; + +#ifndef _ARCHIVE_ACL_MAPS_DEFS +#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_DEFS */ +#endif /* ARCHIVE_ACL_MAPS_H_INCLUDED */ diff --git a/libarchive/archive_acl_maps_darwin.c b/libarchive/archive_acl_maps_darwin.c new file mode 100644 index 00000000..eaa046ce --- /dev/null +++ b/libarchive/archive_acl_maps_darwin.c @@ -0,0 +1,76 @@ +/*- + * 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" +#define _ARCHIVE_ACL_MAPS_DEFS +#include "archive_acl_maps.h" + +const acl_perm_map_t acl_nfs4_perm_map[] = { + {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 +}; + +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_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} +}; + +const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); diff --git a/libarchive/archive_acl_maps_freebsd.c b/libarchive/archive_acl_maps_freebsd.c new file mode 100644 index 00000000..222dcff1 --- /dev/null +++ b/libarchive/archive_acl_maps_freebsd.c @@ -0,0 +1,87 @@ +/*- + * 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" +#define _ARCHIVE_ACL_MAPS_DEFS +#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 */ diff --git a/libarchive/archive_acl_maps_linux.c b/libarchive/archive_acl_maps_linux.c new file mode 100644 index 00000000..c184f20b --- /dev/null +++ b/libarchive/archive_acl_maps_linux.c @@ -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. + */ + +#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" +#define _ARCHIVE_ACL_MAPS_DEFS +#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])); diff --git a/libarchive/archive_acl_maps_sunos.c b/libarchive/archive_acl_maps_sunos.c new file mode 100644 index 00000000..2197d501 --- /dev/null +++ b/libarchive/archive_acl_maps_sunos.c @@ -0,0 +1,90 @@ +/*- + * 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" +#define _ARCHIVE_ACL_MAPS_DEFS +#include "archive_acl_maps.h" + +const acl_perm_map_t acl_posix_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH }, + {ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH }, + {ARCHIVE_ENTRY_ACL_READ, S_IROTH } +}; + +const int acl_posix_perm_map_size = + (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); + +#if ARCHIVE_ACL_SUNOS_NFS4 +const acl_perm_map_t acl_nfs4_perm_map[] = { + {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} +}; + +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, 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 +}; + +const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); + +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h index 01d6a70d..34be8eda 100644 --- a/libarchive/archive_platform.h +++ b/libarchive/archive_platform.h @@ -143,40 +143,6 @@ #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. */ diff --git a/libarchive/archive_platform_acl.h b/libarchive/archive_platform_acl.h new file mode 100644 index 00000000..8c091cf5 --- /dev/null +++ b/libarchive/archive_platform_acl.h @@ -0,0 +1,48 @@ +/*- + * 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 +#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 */ diff --git a/libarchive/archive_read_disk_acl_darwin.c b/libarchive/archive_read_disk_acl_darwin.c new file mode 100644 index 00000000..dc332ace --- /dev/null +++ b/libarchive/archive_read_disk_acl_darwin.c @@ -0,0 +1,348 @@ +/*- + * 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_FCNTL_H +#include <fcntl.h> +#endif +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_MEMBERSHIP_H +#include <membership.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" + + +/* + * Darwin-specific ACL functions and helper functions + * + * Exported functions: + * none + */ +static int translate_guid(struct archive *a, acl_entry_t acl_entry, + int *ae_id, int *ae_tag, const char **ae_name) +{ + void *q; + uid_t ugid; + int r, idtype; + + q = acl_get_qualifier(acl_entry); + if (q == NULL) + return (1); + r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); + if (r != 0) { + acl_free(q); + return (1); + } + if (idtype == ID_TYPE_UID) { + *ae_tag = ARCHIVE_ENTRY_ACL_USER; + *ae_id = ugid; + *ae_name = archive_read_disk_uname(a, *ae_id); + } else if (idtype == ID_TYPE_GID) { + *ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + *ae_id = ugid; + *ae_name = archive_read_disk_gname(a, *ae_id); + } else + r = 1; + + acl_free(q); + return (r); +} + +/* + * Add trivial NFSv4 ACL entries from mode + */ +static void +add_trivial_nfs4_acl(struct archive_entry *entry) +{ + mode_t mode; + int i; + const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; + const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA; + const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE; + const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER; + + struct { + const int type; + const int tag; + int permset; + } tacl_entry[] = { + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset} + }; + + mode = archive_entry_mode(entry); + + /* Permissions for everyone@ */ + if (mode & 0004) + tacl_entry[5].permset |= rperm; + if (mode & 0002) + tacl_entry[5].permset |= wperm; + if (mode & 0001) + tacl_entry[5].permset |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tacl_entry[4].permset |= rperm; + else if (mode & 0004) + tacl_entry[2].permset |= rperm; + if (mode & 0020) + tacl_entry[4].permset |= wperm; + else if (mode & 0002) + tacl_entry[2].permset |= wperm; + if (mode & 0010) + tacl_entry[4].permset |= eperm; + else if (mode & 0001) + tacl_entry[2].permset |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tacl_entry[3].permset |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tacl_entry[0].permset |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tacl_entry[1].permset |= rperm; + if (mode & 0200) { + tacl_entry[3].permset |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tacl_entry[0].permset |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tacl_entry[1].permset |= wperm; + if (mode & 0100) { + tacl_entry[3].permset |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tacl_entry[0].permset |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tacl_entry[1].permset |= eperm; + + for (i = 0; i < 6; i++) { + if (tacl_entry[i].permset != 0) { + archive_entry_acl_add_entry(entry, + tacl_entry[i].type, tacl_entry[i].permset, + tacl_entry[i].tag, -1, NULL); + } + } + + return; +} + +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl) +{ + acl_tag_t acl_tag; + acl_flagset_t acl_flagset; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type; + int r, s, ae_id, ae_tag, ae_perm; + const char *ae_name; + + 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 == 0) { + 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_EXTENDED_ALLOW: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + r = translate_guid(&a->archive, acl_entry, + &ae_id, &ae_tag, &ae_name); + break; + case ACL_EXTENDED_DENY: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + r = translate_guid(&a->archive, acl_entry, + &ae_id, &ae_tag, &ae_name); + break; + default: + /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + /* Skip if translate_guid() above failed */ + if (r != 0) { + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + /* + * 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; + } + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + /* + * acl_get_perm() is spelled differently on different + * platforms; see above. + */ + r = acl_get_perm_np(acl_permset, + acl_nfs4_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 |= acl_nfs4_perm_map[i].a_perm; + } + +#if !HAVE_DECL_ACL_SYNCHRONIZE + /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */ + ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; +#endif + + 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); + } + 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_entry_sourcepath(entry); + if (accpath == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + accpath = archive_entry_pathname(entry); + if (accpath == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine file path to read ACLs"); + return (ARCHIVE_WARN); + } + if (a->tree != NULL && (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, + accpath, O_RDONLY | O_NONBLOCK); + } + } + + archive_entry_acl_clear(entry); + + acl = NULL; + + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED); + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED); + else + acl = acl_get_file(accpath, ACL_TYPE_EXTENDED); + + if (acl != NULL) { + r = translate_acl(a, entry, acl); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + + /* + * Because Mac OS doesn't support owner@, group@ and everyone@ + * ACLs we need to add NFSv4 ACLs mirroring the file mode to + * the archive entry. Otherwise extraction on non-Mac platforms + * would lead to an invalid file mode. + */ + if ((archive_entry_acl_types(entry) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) + add_trivial_nfs4_acl(entry); + + return (r); + } + return (ARCHIVE_OK); +} diff --git a/libarchive/archive_read_disk_acl_freebsd.c b/libarchive/archive_read_disk_acl_freebsd.c new file mode 100644 index 00000000..ee87517e --- /dev/null +++ b/libarchive/archive_read_disk_acl_freebsd.c @@ -0,0 +1,382 @@ +/*- + * 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_entry_sourcepath(entry); + if (accpath == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + accpath = archive_entry_pathname(entry); + if (accpath == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine file path to read ACLs"); + return (ARCHIVE_WARN); + } + if (a->tree != NULL && (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, + accpath, O_RDONLY | O_NONBLOCK); + } + } + + 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); +} diff --git a/libarchive/archive_read_disk_acl_linux.c b/libarchive/archive_read_disk_acl_linux.c new file mode 100644 index 00000000..23146dba --- /dev/null +++ b/libarchive/archive_read_disk_acl_linux.c @@ -0,0 +1,228 @@ +/*- + * 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 +#if HAVE_ACL_LIBACL_H && HAVE_LIBACL +#include <acl/libacl.h> +#endif +#ifdef HAVE_SYS_ACL_H +#include <sys/acl.h> +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_acl_maps.h" + +#if HAVE_LIBACL +#include <acl/libacl.h> +#endif + +/* + * Translate POSIX.1e 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) +{ + acl_tag_t acl_tag; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type; + int r, s, ae_id, ae_tag, ae_perm; + void *q; + const char *ae_name; + + 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; + 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 (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + r = acl_get_perm(acl_permset, + acl_posix_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 |= acl_posix_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; + + /* For default ACLs we need reachable accpath */ + if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) + { + accpath = archive_entry_sourcepath(entry); + if (accpath == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + accpath = archive_entry_pathname(entry); + if (accpath == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine file path to read ACLs"); + return (ARCHIVE_WARN); + } + if (a->tree != NULL && *fd < 0 && (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, + accpath, O_RDONLY | O_NONBLOCK); + } + } + + archive_entry_acl_clear(entry); + + acl = NULL; + + /* Retrieve access ACL from file. */ + if (*fd >= 0) + acl = acl_get_fd(*fd); + 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; + else + acl = acl_get_file(accpath, ACL_TYPE_ACCESS); + + 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))) { + 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); +} diff --git a/libarchive/archive_read_disk_acl_sunos.c b/libarchive/archive_read_disk_acl_sunos.c new file mode 100644 index 00000000..2bcdf0e3 --- /dev/null +++ b/libarchive/archive_read_disk_acl_sunos.c @@ -0,0 +1,494 @@ +/*- + * 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_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 +#include <sys/acl.h> +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_acl_maps.h" + +/* + * Solaris-specific ACL functions and helper functions + * + * Exported functions: + * translate_acl() + */ +static void * +sunacl_get(int cmd, int *aclcnt, int fd, const char *path) +{ + int cnt, cntcmd; + size_t size; + void *aclp; + + if (cmd == GETACL) { + cntcmd = GETACLCNT; + size = sizeof(aclent_t); + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else if (cmd == ACE_GETACL) { + cntcmd = ACE_GETACLCNT; + size = sizeof(ace_t); + } +#endif + else { + errno = EINVAL; + *aclcnt = -1; + return (NULL); + } + + aclp = NULL; + cnt = -2; + + while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) { + if (path != NULL) + cnt = acl(path, cntcmd, 0, NULL); + else + cnt = facl(fd, cntcmd, 0, NULL); + + if (cnt > 0) { + if (aclp == NULL) + aclp = malloc(cnt * size); + else + aclp = realloc(NULL, cnt * size); + if (aclp != NULL) { + if (path != NULL) + cnt = acl(path, cmd, cnt, aclp); + else + cnt = facl(fd, cmd, cnt, aclp); + } + } else { + if (aclp != NULL) { + free(aclp); + aclp = NULL; + } + break; + } + } + + *aclcnt = cnt; + return (aclp); +} + +/* + * Check if acl is trivial + * This is a FreeBSD acl_is_trivial_np() implementation for Solaris + */ +static int +sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4, + int is_dir, int *trivialp) +{ +#if ARCHIVE_ACL_SUNOS_NFS4 + int i, p; + const uint32_t rperm = ACE_READ_DATA; + const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA; + const uint32_t eperm = ACE_EXECUTE; + const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | + ACE_READ_ACL | ACE_SYNCHRONIZE; + const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES | + ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER; + + ace_t *ace; + ace_t tace[6]; +#endif + + if (aclp == NULL || trivialp == NULL) + return (-1); + + *trivialp = 0; + + /* + * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with + * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries, + * including mask. + */ + if (!is_nfs4) { + if (aclcnt == 4) + *trivialp = 1; + return (0); + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + /* + * Continue with checking NFSv4 ACLs + * + * Create list of trivial ace's to be compared + */ + + /* owner@ allow pre */ + tace[0].a_flags = ACE_OWNER; + tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[0].a_access_mask = 0; + + /* owner@ deny */ + tace[1].a_flags = ACE_OWNER; + tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[1].a_access_mask = 0; + + /* group@ deny */ + tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[2].a_access_mask = 0; + + /* owner@ allow */ + tace[3].a_flags = ACE_OWNER; + tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[3].a_access_mask = ownset; + + /* group@ allow */ + tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[4].a_access_mask = pubset; + + /* everyone@ allow */ + tace[5].a_flags = ACE_EVERYONE; + tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[5].a_access_mask = pubset; + + /* Permissions for everyone@ */ + if (mode & 0004) + tace[5].a_access_mask |= rperm; + if (mode & 0002) + tace[5].a_access_mask |= wperm; + if (mode & 0001) + tace[5].a_access_mask |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tace[4].a_access_mask |= rperm; + else if (mode & 0004) + tace[2].a_access_mask |= rperm; + if (mode & 0020) + tace[4].a_access_mask |= wperm; + else if (mode & 0002) + tace[2].a_access_mask |= wperm; + if (mode & 0010) + tace[4].a_access_mask |= eperm; + else if (mode & 0001) + tace[2].a_access_mask |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tace[3].a_access_mask |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tace[0].a_access_mask |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tace[1].a_access_mask |= rperm; + if (mode & 0200) { + tace[3].a_access_mask |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tace[0].a_access_mask |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tace[1].a_access_mask |= wperm; + if (mode & 0100) { + tace[3].a_access_mask |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tace[0].a_access_mask |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tace[1].a_access_mask |= eperm; + + /* Check if the acl count matches */ + p = 3; + for (i = 0; i < 3; i++) { + if (tace[i].a_access_mask != 0) + p++; + } + if (aclcnt != p) + return (0); + + p = 0; + for (i = 0; i < 6; i++) { + if (tace[i].a_access_mask != 0) { + ace = &((ace_t *)aclp)[p]; + /* + * Illumos added ACE_DELETE_CHILD to write perms for + * directories. We have to check against that, too. + */ + if (ace->a_flags != tace[i].a_flags || + ace->a_type != tace[i].a_type || + (ace->a_access_mask != tace[i].a_access_mask && + (!is_dir || (tace[i].a_access_mask & wperm) == 0 || + ace->a_access_mask != + (tace[i].a_access_mask | ACE_DELETE_CHILD)))) + return (0); + p++; + } + } + + *trivialp = 1; +#else /* !ARCHIVE_ACL_SUNOS_NFS4 */ + (void)is_dir; /* UNUSED */ + (void)aclp; /* UNUSED */ +#endif /* !ARCHIVE_ACL_SUNOS_NFS4 */ + return (0); +} + +/* + * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL + */ +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, void *aclp, int aclcnt, + int default_entry_acl_type) +{ + int e, i; + int ae_id, ae_tag, ae_perm; + int entry_acl_type; + const char *ae_name; + aclent_t *aclent; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace_t *ace; +#endif + + if (aclcnt <= 0) + return (ARCHIVE_OK); + + for (e = 0; e < aclcnt; e++) { + ae_name = NULL; + ae_tag = 0; + ae_perm = 0; + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + ace = &((ace_t *)aclp)[e]; + ae_id = ace->a_who; + + switch(ace->a_type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case ACE_ACCESS_DENIED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + case ACE_SYSTEM_AUDIT_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + break; + case ACE_SYSTEM_ALARM_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + break; + default: + /* Unknown entry type, skip */ + continue; + } + + if ((ace->a_flags & ACE_OWNER) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if ((ace->a_flags & ACE_GROUP) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + else if ((ace->a_flags & ACE_EVERYONE) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) { + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } else { + ae_tag = ARCHIVE_ENTRY_ACL_USER; + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if ((ace->a_flags & + acl_nfs4_flag_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if ((ace->a_access_mask & + acl_nfs4_perm_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_perm_map[i].a_perm; + } + } else +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + aclent = &((aclent_t *)aclp)[e]; + if ((aclent->a_type & ACL_DEFAULT) != 0) + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + else + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + ae_id = aclent->a_id; + + switch(aclent->a_type) { + case DEF_USER: + case USER: + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case DEF_GROUP: + case GROUP: + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case DEF_CLASS_OBJ: + case CLASS_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case DEF_USER_OBJ: + case USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case DEF_GROUP_OBJ: + case GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case DEF_OTHER_OBJ: + case OTHER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + default: + /* Unknown tag type, skip */ + continue; + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + if ((aclent->a_perm & + acl_posix_perm_map[i].p_perm) != 0) + ae_perm |= acl_posix_perm_map[i].a_perm; + } + } else + return (ARCHIVE_WARN); + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, ae_id, ae_name); + } + return (ARCHIVE_OK); +} + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + void *aclp; + int aclcnt; + int r; + + accpath = NULL; + + if (*fd < 0) + { + accpath = archive_entry_sourcepath(entry); + if (accpath == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + accpath = archive_entry_pathname(entry); + if (accpath == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine file path to read ACLs"); + return (ARCHIVE_WARN); + } + if (a->tree != NULL && (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, + accpath, O_RDONLY | O_NONBLOCK); + } + } + + archive_entry_acl_clear(entry); + + aclp = NULL; + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (*fd >= 0) + aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL); + 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. */ + aclp = NULL; + else + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath); + + if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, + archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)), + &r) == 0 && r == 1) { + free(aclp); + aclp = NULL; + return (ARCHIVE_OK); + } + + if (aclp != NULL) { + r = translate_acl(a, entry, aclp, aclcnt, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + free(aclp); + aclp = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + return (r); + } +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + + /* Retrieve POSIX.1e ACLs from file. */ + if (*fd >= 0) + aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL); + 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. */ + aclp = NULL; + else + aclp = sunacl_get(GETACL, &aclcnt, 0, accpath); + + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, + archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)), + &r) == 0 && r == 1) { + free(aclp); + aclp = NULL; + } + + if (aclp != NULL) + { + r = translate_acl(a, entry, aclp, aclcnt, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + free(aclp); + aclp = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } + } + + return (ARCHIVE_OK); +} diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index 1c94afdd..899cb062 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -26,21 +26,14 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $"); +__FBSDID("$FreeBSD"); /* This is the tree-walking code for POSIX systems. */ #if !defined(_WIN32) || defined(__CYGWIN__) #ifdef HAVE_SYS_TYPES_H -/* Mac OSX requires sys/types.h before sys/acl.h. */ #include <sys/types.h> #endif -#ifdef HAVE_SYS_ACL_H -#include <sys/acl.h> -#endif -#ifdef HAVE_DARWIN_ACL -#include <membership.h> -#endif #ifdef HAVE_SYS_EXTATTR_H #include <sys/extattr.h> #endif @@ -61,9 +54,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #ifdef HAVE_SYS_EA_H #include <sys/ea.h> #endif -#ifdef HAVE_ACL_LIBACL_H -#include <acl/libacl.h> -#endif #ifdef HAVE_COPYFILE_H #include <copyfile.h> #endif @@ -111,25 +101,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #define O_CLOEXEC 0 #endif -/* - * Linux and FreeBSD plug this obvious hole in POSIX.1e in - * different ways. - */ -#if HAVE_ACL_GET_PERM -#define ACL_GET_PERM acl_get_perm -#elif HAVE_ACL_GET_PERM_NP -#define ACL_GET_PERM acl_get_perm_np -#endif - -/* NFSv4 platform ACL type */ -#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 +#ifndef ARCHIVE_ACL_SUPPORT +static int archive_read_disk_entry_setup_acls(struct archive_read_disk *, +struct archive_entry *, int *fd); #endif - -static int setup_acls(struct archive_read_disk *, - struct archive_entry *, int *fd); static int setup_mac_metadata(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_xattrs(struct archive_read_disk *, @@ -275,7 +250,7 @@ archive_read_disk_entry_from_file(struct archive *_a, r = 0; if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0) - r = setup_acls(a, entry, &fd); + r = archive_read_disk_entry_setup_acls(a, entry, &fd); if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) { r1 = setup_xattrs(a, entry, &fd); if (r1 < r) @@ -422,1102 +397,6 @@ setup_mac_metadata(struct archive_read_disk *a, } #endif -#if HAVE_DARWIN_ACL -static int translate_guid(struct archive *, acl_entry_t, - int *, int *, const char **); - -static void add_trivial_nfs4_acl(struct archive_entry *); -#endif - -#if HAVE_SUN_ACL -static int -sun_acl_is_trivial(void *, int, mode_t, int, int, int *); - -static void * -sunacl_get(int cmd, int *aclcnt, int fd, const char *path) -{ - int cnt, cntcmd; - size_t size; - void *aclp; - - if (cmd == GETACL) { - cntcmd = GETACLCNT; - size = sizeof(aclent_t); - } -#if HAVE_SUN_NFS4_ACL - else if (cmd == ACE_GETACL) { - cntcmd = ACE_GETACLCNT; - size = sizeof(ace_t); - } -#endif - else { - errno = EINVAL; - *aclcnt = -1; - return (NULL); - } - - aclp = NULL; - cnt = -2; - - while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) { - if (path != NULL) - cnt = acl(path, cntcmd, 0, NULL); - else - cnt = facl(fd, cntcmd, 0, NULL); - - if (cnt > 0) { - if (aclp == NULL) - aclp = malloc(cnt * size); - else - aclp = realloc(NULL, cnt * size); - if (aclp != NULL) { - if (path != NULL) - cnt = acl(path, cmd, cnt, aclp); - else - cnt = facl(fd, cmd, cnt, aclp); - } - } else { - if (aclp != NULL) { - free(aclp); - aclp = NULL; - } - break; - } - } - - *aclcnt = cnt; - return (aclp); -} -#endif /* HAVE_SUN_ACL */ - -#if HAVE_POSIX_ACL || HAVE_NFS4_ACL -static int translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, -#if HAVE_SUN_ACL - void *aclp, - int aclcnt, -#else - acl_t acl, -#endif - int archive_entry_acl_type); - -static int -setup_acls(struct archive_read_disk *a, - struct archive_entry *entry, int *fd) -{ - const char *accpath; -#if HAVE_SUN_ACL - void *aclp; - int aclcnt; -#else - acl_t acl; -#endif - int r; - - accpath = NULL; - -#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP - if (*fd < 0) -#else - /* For default ACLs on Linux we need reachable accpath */ - if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) -#endif - { - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL || (a->tree != NULL && - a->tree_enter_working_dir(a->tree) != 0)) - accpath = archive_entry_pathname(entry); - if (accpath == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Couldn't determine file path to read ACLs"); - return (ARCHIVE_WARN); - } - if (a->tree != NULL && -#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP - *fd < 0 && -#endif - (a->follow_symlinks || - archive_entry_filetype(entry) != AE_IFLNK)) { - *fd = a->open_on_current_dir(a->tree, - accpath, O_RDONLY | O_NONBLOCK); - } - } - - archive_entry_acl_clear(entry); - -#if HAVE_SUN_ACL - aclp = NULL; -#else - acl = NULL; -#endif - -#if HAVE_NFS4_ACL - /* Try NFSv4 ACL first. */ - if (*fd >= 0) -#if HAVE_SUN_ACL - aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL); -#elif HAVE_ACL_GET_FD_NP - acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); -#else - acl = acl_get_fd(*fd); -#endif -#if HAVE_ACL_GET_LINK_NP - else if (!a->follow_symlinks) - acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); -#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. */ -#if HAVE_SUN_ACL - aclp = NULL; -#else - acl = NULL; -#endif -#endif /* !HAVE_ACL_GET_LINK_NP */ - else -#if HAVE_SUN_ACL - /* Solaris reads both POSIX.1e and NFSv4 ACLs here */ - aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath); -#else - acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); -#endif - - - /* Ignore "trivial" ACLs that just mirror the file mode. */ -#if HAVE_SUN_ACL - if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, - archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)), - &r) == 0 && r == 1) { - free(aclp); - aclp = NULL; - return (ARCHIVE_OK); - } -#elif HAVE_ACL_IS_TRIVIAL_NP - if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { - acl_free(acl); - acl = NULL; - return (ARCHIVE_OK); - } -#endif - -#if HAVE_SUN_ACL - if (aclp != NULL) -#else - if (acl != NULL) -#endif - { - r = translate_acl(a, entry, -#if HAVE_SUN_ACL - aclp, aclcnt, -#else - acl, -#endif - ARCHIVE_ENTRY_ACL_TYPE_NFS4); -#if HAVE_SUN_ACL - free(aclp); - aclp = NULL; -#else - acl_free(acl); - acl = NULL; -#endif - - if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, errno, - "Couldn't translate NFSv4 ACLs"); - } -#if HAVE_DARWIN_ACL - /* - * Because Mac OS doesn't support owner@, group@ and everyone@ - * ACLs we need to add NFSv4 ACLs mirroring the file mode to - * the archive entry. Otherwise extraction on non-Mac platforms - * would lead to an invalid file mode. - */ - if ((archive_entry_acl_types(entry) & - ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) - add_trivial_nfs4_acl(entry); -#endif - return (r); - } -#endif /* HAVE_NFS4_ACL */ - -#if HAVE_POSIX_ACL || HAVE_SUN_ACL - /* This code path is skipped on MacOS */ - - /* Retrieve access ACL from file. */ - if (*fd >= 0) -#if HAVE_SUN_ACL - aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL); -#else - acl = acl_get_fd(*fd); -#endif -#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. */ -#if HAVE_SUN_ACL - aclp = NULL; -#else - acl = NULL; -#endif -#endif /* !HAVE_ACL_GET_LINK_NP */ - else -#if HAVE_SUN_ACL - aclp = sunacl_get(GETACL, &aclcnt, 0, accpath); -#else - acl = acl_get_file(accpath, ACL_TYPE_ACCESS); -#endif - - - /* Ignore "trivial" ACLs that just mirror the file mode. */ -#if HAVE_SUN_ACL - if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, - archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)), - &r) == 0 && r == 1) { - free(aclp); - aclp = NULL; - } -#elif HAVE_ACL_IS_TRIVIAL_NP - if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { - acl_free(acl); - acl = NULL; - } -#endif - -#if HAVE_SUN_ACL - if (aclp != NULL) -#else - if (acl != NULL) -#endif - { - r = translate_acl(a, entry, -#if HAVE_SUN_ACL - aclp, aclcnt, -#else - acl, -#endif - ARCHIVE_ENTRY_ACL_TYPE_ACCESS); -#if HAVE_SUN_ACL - free(aclp); - aclp = NULL; -#else - acl_free(acl); - acl = NULL; -#endif - - if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, errno, - "Couldn't translate access ACLs"); - return (r); - } - } - -#if !HAVE_SUN_ACL - /* Only directories can have default ACLs. */ - if (S_ISDIR(archive_entry_mode(entry))) { -#if HAVE_ACL_GET_FD_NP - if (*fd >= 0) - acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); - else -#endif - 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); - } - } - } -#endif /* !HAVE_SUN_ACL */ -#endif /* HAVE_POSIX_ACL || HAVE_SUN_ACL */ - return (ARCHIVE_OK); -} - -/* - * 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_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 */ -}; - -#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 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 - {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 */ - -#if HAVE_DARWIN_ACL -static int translate_guid(struct archive *a, acl_entry_t acl_entry, - int *ae_id, int *ae_tag, const char **ae_name) -{ - void *q; - uid_t ugid; - int r, idtype; - - q = acl_get_qualifier(acl_entry); - if (q == NULL) - return (1); - r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); - if (r != 0) { - acl_free(q); - return (1); - } - if (idtype == ID_TYPE_UID) { - *ae_tag = ARCHIVE_ENTRY_ACL_USER; - *ae_id = ugid; - *ae_name = archive_read_disk_uname(a, *ae_id); - } else if (idtype == ID_TYPE_GID) { - *ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - *ae_id = ugid; - *ae_name = archive_read_disk_gname(a, *ae_id); - } else - r = 1; - - acl_free(q); - return (r); -} - -/* - * Add trivial NFSv4 ACL entries from mode - */ -static void -add_trivial_nfs4_acl(struct archive_entry *entry) -{ - mode_t mode; - int i; - const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; - const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | - ARCHIVE_ENTRY_ACL_APPEND_DATA; - const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE; - const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | - ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | - ARCHIVE_ENTRY_ACL_READ_ACL | - ARCHIVE_ENTRY_ACL_SYNCHRONIZE; - const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | - ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | - ARCHIVE_ENTRY_ACL_WRITE_ACL | - ARCHIVE_ENTRY_ACL_WRITE_OWNER; - - struct { - const int type; - const int tag; - int permset; - } tacl_entry[] = { - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, - {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, - {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0}, - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset}, - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset}, - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset} - }; - - mode = archive_entry_mode(entry); - - /* Permissions for everyone@ */ - if (mode & 0004) - tacl_entry[5].permset |= rperm; - if (mode & 0002) - tacl_entry[5].permset |= wperm; - if (mode & 0001) - tacl_entry[5].permset |= eperm; - - /* Permissions for group@ */ - if (mode & 0040) - tacl_entry[4].permset |= rperm; - else if (mode & 0004) - tacl_entry[2].permset |= rperm; - if (mode & 0020) - tacl_entry[4].permset |= wperm; - else if (mode & 0002) - tacl_entry[2].permset |= wperm; - if (mode & 0010) - tacl_entry[4].permset |= eperm; - else if (mode & 0001) - tacl_entry[2].permset |= eperm; - - /* Permissions for owner@ */ - if (mode & 0400) { - tacl_entry[3].permset |= rperm; - if (!(mode & 0040) && (mode & 0004)) - tacl_entry[0].permset |= rperm; - } else if ((mode & 0040) || (mode & 0004)) - tacl_entry[1].permset |= rperm; - if (mode & 0200) { - tacl_entry[3].permset |= wperm; - if (!(mode & 0020) && (mode & 0002)) - tacl_entry[0].permset |= wperm; - } else if ((mode & 0020) || (mode & 0002)) - tacl_entry[1].permset |= wperm; - if (mode & 0100) { - tacl_entry[3].permset |= eperm; - if (!(mode & 0010) && (mode & 0001)) - tacl_entry[0].permset |= eperm; - } else if ((mode & 0010) || (mode & 0001)) - tacl_entry[1].permset |= eperm; - - for (i = 0; i < 6; i++) { - if (tacl_entry[i].permset != 0) { - archive_entry_acl_add_entry(entry, - tacl_entry[i].type, tacl_entry[i].permset, - tacl_entry[i].tag, -1, NULL); - } - } - - return; -} -#elif HAVE_SUN_ACL -/* - * Check if acl is trivial - * This is a FreeBSD acl_is_trivial_np() implementation for Solaris - */ -static int -sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4, - int is_dir, int *trivialp) -{ - int i, p; -#if HAVE_SUN_NFS4_ACL - const uint32_t rperm = ACE_READ_DATA; - const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA; - const uint32_t eperm = ACE_EXECUTE; - const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | - ACE_READ_ACL | ACE_SYNCHRONIZE; - const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES | - ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER; - - ace_t *ace; - ace_t tace[6]; -#endif - - if (aclp == NULL || trivialp == NULL) - return (-1); - - *trivialp = 0; - - /* - * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with - * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries, - * including mask. - */ - if (!is_nfs4) { - if (aclcnt == 4) - *trivialp = 1; - return (0); - } - -#if HAVE_SUN_NFS4_ACL - /* - * Continue with checking NFSv4 ACLs - * - * Create list of trivial ace's to be compared - */ - - /* owner@ allow pre */ - tace[0].a_flags = ACE_OWNER; - tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[0].a_access_mask = 0; - - /* owner@ deny */ - tace[1].a_flags = ACE_OWNER; - tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE; - tace[1].a_access_mask = 0; - - /* group@ deny */ - tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; - tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE; - tace[2].a_access_mask = 0; - - /* owner@ allow */ - tace[3].a_flags = ACE_OWNER; - tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[3].a_access_mask = ownset; - - /* group@ allow */ - tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; - tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[4].a_access_mask = pubset; - - /* everyone@ allow */ - tace[5].a_flags = ACE_EVERYONE; - tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[5].a_access_mask = pubset; - - /* Permissions for everyone@ */ - if (mode & 0004) - tace[5].a_access_mask |= rperm; - if (mode & 0002) - tace[5].a_access_mask |= wperm; - if (mode & 0001) - tace[5].a_access_mask |= eperm; - - /* Permissions for group@ */ - if (mode & 0040) - tace[4].a_access_mask |= rperm; - else if (mode & 0004) - tace[2].a_access_mask |= rperm; - if (mode & 0020) - tace[4].a_access_mask |= wperm; - else if (mode & 0002) - tace[2].a_access_mask |= wperm; - if (mode & 0010) - tace[4].a_access_mask |= eperm; - else if (mode & 0001) - tace[2].a_access_mask |= eperm; - - /* Permissions for owner@ */ - if (mode & 0400) { - tace[3].a_access_mask |= rperm; - if (!(mode & 0040) && (mode & 0004)) - tace[0].a_access_mask |= rperm; - } else if ((mode & 0040) || (mode & 0004)) - tace[1].a_access_mask |= rperm; - if (mode & 0200) { - tace[3].a_access_mask |= wperm; - if (!(mode & 0020) && (mode & 0002)) - tace[0].a_access_mask |= wperm; - } else if ((mode & 0020) || (mode & 0002)) - tace[1].a_access_mask |= wperm; - if (mode & 0100) { - tace[3].a_access_mask |= eperm; - if (!(mode & 0010) && (mode & 0001)) - tace[0].a_access_mask |= eperm; - } else if ((mode & 0010) || (mode & 0001)) - tace[1].a_access_mask |= eperm; - - /* Check if the acl count matches */ - p = 3; - for (i = 0; i < 3; i++) { - if (tace[i].a_access_mask != 0) - p++; - } - if (aclcnt != p) - return (0); - - p = 0; - for (i = 0; i < 6; i++) { - if (tace[i].a_access_mask != 0) { - ace = &((ace_t *)aclp)[p]; - /* - * Illumos added ACE_DELETE_CHILD to write perms for - * directories. We have to check against that, too. - */ - if (ace->a_flags != tace[i].a_flags || - ace->a_type != tace[i].a_type || - (ace->a_access_mask != tace[i].a_access_mask && - (!is_dir || (tace[i].a_access_mask & wperm) == 0 || - ace->a_access_mask != - (tace[i].a_access_mask | ACE_DELETE_CHILD)))) - return (0); - p++; - } - } - - *trivialp = 1; -#else /* !HAVE_SUN_NFS4_ACL */ - (void)aclp; /* UNUSED */ -#endif /* !HAVE_SUN_NFS4_ACL */ - return (0); -} -#endif /* HAVE_SUN_ACL */ - -#if HAVE_SUN_ACL -/* - * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL - */ -static int -translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, void *aclp, int aclcnt, - int default_entry_acl_type) -{ - int e, i; - int ae_id, ae_tag, ae_perm; - int entry_acl_type; - const char *ae_name; - aclent_t *aclent; -#if HAVE_SUN_NFS4_ACL - ace_t *ace; -#endif - - if (aclcnt <= 0) - return (ARCHIVE_OK); - - for (e = 0; e < aclcnt; e++) { - ae_name = NULL; - ae_tag = 0; - ae_perm = 0; - -#if HAVE_SUN_NFS4_ACL - if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - ace = &((ace_t *)aclp)[e]; - ae_id = ace->a_who; - - switch(ace->a_type) { - case ACE_ACCESS_ALLOWED_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; - break; - case ACE_ACCESS_DENIED_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; - break; - case ACE_SYSTEM_AUDIT_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; - break; - case ACE_SYSTEM_ALARM_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; - break; - default: - /* Unknown entry type, skip */ - continue; - } - - if ((ace->a_flags & ACE_OWNER) != 0) - ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - else if ((ace->a_flags & ACE_GROUP) != 0) - ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - else if ((ace->a_flags & ACE_EVERYONE) != 0) - ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; - else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) { - ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - ae_name = archive_read_disk_gname(&a->archive, - ae_id); - } else { - ae_tag = ARCHIVE_ENTRY_ACL_USER; - ae_name = archive_read_disk_uname(&a->archive, - ae_id); - } - - for (i = 0; i < (int)(sizeof(acl_inherit_map) / - sizeof(acl_inherit_map[0])); ++i) { - if ((ace->a_flags & - acl_inherit_map[i].platform_inherit) != 0) - ae_perm |= - acl_inherit_map[i].archive_inherit; - } - - for (i = 0; i < (int)(sizeof(acl_perm_map) / - sizeof(acl_perm_map[0])); ++i) { - if ((ace->a_access_mask & - acl_perm_map[i].platform_perm) != 0) - ae_perm |= - acl_perm_map[i].archive_perm; - } - } else -#endif /* HAVE_SUN_NFS4_ACL */ - if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { - aclent = &((aclent_t *)aclp)[e]; - if ((aclent->a_type & ACL_DEFAULT) != 0) - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; - else - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; - ae_id = aclent->a_id; - - switch(aclent->a_type) { - case DEF_USER: - case USER: - ae_name = archive_read_disk_uname(&a->archive, - ae_id); - ae_tag = ARCHIVE_ENTRY_ACL_USER; - break; - case DEF_GROUP: - case GROUP: - ae_name = archive_read_disk_gname(&a->archive, - ae_id); - ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - break; - case DEF_CLASS_OBJ: - case CLASS_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_MASK; - break; - case DEF_USER_OBJ: - case USER_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - break; - case DEF_GROUP_OBJ: - case GROUP_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - break; - case DEF_OTHER_OBJ: - case OTHER_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_OTHER; - break; - default: - /* Unknown tag type, skip */ - continue; - } - - if ((aclent->a_perm & 1) != 0) - ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; - if ((aclent->a_perm & 2) != 0) - ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; - if ((aclent->a_perm & 4) != 0) - ae_perm |= ARCHIVE_ENTRY_ACL_READ; - } else - return (ARCHIVE_WARN); - - archive_entry_acl_add_entry(entry, entry_acl_type, - ae_perm, ae_tag, ae_id, ae_name); - } - return (ARCHIVE_OK); -} -#else /* !HAVE_SUN_ACL */ -/* - * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and - * MacOS (NFSv4 only) 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) -{ - acl_tag_t acl_tag; -#if HAVE_FREEBSD_NFS4_ACL - acl_entry_type_t acl_type; - int brand; -#endif -#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL - acl_flagset_t acl_flagset; -#endif - acl_entry_t acl_entry; - acl_permset_t acl_permset; - int i, entry_acl_type; - int r, s, ae_id, ae_tag, ae_perm; -#if !HAVE_DARWIN_ACL - void *q; -#endif - const char *ae_name; - -#if HAVE_FREEBSD_NFS4_ACL - // 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); - } - -#if HAVE_DARWIN_ACL - while (s == 0) -#else /* FreeBSD, Linux */ - while (s == 1) -#endif - { - 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) { -#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ - 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 HAVE_FREEBSD_NFS4_ACL - case ACL_EVERYONE: - ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; - break; -#endif -#else /* HAVE_DARWIN_ACL */ - case ACL_EXTENDED_ALLOW: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; - r = translate_guid(&a->archive, acl_entry, &ae_id, - &ae_tag, &ae_name); - break; - case ACL_EXTENDED_DENY: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; - r = translate_guid(&a->archive, acl_entry, &ae_id, - &ae_tag, &ae_name); - break; -#endif /* HAVE_DARWIN_ACL */ - default: - /* Skip types that libarchive can't support. */ - s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); - continue; - } - -#if HAVE_DARWIN_ACL - /* Skip if translate_guid() above failed */ - if (r != 0) { - s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); - continue; - } -#endif - -#if !HAVE_DARWIN_ACL - // XXX acl_type maps to allow/deny/audit/YYYY bits - entry_acl_type = default_entry_acl_type; -#endif -#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL - if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { -#if HAVE_FREEBSD_NFS4_ACL - /* - * 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); - } -#endif /* HAVE_FREEBSD_NFS4_ACL */ - - /* - * 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 < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - r = acl_get_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit); - 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_inherit_map[i].archive_inherit; - } - } -#endif /* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL */ - - if (acl_get_permset(acl_entry, &acl_permset) != 0) { - archive_set_error(&a->archive, errno, - "Failed to get ACL permission set"); - return (ARCHIVE_WARN); - } - for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { - /* - * acl_get_perm() is spelled differently on different - * platforms; see above. - */ - r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_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 |= acl_perm_map[i].archive_perm; - } - -#if HAVE_DARWIN_ACL && !HAVE_DECL_ACL_SYNCHRONIZE - /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */ - ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; -#endif - - 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 !HAVE_DARWIN_ACL - if (s == -1) { - archive_set_error(&a->archive, errno, - "Failed to get next ACL entry"); - return (ARCHIVE_WARN); - } -#endif - } - return (ARCHIVE_OK); -} -#endif /* !HAVE_SUN_ACL */ -#else /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ -static int -setup_acls(struct archive_read_disk *a, - struct archive_entry *entry, int *fd) -{ - (void)a; /* UNUSED */ - (void)entry; /* UNUSED */ - (void)fd; /* UNUSED */ - return (ARCHIVE_OK); -} -#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ - #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \ HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \ (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA) @@ -1596,6 +475,18 @@ setup_xattr(struct archive_read_disk *a, return (ARCHIVE_OK); } +#ifndef ARCHIVE_ACL_SUPPORT +static int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + (void)a; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)fd; /* UNUSED */ + return (ARCHIVE_OK); +} +#endif + static int setup_xattrs(struct archive_read_disk *a, struct archive_entry *entry, int *fd) diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h index b5a8328b..d434d397 100644 --- a/libarchive/archive_read_disk_private.h +++ b/libarchive/archive_read_disk_private.h @@ -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,10 @@ struct archive_read_disk { void *excluded_cb_data; }; +#if ARCHIVE_ACL_SUPPORT +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *, + struct archive_entry *, int *); +#endif + #endif diff --git a/libarchive/archive_write_disk_acl.c b/libarchive/archive_write_disk_acl.c deleted file mode 100644 index 49792749..00000000 --- a/libarchive/archive_write_disk_acl.c +++ /dev/null @@ -1,695 +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_uid_to_uuid(ae_uid, 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_gid_to_uuid(ae_gid, 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 */ diff --git a/libarchive/archive_write_disk_acl_darwin.c b/libarchive/archive_write_disk_acl_darwin.c new file mode 100644 index 00000000..22375c76 --- /dev/null +++ b/libarchive/archive_write_disk_acl_darwin.c @@ -0,0 +1,232 @@ +/*- + * 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 + * 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" + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_MEMBERSHIP_H +#include <membership.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) +{ + acl_t acl; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + acl_flagset_t acl_flagset; + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + uuid_t ae_uuid; + 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 (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + 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) { + /* + * 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; + + 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_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; + } + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + 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; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if (ae_permset & acl_nfs4_perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + acl_nfs4_perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + + /* + * 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; + } + } + } + } + + if (fd >= 0) { + if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 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; + } + } + } else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) { + 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) +{ + int ret = ARCHIVE_OK; + + 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"); + } + return (ret); +} diff --git a/libarchive/archive_write_disk_acl_freebsd.c b/libarchive/archive_write_disk_acl_freebsd.c new file mode 100644 index 00000000..d6b87671 --- /dev/null +++ b/libarchive/archive_write_disk_acl_freebsd.c @@ -0,0 +1,319 @@ +/*- + * 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) +{ + int ret = ARCHIVE_OK; + + 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); +} diff --git a/libarchive/archive_write_disk_acl_linux.c b/libarchive/archive_write_disk_acl_linux.c new file mode 100644 index 00000000..15af1a1b --- /dev/null +++ b/libarchive/archive_write_disk_acl_linux.c @@ -0,0 +1,204 @@ +/*- + * 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" + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#if HAVE_ACL_LIBACL_H && HAVE_LIBACL +#include <acl/libacl.h> +#endif +#ifdef HAVE_SYS_ACL_H +#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; + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + 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; + 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; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + 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; + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + if (ae_permset & acl_posix_perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + acl_posix_perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + + } + + if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + if (acl_set_fd(fd, acl) == 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; + } + } + } else if (acl_set_file(name, acl_type, acl) != 0) { + 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) +{ + int ret = ARCHIVE_OK; + + 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"); + } + return (ret); +} diff --git a/libarchive/archive_write_disk_acl_sunos.c b/libarchive/archive_write_disk_acl_sunos.c new file mode 100644 index 00000000..e8002396 --- /dev/null +++ b/libarchive/archive_write_disk_acl_sunos.c @@ -0,0 +1,327 @@ +/*- + * 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 + * 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" + +#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) +{ + aclent_t *aclent; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace_t *ace; +#endif + int cmd, e, r; + void *aclp; + 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_POSIX1E: + cmd = SETACL; + aclp = malloc(entries * sizeof(aclent_t)); + break; +#if ARCHIVE_ACL_SUNOS_NFS4 + 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, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + if (aclp == NULL) { + archive_set_error(a, errno, + "Can't allocate memory for acl buffer"); + return (ARCHIVE_FAILED); + } + + e = 0; + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + aclent = NULL; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace = NULL; +#endif + if (cmd == SETACL) { + aclent = &((aclent_t *)aclp)[e]; + aclent->a_id = -1; + aclent->a_type = 0; + aclent->a_perm = 0; + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { /* cmd == ACE_SETACL */ + ace = &((ace_t *)aclp)[e]; + ace->a_who = -1; + ace->a_access_mask = 0; + ace->a_flags = 0; + } +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + + switch (ae_tag) { + 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 ARCHIVE_ACL_SUNOS_NFS4 + 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 ARCHIVE_ACL_SUNOS_NFS4 + 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 ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_flags |= ACE_OWNER; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (aclent != NULL) + aclent->a_type |= GROUP_OBJ; +#if ARCHIVE_ACL_SUNOS_NFS4 + 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 ARCHIVE_ACL_SUNOS_NFS4 + case ARCHIVE_ENTRY_ACL_EVERYONE: + if (ace != NULL) + ace->a_flags |= ACE_EVERYONE; + break; +#endif + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + r = 0; + switch (ae_type) { +#if ARCHIVE_ACL_SUNOS_NFS4 + 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; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (r != 0) { + errno = EINVAL; + archive_set_error(a, errno, + "Failed to set ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + +#if ARCHIVE_ACL_SUNOS_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_SUNOS_NFS4 + } +#endif + for (i = 0; i < perm_map_size; ++i) { + if (ae_permset & perm_map[i].a_perm) { +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == + ARCHIVE_ENTRY_ACL_TYPE_NFS4) + ace->a_access_mask |= + perm_map[i].p_perm; + else +#endif + aclent->a_perm |= perm_map[i].p_perm; + } + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & acl_nfs4_flag_map[i].a_perm) { + ace->a_flags |= + acl_nfs4_flag_map[i].p_perm; + } + } + } +#endif + e++; + } + + /* Try restoring the ACL through 'fd' if we can. */ + if (fd >= 0) { + if (facl(fd, cmd, entries, aclp) == 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; + } + } + } else if (acl(name, cmd, entries, aclp) != 0) { + 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: + free(aclp); + return (ret); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl) +{ + int ret = ARCHIVE_OK; + + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* Solaris writes POSIX.1e access and default ACLs together */ + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e"); + + /* Simultaneous POSIX.1e and NFSv4 is not supported */ + return (ret); + } +#if ARCHIVE_ACL_SUNOS_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); +} diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index bf58b6d0..6c0dd19b 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -369,6 +369,10 @@ static ssize_t hfs_write_data_block(struct archive_write_disk *, static int fixup_appledouble(struct archive_write_disk *, const char *); static int older(struct stat *, struct archive_entry *); static int restore_entry(struct archive_write_disk *); +#ifndef ARCHIVE_ACL_SUPPORT +static int archive_write_disk_set_acls(struct archive *, int, const char *, + struct archive_acl *); +#endif static int set_mac_metadata(struct archive_write_disk *, const char *, const void *, size_t); static int set_xattrs(struct archive_write_disk *); @@ -425,6 +429,19 @@ lazy_stat(struct archive_write_disk *a) return (ARCHIVE_WARN); } +#ifndef ARCHIVE_ACL_SUPPORT +static 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); +} +#endif + static struct archive_vtable * archive_write_disk_vtable(void) { @@ -1703,7 +1720,7 @@ _archive_write_disk_finish_entry(struct archive *_a) */ if (a->todo & TODO_ACLS) { int r2; -#ifdef HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN /* * On Mac OS, platform ACLs are stored also in mac_metadata by * the operating system. If mac_metadata is present it takes @@ -1719,7 +1736,7 @@ _archive_write_disk_finish_entry(struct archive *_a) archive_entry_pathname(a->entry), archive_entry_acl(a->entry)); if (r2 < ret) ret = r2; -#ifdef HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN } #endif } @@ -2293,7 +2310,7 @@ _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 ARCHIVE_ACL_DARWIN if ((p->fixup & TODO_MAC_METADATA) == 0 || p->mac_metadata == NULL || p->mac_metadata_size == 0) diff --git a/libarchive/archive_write_disk_private.h b/libarchive/archive_write_disk_private.h index d84e7e1c..c5814b4b 100644 --- a/libarchive/archive_write_disk_private.h +++ b/libarchive/archive_write_disk_private.h @@ -33,11 +33,14 @@ #ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED #define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED +#include "archive_platform_acl.h" #include "archive_acl_private.h" struct archive_write_disk; +#if ARCHIVE_ACL_SUPPORT int archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *); +#endif #endif diff --git a/libarchive/test/test_acl_platform_nfs4.c b/libarchive/test/test_acl_platform_nfs4.c index c8854082..b8dce122 100644 --- a/libarchive/test/test_acl_platform_nfs4.c +++ b/libarchive/test/test_acl_platform_nfs4.c @@ -26,15 +26,13 @@ #include "test.h" __FBSDID("$FreeBSD$"); -#if HAVE_POSIX_ACL || HAVE_NFS4_ACL +#if ARCHIVE_ACL_NFS4 #define _ACL_PRIVATE #include <sys/acl.h> -#if HAVE_DARWIN_ACL +#if HAVE_MEMBERSHIP_H #include <membership.h> #endif -#endif -#if HAVE_NFS4_ACL struct myacl_t { int type; int permset; @@ -44,7 +42,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 +89,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 +132,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 +178,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 +209,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 +256,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,14 +273,14 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end) } static int -#ifdef HAVE_SUN_NFS4_ACL +#ifdef ARCHIVE_ACL_SUNOS_NFS4 acl_permset_to_bitmap(uint32_t a_access_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 */ +#ifdef ARCHIVE_ACL_SUNOS_NFS4 /* 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}, @@ -296,7 +298,7 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps) {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 */ +#elif ARCHIVE_ACL_DARWIN /* 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}, @@ -341,7 +343,7 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps) int i, permset = 0; for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i) -#if HAVE_SUN_NFS4_ACL +#if ARCHIVE_ACL_SUNOS_NFS4 if (a_access_mask & perms[i].machine) #else if (acl_get_perm_np(opaque_ps, perms[i].machine)) @@ -351,14 +353,14 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps) } static int -#if HAVE_SUN_NFS4_ACL +#if ARCHIVE_ACL_SUNOS_NFS4 acl_flagset_to_bitmap(uint16_t a_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 */ +#if ARCHIVE_ACL_SUNOS_NFS4 /* 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}, @@ -368,25 +370,26 @@ acl_flagset_to_bitmap(acl_flagset_t opaque_fs) #ifdef ACE_INHERITED_ACE {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED} #endif -#elif HAVE_DARWIN_ACL /* MacOS NFSv4 ACL inheritance flags */ +#elif ARCHIVE_ACL_DARWIN /* 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} #else /* FreeBSD 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_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_FAILED_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS}, {ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_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 ARCHIVE_ACL_SUNOS_NFS4 if (a_flags & flags[i].machine) #else if (acl_get_flag_np(opaque_fs, flags[i].machine)) @@ -395,46 +398,17 @@ acl_flagset_to_bitmap(acl_flagset_t opaque_fs) 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 +450,29 @@ 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_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 +509,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,13 +584,13 @@ 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, #else @@ -582,19 +601,24 @@ 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; #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 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,15 +630,13 @@ 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 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]; #else /* After the first time... */ @@ -708,7 +730,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 +738,25 @@ 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 */ +#else /* !ARCHIVE_ACL_SUNOS_NFS4 */ acl_t acl; #endif @@ -790,12 +812,12 @@ 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)); assert(aclp != 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); @@ -803,7 +825,7 @@ DEFINE_TEST(test_acl_platform_nfs4) failure("acl_get_file(): errno = %d (%s)", 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; @@ -818,12 +840,12 @@ 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)); assert(aclp != 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); @@ -832,7 +854,7 @@ DEFINE_TEST(test_acl_platform_nfs4) 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; @@ -845,12 +867,12 @@ 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)); assert(aclp != 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); @@ -858,7 +880,7 @@ DEFINE_TEST(test_acl_platform_nfs4) failure("acl_get_file(): errno = %d (%s)", 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; @@ -890,5 +912,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 */ } diff --git a/libarchive/test/test_acl_platform_posix1e.c b/libarchive/test/test_acl_platform_posix1e.c index 0224a57f..801a7acf 100644 --- a/libarchive/test/test_acl_platform_posix1e.c +++ b/libarchive/test/test_acl_platform_posix1e.c @@ -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 +{ + + if (myacl->permset != acl_entry_get_perm(aclent)) + return (0); + + switch (aclent->a_type) { + case DEF_USER_OBJ: + case USER_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0); + break; + if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) + return (0); + if ((uid_t)myacl->qual != aclent->a_id) + return (0); + break; + case DEF_GROUP_OBJ: + case GROUP_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0); + break; + case DEF_GROUP: + case GROUP: + if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) + return (0); + if ((gid_t)myacl->qual != aclent->a_id) + return (0); + break; + case DEF_CLASS_OBJ: + case CLASS_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0); + break; + case DEF_OTHER_OBJ: + case OTHER_OBJ: + if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0); + break; + } + return (1); +} + +#else /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */ +static int 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 - case DEF_USER_OBJ: - case USER_OBJ: -#else + switch (tag_type) { 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); } +#endif static void -#if HAVE_SUN_ACL -compare_acls(void *aclp, int aclcnt, struct archive_test_acl_t *myacls, int n) +compare_acls( +#if ARCHIVE_ACL_SUNOS + void *aclp, int aclcnt, #else -compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n) + 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 */ } |