From 46ab065716a6ecbe96471bebf59ab452a0edcdac Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Thu, 2 Mar 2017 21:13:25 +0000 Subject: [PATCH] Update vendor/libarchive to git a15c7f7b496ba4cefbcaf6f8ac637db4f3009a58 Documentation, style, test suite changes and typo fixes. New bsdtar tests for --acls and --fflags options. --- CMakeLists.txt | 48 +- Makefile.am | 4 +- build/cmake/config.h.in | 52 +- build/version | 2 +- cat/test/CMakeLists.txt | 5 + configure.ac | 33 +- cpio/cpio.c | 10 +- cpio/test/CMakeLists.txt | 5 + libarchive/archive.h | 4 +- libarchive/archive_check_magic.c | 2 +- libarchive/archive_entry.c | 20 +- libarchive/archive_entry.h | 2 +- libarchive/archive_entry_acl.3 | 2 +- libarchive/archive_entry_paths.3 | 12 +- libarchive/archive_entry_perms.3 | 4 +- libarchive/archive_platform.h | 18 +- libarchive/archive_read_disk.3 | 22 +- .../archive_read_disk_entry_from_file.c | 286 ++++++++--- libarchive/archive_read_format.3 | 6 +- libarchive/archive_read_open.3 | 2 +- libarchive/archive_read_support_format_warc.c | 9 +- libarchive/archive_write_data.3 | 24 +- libarchive/archive_write_disk.3 | 79 +-- libarchive/archive_write_disk_acl.c | 181 ++++--- libarchive/archive_write_disk_posix.c | 20 +- libarchive/archive_write_finish_entry.3 | 5 +- libarchive/archive_write_format.3 | 1 - libarchive/test/test_acl_platform_nfs4.c | 177 +++---- libarchive/test/test_acl_platform_posix1e.c | 179 +++---- .../test_read_disk_directory_traversals.c | 6 +- tar/bsdtar.1 | 23 +- tar/bsdtar.c | 4 +- tar/bsdtar.h | 6 +- tar/test/CMakeLists.txt | 7 + tar/test/test_option_acls.c | 471 ++++++++++++++++++ tar/test/test_option_fflags.c | 74 +++ tar/test/test_option_nodump.c | 2 +- test_utils/test_common.h | 51 +- test_utils/test_main.c | 353 ++++++++++++- 39 files changed, 1586 insertions(+), 625 deletions(-) create mode 100644 tar/test/test_option_acls.c create mode 100644 tar/test/test_option_fflags.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ca9d8fdc066..bddf30c71828 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ endif() # RelWithDebInfo : Release build with Debug Info # MinSizeRel : Release Min Size build IF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE) + SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) # Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the # value type is "UNINITIALIZED". @@ -579,6 +579,7 @@ int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS) LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H) LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H) +LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H) LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H) LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H) LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H) @@ -1618,29 +1619,29 @@ IF(ENABLE_ACL) CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP) CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP) CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP) - CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4) + CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_DECL_ACL_TYPE_NFS4) # MacOS has an acl.h that isn't POSIX. It can be detected by # checking for ACL_USER - CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER) + CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_DECL_ACL_USER) CHECK_C_SOURCE_COMPILES("#include #include -int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED) +int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_DECL_ACL_TYPE_EXTENDED) + CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE) # Solaris and derivates ACLs - CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC) - IF(HAVE_LIBSEC) - SET(CMAKE_REQUIRED_LIBRARIES "sec") - FIND_LIBRARY(SEC_LIBRARY NAMES sec) - LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY}) - ENDIF(HAVE_LIBSEC) - # CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T) CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T) - CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET) - CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET) - CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET) - CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET) + CHECK_FUNCTION_EXISTS(acl HAVE_ACL) + CHECK_FUNCTION_EXISTS(facl HAVE_FACL) + CHECK_SYMBOL_EXISTS(GETACL "${INCLUDES}" HAVE_DECL_GETACL) + CHECK_SYMBOL_EXISTS(GETACLCNT "${INCLUDES}" HAVE_DECL_GETACLCNT) + CHECK_SYMBOL_EXISTS(SETACL "${INCLUDES}" HAVE_DECL_SETACL) + CHECK_SYMBOL_EXISTS(ACE_GETACL "${INCLUDES}" HAVE_DECL_ACE_GETACL) + CHECK_SYMBOL_EXISTS(ACE_GETACLCNT "${INCLUDES}" HAVE_DECL_ACE_GETACLCNT) + CHECK_SYMBOL_EXISTS(ACE_SETACL "${INCLUDES}" HAVE_DECL_ACE_SETACL) ELSE(ENABLE_ACL) # If someone runs cmake, then disables ACL support, we need # to forcibly override the cached values for these. @@ -1655,15 +1656,20 @@ ELSE(ENABLE_ACL) SET(HAVE_ACL_SET_FD FALSE) SET(HAVE_ACL_SET_FD_NP FALSE) SET(HAVE_ACL_SET_FILE FALSE) - SET(HAVE_ACL_TYPE_NFS4 FALSE) - SET(HAVE_ACL_USER FALSE) SET(HAVE_ACL_TYPE_EXTENDED FALSE) - SET(HAVE_ACL_GET FALSE) SET(HAVE_ACLENT_T FALSE) SET(HAVE_ACE_T FALSE) - SET(HAVE_FACL_GET FALSE) - SET(HAVE_ACL_SET FALSE) - SET(HAVE_FACL_SET FALSE) + SET(HAVE_DECL_ACL_TYPE_NFS4 FALSE) + SET(HAVE_DECL_ACL_USER FALSE) + SET(HAVE_DECL_ACL_SYNCHRONIZE FALSE) + SET(HAVE_DECL_GETACL FALSE) + SET(HAVE_DECL_GETACLCNT FALSE) + SET(HAVE_DECL_SETACL FALSE) + SET(HAVE_DECL_ACE_GETACL FALSE) + SET(HAVE_DECL_ACE_GETACLCNT FALSE) + SET(HAVE_DECL_ACE_SETACL FALSE) + SET(HAVE_ACL FALSE) + SET(HAVE_FACL FALSE) ENDIF(ENABLE_ACL) # diff --git a/Makefile.am b/Makefile.am index f22a918729ae..b5a41f980fbd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $ DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio # The next line is commented out by default in shipping libarchive releases. # It is uncommented by default in trunk. -# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g +DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g AM_CFLAGS=$(DEV_CFLAGS) PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@ AM_CPPFLAGS=$(PLATFORMCPPFLAGS) @@ -951,10 +951,12 @@ bsdtar_test_SOURCES= \ tar/test/test_option_T_upper.c \ tar/test/test_option_U_upper.c \ tar/test/test_option_X_upper.c \ + tar/test/test_option_acls.c \ tar/test/test_option_a.c \ tar/test/test_option_b.c \ tar/test/test_option_b64encode.c \ tar/test/test_option_exclude.c \ + tar/test/test_option_fflags.c \ tar/test/test_option_gid_gname.c \ tar/test/test_option_grzip.c \ tar/test/test_option_j.c \ diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 923a78e51738..8c18edf8a079 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -326,15 +326,6 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `acl_set_file' function. */ #cmakedefine HAVE_ACL_SET_FILE 1 -/* True for FreeBSD with NFSv4 ACL support */ -#cmakedefine HAVE_ACL_TYPE_NFS4 1 - -/* True for MacOS ACL support */ -#cmakedefine HAVE_ACL_TYPE_EXTENDED 1 - -/* True for systems with POSIX ACL support */ -#cmakedefine HAVE_ACL_USER 1 - /* Define to 1 if you have the `arc4random_buf' function. */ #cmakedefine HAVE_ARC4RANDOM_BUF 1 @@ -371,6 +362,34 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `cygwin_conv_path' function. */ #cmakedefine HAVE_CYGWIN_CONV_PATH 1 +/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_GETACL 1 + +/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_GETACLCNT 1 + +/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_SETACL 1 + +/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_ACL_SYNCHRONIZE 1 + +/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_ACL_TYPE_EXTENDED 1 + +/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACL_TYPE_NFS4 1 + +/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACL_USER 1 + /* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you don't. */ #cmakedefine HAVE_DECL_INT32_MAX 1 @@ -395,6 +414,10 @@ typedef uint64_t uintmax_t; don't. */ #cmakedefine HAVE_DECL_INTMAX_MIN 1 +/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't. + */ +#cmakedefine HAVE_DECL_SETACL 1 + /* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you don't. */ #cmakedefine HAVE_DECL_SIZE_MAX 1 @@ -468,6 +491,14 @@ typedef uint64_t uintmax_t; /* Define to 1 if EXTATTR_NAMESPACE_USER is defined in sys/extattr.h. */ #cmakedefine HAVE_DECL_EXTATTR_NAMESPACE_USER 1 +/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't. + */ +#cmakedefine HAVE_DECL_GETACL 1 + +/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_GETACLCNT 1 + /* Define to 1 if you have the `fchdir' function. */ #cmakedefine HAVE_FCHDIR 1 @@ -742,6 +773,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `mbrtowc' function. */ #cmakedefine HAVE_MBRTOWC 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMBERSHIP_H 1 + /* Define to 1 if you have the `memmove' function. */ #cmakedefine HAVE_MEMMOVE 1 diff --git a/build/version b/build/version index ef8345726c8a..6d36e9c14cdd 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3003001 +3003002dev diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt index 7f1ce5e77d13..0623cc367227 100644 --- a/cat/test/CMakeLists.txt +++ b/cat/test/CMakeLists.txt @@ -29,6 +29,11 @@ IF(ENABLE_CAT AND ENABLE_TEST) # Register target # ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES}) + IF(ENABLE_ACL) + IF(HAVE_LIBACL) + TARGET_LINK_LIBRARIES(bsdcat_test ${ACL_LIBRARY}) + ENDIF(HAVE_LIBACL) + ENDIF(ENABLE_ACL) SET_PROPERTY(TARGET bsdcat_test PROPERTY COMPILE_DEFINITIONS LIST_H) # diff --git a/configure.ac b/configure.ac index 3a8ac6a853b5..0592279d96a3 100644 --- a/configure.ac +++ b/configure.ac @@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front. dnl In particular, this allows the version macro to be used in AC_INIT dnl These first two version numbers are updated automatically on each release. -m4_define([LIBARCHIVE_VERSION_S],[3.3.1]) -m4_define([LIBARCHIVE_VERSION_N],[3003001]) +m4_define([LIBARCHIVE_VERSION_S],[3.3.2dev]) +m4_define([LIBARCHIVE_VERSION_N],[3003002]) dnl bsdtar and bsdcpio versioning tracks libarchive m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) @@ -699,6 +699,7 @@ AC_ARG_ENABLE([acl], if test "x$enable_acl" != "xno"; then AC_CHECK_HEADERS([acl/libacl.h]) AC_CHECK_HEADERS([sys/acl.h]) + AC_CHECK_HEADERS([membership.h]) AC_CHECK_LIB([acl],[acl_get_file]) AC_CHECK_FUNCS([acl_create_entry acl_get_fd_np]) AC_CHECK_FUNCS([acl_init acl_set_fd acl_set_fd_np acl_set_file]) @@ -737,31 +738,23 @@ if test "x$enable_acl" != "xno"; then #endif ]) - # Check for ACL_TYPE_NFS4 - AC_CHECK_DECL([ACL_TYPE_NFS4], - [AC_DEFINE(HAVE_ACL_TYPE_NFS4, 1, [True for FreeBSD with NFSv4 ACL support])], - [], - [#include ]) + # FreeBSD and POSIX + # MacOS has no ACL_USER in acl.h + AC_CHECK_DECLS([ACL_TYPE_NFS4, ACL_USER], + [], [], + [#include + #include ]) - # MacOS has an acl.h that isn't POSIX. It can be detected by - # checking for ACL_USER - AC_CHECK_DECL([ACL_USER], - [AC_DEFINE(HAVE_ACL_USER, 1, [True for systems with POSIX ACL support])], - [], - [#include ]) - - # MacOS has ACL_TYPE_EXTENDED instead - AC_CHECK_DECL([ACL_TYPE_EXTENDED], - [AC_DEFINE(HAVE_ACL_TYPE_EXTENDED, 1, [True for MacOS ACL support])], - [], + # FreeBSD and MacOS ACL support + AC_CHECK_DECLS([ACL_TYPE_EXTENDED, ACL_SYNCHRONIZE], [], [], [#include #include ]) # Solaris and derivates ACLs - AC_CHECK_LIB([sec], [acl_get]) AC_CHECK_TYPES([aclent_t], [], [], [[#include ]]) AC_CHECK_TYPES([ace_t], [], [], [[#include ]]) - AC_CHECK_FUNCS(acl_get facl_get acl_set facl_set) + AC_CHECK_FUNCS(acl facl) + AC_CHECK_DECLS([GETACL, SETACL, GETACLCNT, ACE_GETACL, ACE_SETACL, ACE_GETACLCNT], [], [], [#include ]) fi # Additional requirements diff --git a/cpio/cpio.c b/cpio/cpio.c index 6c20ee68322e..d7bb9c469f73 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -108,22 +108,22 @@ static int entry_to_archive(struct cpio *, struct archive_entry *); static int file_to_archive(struct cpio *, const char *); static void free_cache(struct name_cache *cache); static void list_item_verbose(struct cpio *, struct archive_entry *); -static void long_help(void); +static void long_help(void) __LA_DEAD; static const char *lookup_gname(struct cpio *, gid_t gid); static int lookup_gname_helper(struct cpio *, const char **name, id_t gid); static const char *lookup_uname(struct cpio *, uid_t uid); static int lookup_uname_helper(struct cpio *, const char **name, id_t uid); -static void mode_in(struct cpio *); -static void mode_list(struct cpio *); +static void mode_in(struct cpio *) __LA_DEAD; +static void mode_list(struct cpio *) __LA_DEAD; static void mode_out(struct cpio *); static void mode_pass(struct cpio *, const char *); static const char *remove_leading_slash(const char *); static int restore_time(struct cpio *, struct archive_entry *, const char *, int fd); -static void usage(void); -static void version(void); +static void usage(void) __LA_DEAD; +static void version(void) __LA_DEAD; static const char * passphrase_callback(struct archive *, void *); static void passphrase_free(char *); diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt index ec9509be98fa..cc5fe0117db3 100644 --- a/cpio/test/CMakeLists.txt +++ b/cpio/test/CMakeLists.txt @@ -62,6 +62,11 @@ IF(ENABLE_CPIO AND ENABLE_TEST) # Register target # ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES}) + IF(ENABLE_ACL) + IF(HAVE_LIBACL) + TARGET_LINK_LIBRARIES(bsdcpio_test ${ACL_LIBRARY}) + ENDIF(HAVE_LIBACL) + ENDIF(ENABLE_ACL) SET_PROPERTY(TARGET bsdcpio_test PROPERTY COMPILE_DEFINITIONS LIST_H) # diff --git a/libarchive/archive.h b/libarchive/archive.h index d400735a272a..d6913f35fc0c 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -36,7 +36,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3003001 +#define ARCHIVE_VERSION_NUMBER 3003002 #include #include /* for wchar_t */ @@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.3.1" +#define ARCHIVE_VERSION_ONLY_STRING "3.3.2dev" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/libarchive/archive_check_magic.c b/libarchive/archive_check_magic.c index c695e582a242..288ce2338550 100644 --- a/libarchive/archive_check_magic.c +++ b/libarchive/archive_check_magic.c @@ -62,7 +62,7 @@ errmsg(const char *m) } } -static void +static __LA_DEAD void diediedie(void) { #if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index 10eff11b287f..e268194143dd 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -401,7 +401,7 @@ archive_entry_fflags_text(struct archive_entry *entry) return (NULL); } -int64_t +la_int64_t archive_entry_gid(struct archive_entry *entry) { return (entry->ae_stat.aest_gid); @@ -502,7 +502,7 @@ _archive_entry_hardlink_l(struct archive_entry *entry, return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc)); } -int64_t +la_int64_t archive_entry_ino(struct archive_entry *entry) { return (entry->ae_stat.aest_ino); @@ -514,7 +514,7 @@ archive_entry_ino_is_set(struct archive_entry *entry) return (entry->ae_set & AE_SET_INO); } -int64_t +la_int64_t archive_entry_ino64(struct archive_entry *entry) { return (entry->ae_stat.aest_ino); @@ -627,7 +627,7 @@ archive_entry_rdevminor(struct archive_entry *entry) return minor(entry->ae_stat.aest_rdev); } -int64_t +la_int64_t archive_entry_size(struct archive_entry *entry) { return (entry->ae_stat.aest_size); @@ -715,7 +715,7 @@ _archive_entry_symlink_l(struct archive_entry *entry, return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc)); } -int64_t +la_int64_t archive_entry_uid(struct archive_entry *entry) { return (entry->ae_stat.aest_uid); @@ -819,7 +819,7 @@ archive_entry_copy_fflags_text_w(struct archive_entry *entry, } void -archive_entry_set_gid(struct archive_entry *entry, int64_t g) +archive_entry_set_gid(struct archive_entry *entry, la_int64_t g) { entry->stat_valid = 0; entry->ae_stat.aest_gid = g; @@ -868,7 +868,7 @@ _archive_entry_copy_gname_l(struct archive_entry *entry, } void -archive_entry_set_ino(struct archive_entry *entry, int64_t ino) +archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino) { entry->stat_valid = 0; entry->ae_set |= AE_SET_INO; @@ -876,7 +876,7 @@ archive_entry_set_ino(struct archive_entry *entry, int64_t ino) } void -archive_entry_set_ino64(struct archive_entry *entry, int64_t ino) +archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino) { entry->stat_valid = 0; entry->ae_set |= AE_SET_INO; @@ -1209,7 +1209,7 @@ archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) } void -archive_entry_set_size(struct archive_entry *entry, int64_t s) +archive_entry_set_size(struct archive_entry *entry, la_int64_t s) { entry->stat_valid = 0; entry->ae_stat.aest_size = s; @@ -1306,7 +1306,7 @@ _archive_entry_copy_symlink_l(struct archive_entry *entry, } void -archive_entry_set_uid(struct archive_entry *entry, int64_t u) +archive_entry_set_uid(struct archive_entry *entry, la_int64_t u) { entry->stat_valid = 0; entry->ae_stat.aest_uid = u; diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 7645f0cf6011..bcc2962b983f 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -30,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3003001 +#define ARCHIVE_VERSION_NUMBER 3003002 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive/archive_entry_acl.3 b/libarchive/archive_entry_acl.3 index c5115f7274d3..7ede7b76bc15 100644 --- a/libarchive/archive_entry_acl.3 +++ b/libarchive/archive_entry_acl.3 @@ -32,7 +32,7 @@ .Nm archive_entry_acl_clear , .Nm archive_entry_acl_count , .Nm archive_entry_acl_from_text , -.Nm archive_entry_acl_from_text_w, +.Nm archive_entry_acl_from_text_w , .Nm archive_entry_acl_next , .Nm archive_entry_acl_next_w , .Nm archive_entry_acl_reset , diff --git a/libarchive/archive_entry_paths.3 b/libarchive/archive_entry_paths.3 index fd22cf7e20c1..f647212a98be 100644 --- a/libarchive/archive_entry_paths.3 +++ b/libarchive/archive_entry_paths.3 @@ -31,25 +31,25 @@ .Nm archive_entry_set_hardlink , .Nm archive_entry_copy_hardlink , .Nm archive_entry_copy_hardlink_w , -.Nm archve_entry_update_hardlink_utf8 , +.Nm archive_entry_update_hardlink_utf8 , .Nm archive_entry_set_link , .Nm archive_entry_copy_link , .Nm archive_entry_copy_link_w , -.Nm archve_entry_update_link_utf8 , +.Nm archive_entry_update_link_utf8 , .Nm archive_entry_pathname , .Nm archive_entry_pathname_w , .Nm archive_entry_set_pathname , .Nm archive_entry_copy_pathname , .Nm archive_entry_copy_pathname_w , -.Nm archve_entry_update_pathname_utf8 , +.Nm archive_entry_update_pathname_utf8 , .Nm archive_entry_sourcepath , .Nm archive_entry_copy_sourcepath , -.Nm archive_entry_symlink, -.Nm archive_entry_symlink_w, +.Nm archive_entry_symlink , +.Nm archive_entry_symlink_w , .Nm archive_entry_set_symlink , .Nm archive_entry_copy_symlink , .Nm archive_entry_copy_symlink_w , -.Nm archve_entry_update_symlink_utf8 +.Nm archive_entry_update_symlink_utf8 .Nd functions for manipulating path names in archive entry descriptions .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) diff --git a/libarchive/archive_entry_perms.3 b/libarchive/archive_entry_perms.3 index 340c5ea72486..aae3648bb210 100644 --- a/libarchive/archive_entry_perms.3 +++ b/libarchive/archive_entry_perms.3 @@ -34,8 +34,8 @@ .Nm archive_entry_perm , .Nm archive_entry_set_perm , .Nm archive_entry_strmode , -.Nm archive_entry_uname -.Nm archive_entry_uname_w +.Nm archive_entry_uname , +.Nm archive_entry_uname_w , .Nm archive_entry_set_uname , .Nm archive_entry_copy_uname , .Nm archive_entry_copy_uname_w , diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h index c9a96020162e..01d6a70d10f8 100644 --- a/libarchive/archive_platform.h +++ b/libarchive/archive_platform.h @@ -148,23 +148,31 @@ * 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_ACL_USER +#if HAVE_DECL_ACL_USER #define HAVE_POSIX_ACL 1 -#elif HAVE_ACL_TYPE_EXTENDED +#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 , acl_get(), facl_get(), acl_set(), + * If this platform has , 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_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T +#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_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL +#if HAVE_FREEBSD_NFS4_ACL || HAVE_SUN_NFS4_ACL || HAVE_DARWIN_ACL #define HAVE_NFS4_ACL 1 #endif diff --git a/libarchive/archive_read_disk.3 b/libarchive/archive_read_disk.3 index 2a5c1305ebdf..55e4bbbd87f3 100644 --- a/libarchive/archive_read_disk.3 +++ b/libarchive/archive_read_disk.3 @@ -37,10 +37,7 @@ .Nm archive_read_disk_uname , .Nm archive_read_disk_set_uname_lookup , .Nm archive_read_disk_set_gname_lookup , -.Nm archive_read_disk_set_standard_lookup , -.Nm archive_read_close , -.Nm archive_read_finish , -.Nm archive_read_free +.Nm archive_read_disk_set_standard_lookup .Nd functions for reading objects from disk .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -81,12 +78,6 @@ Streaming Archive Library (libarchive, -larchive) .Fa "int fd" .Fa "const struct stat *" .Fc -.Ft int -.Fn archive_read_close "struct archive *" -.Ft int -.Fn archive_read_finish "struct archive *" -.Ft int -.Fn archive_read_free "struct archive *" .Sh DESCRIPTION These functions provide an API for reading information about objects on disk. @@ -181,17 +172,6 @@ using the currently registered lookup functions above. This affects the file ownership fields and ACL values in the .Tn struct archive_entry object. -.It Fn archive_read_close -Does nothing for -.Tn archive_read_disk -handles. -.It Fn archive_read_finish -This is a deprecated synonym for -.Fn archive_read_free . -.It Fn archive_read_free -Invokes -.Fn archive_read_close -if it was not invoked manually, then releases all resources. .El More information about the .Va struct archive diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index b2f1d17d9718..9dec2e9080eb 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -124,11 +124,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #endif /* NFSv4 platform ACL type */ -#if HAVE_SUN_ACL -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T -#elif HAVE_DARWIN_ACL +#if HAVE_DARWIN_ACL #define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED -#elif HAVE_ACL_TYPE_NFS4 +#elif HAVE_FREEBSD_NFS4_ACL #define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4 #endif @@ -435,14 +433,71 @@ static void add_trivial_nfs4_acl(struct archive_entry *); #if HAVE_SUN_ACL static int -sun_acl_is_trivial(acl_t *, mode_t, int *trivialp); +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 - acl_t *acl, + void *aclp, + int aclcnt, #else acl_t acl, #endif @@ -454,7 +509,8 @@ setup_acls(struct archive_read_disk *a, { const char *accpath; #if HAVE_SUN_ACL - acl_t *acl; + void *aclp; + int aclcnt; #else acl_t acl; #endif @@ -491,14 +547,17 @@ setup_acls(struct archive_read_disk *a, 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 - /* Solaris reads both POSIX.1e and NFSv4 ACL here */ - facl_get(*fd, 0, &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 @@ -512,47 +571,62 @@ setup_acls(struct archive_read_disk *a, && (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 */ - acl_get(accpath, 0, &acl); + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath); #else acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); #endif -#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL /* Ignore "trivial" ACLs that just mirror the file mode. */ - if (acl != NULL) { #if HAVE_SUN_ACL - if (sun_acl_is_trivial(acl, archive_entry_mode(entry), - &r) == 0 && r == 1) -#elif HAVE_ACL_IS_TRIVIAL_NP - if (acl_is_trivial_np(acl, &r) == 0 && r == 1) -#endif - { - acl_free(acl); - acl = NULL; - /* - * Simultaneous NFSv4 and POSIX.1e ACLs for the same - * entry are not allowed, so we should return here - */ - return (ARCHIVE_OK); - } + 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); } -#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */ - if (acl != NULL) { - r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); +#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 " -#if !HAVE_SUN_ACL - "NFSv4 " -#endif - "ACLs"); + "Couldn't translate NFSv4 ACLs"); } #if HAVE_DARWIN_ACL /* @@ -569,12 +643,16 @@ setup_acls(struct archive_read_disk *a, } #endif /* HAVE_NFS4_ACL */ -#if HAVE_POSIX_ACL - /* This code path is skipped on MacOS and Solaris */ +#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); @@ -583,25 +661,56 @@ setup_acls(struct archive_read_disk *a, && (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 + -#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) { - if (r) { - acl_free(acl); - acl = NULL; - } +#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 (acl != NULL) { - r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); +#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"); @@ -609,6 +718,7 @@ setup_acls(struct archive_read_disk *a, } } +#if !HAVE_SUN_ACL /* Only directories can have default ACLs. */ if (S_ISDIR(archive_entry_mode(entry))) { #if HAVE_ACL_GET_FD_NP @@ -628,7 +738,8 @@ setup_acls(struct archive_read_disk *a, } } } -#endif /* HAVE_POSIX_ACL */ +#endif /* !HAVE_SUN_ACL */ +#endif /* HAVE_POSIX_ACL || HAVE_SUN_ACL */ return (ARCHIVE_OK); } @@ -674,12 +785,14 @@ static const struct { {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_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */ +#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}, @@ -708,14 +821,16 @@ static const struct { const int archive_inherit; const int platform_inherit; } acl_inherit_map[] = { -#if HAVE_SUN_ACL /* Solaris ACL inheritance flags */ +#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}, @@ -730,7 +845,7 @@ static const struct { {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_ACL && !HAVE_DARWIN_ACL */ +#endif /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */ }; #endif /* HAVE_NFS4_ACL */ @@ -873,9 +988,11 @@ add_trivial_nfs4_acl(struct archive_entry *entry) * This is a FreeBSD acl_is_trivial_np() implementation for Solaris */ static int -sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) +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; @@ -886,30 +1003,25 @@ sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) ace_t *ace; ace_t tace[6]; +#endif - if (acl == NULL || trivialp == NULL) + if (aclp == NULL || trivialp == NULL) return (-1); *trivialp = 0; - /* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */ - if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0) - return (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 (acl->acl_type == ACLENT_T) { - if (acl->acl_cnt == 4) + if (!is_nfs4) { + if (aclcnt == 4) *trivialp = 1; return (0); } - if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t)) - return (-1); - +#if HAVE_SUN_NFS4_ACL /* * Continue with checking NFSv4 ACLs * @@ -994,13 +1106,13 @@ sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) if (tace[i].a_access_mask != 0) p++; } - if (acl->acl_cnt != p) + if (aclcnt != p) return (0); p = 0; for (i = 0; i < 6; i++) { if (tace[i].a_access_mask != 0) { - ace = &((ace_t *)acl->acl_aclp)[p]; + ace = &((ace_t *)aclp)[p]; /* * Illumos added ACE_DELETE_CHILD to write perms for * directories. We have to check against that, too. @@ -1008,8 +1120,7 @@ sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) if (ace->a_flags != tace[i].a_flags || ace->a_type != tace[i].a_type || (ace->a_access_mask != tace[i].a_access_mask && - ((acl->acl_flags & ACL_IS_DIR) == 0 || - (tace[i].a_access_mask & wperm) == 0 || + (!is_dir || (tace[i].a_access_mask & wperm) == 0 || ace->a_access_mask != (tace[i].a_access_mask | ACE_DELETE_CHILD)))) return (0); @@ -1018,6 +1129,9 @@ sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) } *trivialp = 1; +#else /* !HAVE_SUN_NFS4_ACL */ + (void)aclp; /* UNUSED */ +#endif /* !HAVE_SUN_NFS4_ACL */ return (0); } #endif /* HAVE_SUN_ACL */ @@ -1028,27 +1142,29 @@ sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) */ static int translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, acl_t *acl, int default_entry_acl_type) + 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 - (void)default_entry_acl_type; - - if (acl->acl_cnt <= 0) + if (aclcnt <= 0) return (ARCHIVE_OK); - for (e = 0; e < acl->acl_cnt; e++) { + for (e = 0; e < aclcnt; e++) { ae_name = NULL; ae_tag = 0; ae_perm = 0; - if (acl->acl_type == ACE_T) { - ace = &((ace_t *)acl->acl_aclp)[e]; +#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) { @@ -1100,8 +1216,10 @@ translate_acl(struct archive_read_disk *a, ae_perm |= acl_perm_map[i].archive_perm; } - } else { - aclent = &((aclent_t *)acl->acl_aclp)[e]; + } 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 @@ -1148,7 +1266,8 @@ translate_acl(struct archive_read_disk *a, ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; if ((aclent->a_perm & 4) != 0) ae_perm |= ARCHIVE_ENTRY_ACL_READ; - } /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ + } else + return (ARCHIVE_WARN); archive_entry_acl_add_entry(entry, entry_acl_type, ae_perm, ae_tag, ae_id, ae_name); @@ -1165,11 +1284,11 @@ 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_ACL_TYPE_NFS4 +#if HAVE_FREEBSD_NFS4_ACL acl_entry_type_t acl_type; int brand; #endif -#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL +#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL acl_flagset_t acl_flagset; #endif acl_entry_t acl_entry; @@ -1181,7 +1300,7 @@ translate_acl(struct archive_read_disk *a, #endif const char *ae_name; -#if HAVE_ACL_TYPE_NFS4 +#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. @@ -1272,7 +1391,7 @@ translate_acl(struct archive_read_disk *a, case ACL_OTHER: ae_tag = ARCHIVE_ENTRY_ACL_OTHER; break; -#if HAVE_ACL_TYPE_NFS4 +#if HAVE_FREEBSD_NFS4_ACL case ACL_EVERYONE: ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; break; @@ -1307,9 +1426,9 @@ translate_acl(struct archive_read_disk *a, // XXX acl_type maps to allow/deny/audit/YYYY bits entry_acl_type = default_entry_acl_type; #endif -#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL +#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { -#if HAVE_ACL_TYPE_NFS4 +#if HAVE_FREEBSD_NFS4_ACL /* * acl_get_entry_type_np() fails with non-NFSv4 ACLs */ @@ -1336,7 +1455,7 @@ translate_acl(struct archive_read_disk *a, "Invalid NFSv4 ACL entry type"); return (ARCHIVE_WARN); } -#endif /* HAVE_ACL_TYPE_NFS4 */ +#endif /* HAVE_FREEBSD_NFS4_ACL */ /* * Libarchive stores "flag" (NFSv4 inheritance bits) @@ -1361,7 +1480,7 @@ translate_acl(struct archive_read_disk *a, ae_perm |= acl_inherit_map[i].archive_inherit; } } -#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */ +#endif /* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL */ if (acl_get_permset(acl_entry, &acl_permset) != 0) { archive_set_error(&a->archive, errno, @@ -1382,6 +1501,11 @@ translate_acl(struct archive_read_disk *a, 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); diff --git a/libarchive/archive_read_format.3 b/libarchive/archive_read_format.3 index 53b9a7e0e607..91c5d2cfd4b6 100644 --- a/libarchive/archive_read_format.3 +++ b/libarchive/archive_read_format.3 @@ -37,9 +37,9 @@ .Nm archive_read_support_format_empty , .Nm archive_read_support_format_iso9660 , .Nm archive_read_support_format_lha , -.Nm archive_read_support_format_mtree, -.Nm archive_read_support_format_rar, -.Nm archive_read_support_format_raw, +.Nm archive_read_support_format_mtree , +.Nm archive_read_support_format_rar , +.Nm archive_read_support_format_raw , .Nm archive_read_support_format_tar , .Nm archive_read_support_format_xar , .Nm archive_read_support_format_zip diff --git a/libarchive/archive_read_open.3 b/libarchive/archive_read_open.3 index 4d8272cac873..02494560da4d 100644 --- a/libarchive/archive_read_open.3 +++ b/libarchive/archive_read_open.3 @@ -33,7 +33,7 @@ .Nm archive_read_open_fd , .Nm archive_read_open_FILE , .Nm archive_read_open_filename , -.Nm archive_read_open_memory , +.Nm archive_read_open_memory .Nd functions for reading streaming archives .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c index b1624651426c..e8753853f3c8 100644 --- a/libarchive/archive_read_support_format_warc.c +++ b/libarchive/archive_read_support_format_warc.c @@ -600,9 +600,10 @@ _warc_rdver(const char *buf, size_t bsz) /* looks good so far, read the version number for a laugh */ buf += sizeof(magic) - 1U; - if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) { + if (isdigit((unsigned char)buf[0U]) && (buf[1U] == '.') && + isdigit((unsigned char)buf[2U])) { /* we support a maximum of 2 digits in the minor version */ - if (isdigit(buf[3U])) + if (isdigit((unsigned char)buf[3U])) end = 1U; /* set up major version */ ver = (buf[0U] - '0') * 10000U; @@ -686,7 +687,7 @@ _warc_rduri(const char *buf, size_t bsz) /* spaces inside uri are not allowed, CRLF should follow */ for (p = val; p < eol; p++) { - if (isspace(*p)) + if (isspace((unsigned char)*p)) return res; } @@ -736,7 +737,7 @@ _warc_rdlen(const char *buf, size_t bsz) while (val < eol && (*val == ' ' || *val == '\t')) val++; /* there must be at least one digit */ - if (!isdigit(*val)) + if (!isdigit((unsigned char)*val)) return -1; len = strtol(val, &on, 10); if (on != eol) { diff --git a/libarchive/archive_write_data.3 b/libarchive/archive_write_data.3 index 0cdd25f1f923..9c16cd9b4f70 100644 --- a/libarchive/archive_write_data.3 +++ b/libarchive/archive_write_data.3 @@ -24,11 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd February 28, 2017 .Dt ARCHIVE_WRITE_DATA 3 .Os .Sh NAME -.Nm archive_write_data +.Nm archive_write_data , +.Nm archive_write_data_block .Nd functions for creating archives .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -36,8 +37,27 @@ Streaming Archive Library (libarchive, -larchive) .In archive.h .Ft la_ssize_t .Fn archive_write_data "struct archive *" "const void *" "size_t" +.Ft la_ssize_t +.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset" .Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_data Write data corresponding to the header just written. +.It Fn archive_write_data_block +Write data corresponding to the header just written. +This is like +.Fn archive_write_data +except that it performs a seek on the file being +written to the specified offset before writing the data. +This is useful when restoring sparse files from archive +formats that support sparse files. +Returns number of bytes written or -1 on error. +(Note: This is currently not supported for +.Tn archive_write +handles, only for +.Tn archive_write_disk +handles. +.El .\" .Sh EXAMPLE .\" .Sh RETURN VALUES diff --git a/libarchive/archive_write_disk.3 b/libarchive/archive_write_disk.3 index ba6c9706e8a3..4891b8572efd 100644 --- a/libarchive/archive_write_disk.3 +++ b/libarchive/archive_write_disk.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd February 28, 2017 .Dt ARCHIVE_WRITE_DISK 3 .Os .Sh NAME @@ -33,14 +33,7 @@ .Nm archive_write_disk_set_skip_file , .Nm archive_write_disk_set_group_lookup , .Nm archive_write_disk_set_standard_lookup , -.Nm archive_write_disk_set_user_lookup , -.Nm archive_write_header , -.Nm archive_write_data , -.Nm archive_write_data_block , -.Nm archive_write_finish_entry , -.Nm archive_write_close , -.Nm archive_write_finish -.Nm archive_write_free +.Nm archive_write_disk_set_user_lookup .Nd functions for creating objects on disk .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -68,20 +61,6 @@ Streaming Archive Library (libarchive, -larchive) .Fa "uid_t (*)(void *, const char *uname, uid_t uid)" .Fa "void (*cleanup)(void *)" .Fc -.Ft int -.Fn archive_write_header "struct archive *" "struct archive_entry *" -.Ft la_ssize_t -.Fn archive_write_data "struct archive *" "const void *" "size_t" -.Ft la_ssize_t -.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset" -.Ft int -.Fn archive_write_finish_entry "struct archive *" -.Ft int -.Fn archive_write_close "struct archive *" -.Ft int -.Fn archive_write_finish "struct archive *" -.Ft int -.Fn archive_write_free "struct archive *" .Sh DESCRIPTION These functions provide a complete API for creating objects on disk from @@ -223,60 +202,6 @@ the number of calls to .Xr getpwnam 3 and .Xr getgrnam 3 . -.It Fn archive_write_header -Build and write a header using the data in the provided -.Tn struct archive_entry -structure. -See -.Xr archive_entry 3 -for information on creating and populating -.Tn struct archive_entry -objects. -.It Fn archive_write_data -Write data corresponding to the header just written. -Returns number of bytes written or -1 on error. -.It Fn archive_write_data_block -Write data corresponding to the header just written. -This is like -.Fn archive_write_data -except that it performs a seek on the file being -written to the specified offset before writing the data. -This is useful when restoring sparse files from archive -formats that support sparse files. -Returns number of bytes written or -1 on error. -(Note: This is currently not supported for -.Tn archive_write -handles, only for -.Tn archive_write_disk -handles.) -.It Fn archive_write_finish_entry -Close out the entry just written. -Ordinarily, clients never need to call this, as it -is called automatically by -.Fn archive_write_next_header -and -.Fn archive_write_close -as needed. -However, some file attributes are written to disk only -after the file is closed, so this can be necessary -if you need to work with the file on disk right away. -.It Fn archive_write_close -Set any attributes that could not be set during the initial restore. -For example, directory timestamps are not restored initially because -restoring a subsequent file would alter that timestamp. -Similarly, non-writable directories are initially created with -write permissions (so that their contents can be restored). -The -.Nm -library maintains a list of all such deferred attributes and -sets them when this function is invoked. -.It Fn archive_write_finish -This is a deprecated synonym for -.Fn archive_write_free . -.It Fn archive_write_free -Invokes -.Fn archive_write_close -if it was not invoked manually, then releases all resources. .El More information about the .Va struct archive diff --git a/libarchive/archive_write_disk_acl.c b/libarchive/archive_write_disk_acl.c index 144ab7e72e1b..643f3c3a0733 100644 --- a/libarchive/archive_write_disk_acl.c +++ b/libarchive/archive_write_disk_acl.c @@ -61,17 +61,18 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name, #else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ -#if HAVE_SUN_ACL -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T -#elif HAVE_DARWIN_ACL +#if HAVE_DARWIN_ACL #define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED -#elif HAVE_ACL_TYPE_NFS4 +#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 *, - acl_type_t, int archive_entry_acl_type, const char *tn); +#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, @@ -84,7 +85,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name, & 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, ACLENT_T, + ret = set_acl(a, fd, name, abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e"); #else /* HAVE_POSIX_ACL */ if ((archive_acl_types(abstract_acl) @@ -109,13 +110,16 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name, 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 */ @@ -123,7 +127,7 @@ static const struct { const int archive_perm; const int platform_perm; } acl_perm_map[] = { -#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */ +#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}, @@ -158,12 +162,14 @@ static const struct { {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_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */ +#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}, @@ -183,6 +189,7 @@ static const struct { #endif #endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ }; +#endif /* !HAVE_SUN_ACL || HAVE_SUN_NFS4_ACL */ #if HAVE_NFS4_ACL /* @@ -192,14 +199,16 @@ static const struct { const int archive_inherit; const int platform_inherit; } acl_inherit_map[] = { -#if HAVE_SUN_ACL /* Solaris NFSv4 inheritance flags */ +#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}, @@ -214,29 +223,34 @@ static const struct { {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_ACL && !HAVE_DARWIN_ACL */ +#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, - acl_type_t acl_type, int ae_requested_type, const char *tname) +#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; - int e, r; - acl_t *acl; +#endif + int cmd, e, r; + void *aclp; #else acl_t acl; acl_entry_t acl_entry; acl_permset_t acl_permset; -#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL +#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL acl_flagset_t acl_flagset; #endif #endif /* HAVE_SUN_ACL */ -#if HAVE_ACL_TYPE_NFS4 +#if HAVE_FREEBSD_NFS4_ACL int r; #endif int ret; @@ -256,31 +270,26 @@ set_acl(struct archive *a, int fd, const char *name, return (ARCHIVE_OK); #if HAVE_SUN_ACL - acl = NULL; - acl = malloc(sizeof(acl_t)); - if (acl == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Invalid ACL type"); + 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 (acl_type == ACE_T) - acl->acl_entry_size = sizeof(ace_t); - else if (acl_type == ACLENT_T) - acl->acl_entry_size = sizeof(aclent_t); - else { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Invalid ACL type"); - acl_free(acl); - return (ARCHIVE_FAILED); - } - acl->acl_type = acl_type; - acl->acl_cnt = entries; - acl->acl_aclp = malloc(entries * acl->acl_entry_size); - if (acl->acl_aclp == NULL) { + if (aclp == NULL) { archive_set_error(a, errno, "Can't allocate memory for acl buffer"); - acl_free(acl); return (ARCHIVE_FAILED); } #else /* !HAVE_SUN_ACL */ @@ -297,19 +306,24 @@ set_acl(struct archive *a, int fd, const char *name, 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 - ace = NULL; aclent = NULL; - if (acl->acl_type == ACE_T) { - ace = &((ace_t *)acl->acl_aclp)[e]; - ace->a_who = -1; - ace->a_access_mask = 0; - ace->a_flags = 0; - } else { - aclent = &((aclent_t *)acl->acl_aclp)[e]; +#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 /* @@ -346,45 +360,63 @@ set_acl(struct archive *a, int fd, const char *name, #if HAVE_SUN_ACL case ARCHIVE_ENTRY_ACL_USER: ae_uid = archive_write_disk_uid(a, ae_name, ae_id); - if (acl->acl_type == ACE_T) - ace->a_who = ae_uid; - else { + 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 (acl->acl_type == ACE_T) { - ace->a_who = ae_gid; - ace->a_flags |= ACE_IDENTIFIER_GROUP; - } else { + 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 (acl->acl_type == ACE_T) - ace->a_flags |= ACE_OWNER; - else + 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 (acl->acl_type == ACE_T) { + 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; - } else - aclent->a_type |= GROUP_OBJ; + } + +#endif break; case ARCHIVE_ENTRY_ACL_MASK: - aclent->a_type |= CLASS_OBJ; + if (aclent != NULL) + aclent->a_type |= CLASS_OBJ; break; case ARCHIVE_ENTRY_ACL_OTHER: - aclent->a_type |= OTHER_OBJ; + if (aclent != NULL) + aclent->a_type |= OTHER_OBJ; break; +#if HAVE_SUN_NFS4_ACL case ARCHIVE_ENTRY_ACL_EVERYONE: - ace->a_flags |= ACE_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); @@ -425,7 +457,7 @@ set_acl(struct archive *a, int fd, const char *name, case ARCHIVE_ENTRY_ACL_OTHER: acl_set_tag_type(acl_entry, ACL_OTHER); break; -#if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */ +#if HAVE_FREEBSD_NFS4_ACL /* FreeBSD only */ case ARCHIVE_ENTRY_ACL_EVERYONE: acl_set_tag_type(acl_entry, ACL_EVERYONE); break; @@ -439,10 +471,11 @@ set_acl(struct archive *a, int fd, const char *name, goto exit_free; } -#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL +#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; @@ -467,6 +500,7 @@ set_acl(struct archive *a, int fd, const char *name, else r = -1; break; +#endif case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: if (aclent == NULL) r = -1; @@ -497,7 +531,7 @@ set_acl(struct archive *a, int fd, const char *name, #endif /* !HAVE_SUN_ACL */ default: archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Unknown ACL entry type"); + "Unsupported ACL entry type"); ret = ARCHIVE_FAILED; goto exit_free; } @@ -511,17 +545,20 @@ set_acl(struct archive *a, int fd, const char *name, ret = ARCHIVE_FAILED; goto exit_free; } -#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */ +#endif /* HAVE_FREEBSD_NFS4_ACL || HAVE_SUN_ACL */ #if HAVE_SUN_ACL - if (acl->acl_type == ACLENT_T) { + 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; - } else + } +#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, @@ -536,6 +573,7 @@ set_acl(struct archive *a, int fd, const char *name, 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 @@ -552,10 +590,11 @@ set_acl(struct archive *a, int fd, const char *name, #endif } } +#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ #if HAVE_NFS4_ACL -#if HAVE_SUN_ACL - if (acl_type == ACE_T) +#if HAVE_SUN_NFS4_ACL + if (ace != NULL) #elif HAVE_DARWIN_ACL if (acl_type == ACL_TYPE_EXTENDED) #else /* FreeBSD */ @@ -611,7 +650,7 @@ set_acl(struct archive *a, int fd, const char *name, #endif { #if HAVE_SUN_ACL - if (facl_set(fd, acl) == 0) + 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 */ @@ -630,7 +669,7 @@ set_acl(struct archive *a, int fd, const char *name, } else #endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */ #if HAVE_SUN_ACL - if (acl_set(name, acl) != 0) + if (acl(name, cmd, entries, aclp) != 0) #elif HAVE_ACL_SET_LINK_NP if (acl_set_link_np(name, acl_type, acl) != 0) #else @@ -648,7 +687,11 @@ set_acl(struct archive *a, int fd, const char *name, } } 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_posix.c b/libarchive/archive_write_disk_posix.c index 5a01e8450cef..bf58b6d010f0 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -2467,7 +2467,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr, if (a_eno) *a_eno = err; if (a_estr) - archive_string_sprintf(a_estr, errstr, path); + archive_string_sprintf(a_estr, "%s%s", errstr, path); } /* @@ -2573,7 +2573,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, * with the deep-directory editing. */ fsobj_error(a_eno, a_estr, errno, - "Could not stat %s", path); + "Could not stat ", path); res = ARCHIVE_FAILED; break; } @@ -2582,7 +2582,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, if (chdir(head) != 0) { tail[0] = c; fsobj_error(a_eno, a_estr, errno, - "Could not chdir %s", path); + "Could not chdir ", path); res = (ARCHIVE_FATAL); break; } @@ -2599,7 +2599,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, if (unlink(head)) { tail[0] = c; fsobj_error(a_eno, a_estr, errno, - "Could not remove symlink %s", + "Could not remove symlink ", path); res = ARCHIVE_FAILED; break; @@ -2618,7 +2618,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, /* if (!S_ISLNK(path)) { fsobj_error(a_eno, a_estr, 0, - "Removing symlink %s", path); + "Removing symlink ", path); } */ /* Symlink gone. No more problem! */ @@ -2630,7 +2630,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, tail[0] = c; fsobj_error(a_eno, a_estr, 0, "Cannot remove intervening " - "symlink %s", path); + "symlink ", path); res = ARCHIVE_FAILED; break; } @@ -2652,7 +2652,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, } else { fsobj_error(a_eno, a_estr, errno, - "Could not stat %s", path); + "Could not stat ", path); res = (ARCHIVE_FAILED); break; } @@ -2661,7 +2661,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, tail[0] = c; fsobj_error(a_eno, a_estr, errno, - "Could not chdir %s", path); + "Could not chdir ", path); res = (ARCHIVE_FATAL); break; } @@ -2674,14 +2674,14 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, tail[0] = c; fsobj_error(a_eno, a_estr, 0, "Cannot extract through " - "symlink %s", path); + "symlink ", path); res = ARCHIVE_FAILED; break; } } else { tail[0] = c; fsobj_error(a_eno, a_estr, 0, - "Cannot extract through symlink %s", path); + "Cannot extract through symlink ", path); res = ARCHIVE_FAILED; break; } diff --git a/libarchive/archive_write_finish_entry.3 b/libarchive/archive_write_finish_entry.3 index c5ef69ebc941..dc1b94b82a5c 100644 --- a/libarchive/archive_write_finish_entry.3 +++ b/libarchive/archive_write_finish_entry.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd February 28, 2017 .Dt ARCHIVE_WRITE_FINISH_ENTRY 3 .Os .Sh NAME @@ -45,6 +45,9 @@ is called automatically by and .Fn archive_write_close as needed. +For +.Tn archive_write_disk +handles, this flushes pending file attribute changes like modification time. .\" .Sh EXAMPLE .Sh RETURN VALUES This function returns diff --git a/libarchive/archive_write_format.3 b/libarchive/archive_write_format.3 index d4ba6abff5a0..aaafb0a8617c 100644 --- a/libarchive/archive_write_format.3 +++ b/libarchive/archive_write_format.3 @@ -108,7 +108,6 @@ Streaming Archive Library (libarchive, -larchive) These functions set the format that will be used for the archive. .Pp The library can write a variety of common archive formats. - .Bl -tag -width indent .It Fn archive_write_set_format Sets the format based on the format code (see diff --git a/libarchive/test/test_acl_platform_nfs4.c b/libarchive/test/test_acl_platform_nfs4.c index 01c1dc589f6f..c8854082ab1b 100644 --- a/libarchive/test/test_acl_platform_nfs4.c +++ b/libarchive/test/test_acl_platform_nfs4.c @@ -254,12 +254,14 @@ 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 (start > 0) { assertEqualInt(ARCHIVE_OK, archive_entry_acl_add_entry(ae, acls[0].type, acls[0].permset, acls[0].tag, acls[0].qual, acls[0].name)); } +#endif for (i = start; i < end; i++) { assertEqualInt(ARCHIVE_OK, archive_entry_acl_add_entry(ae, @@ -269,14 +271,14 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end) } static int -#ifdef HAVE_SUN_ACL +#ifdef HAVE_SUN_NFS4_ACL 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_ACL /* Solaris NFSv4 ACL permissions */ +#ifdef HAVE_SUN_NFS4_ACL /* Solaris NFSv4 ACL permissions */ {ACE_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE}, {ACE_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA}, {ACE_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY}, @@ -311,7 +313,9 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps) {ACL_READ_SECURITY, ARCHIVE_ENTRY_ACL_READ_ACL}, {ACL_WRITE_SECURITY, ARCHIVE_ENTRY_ACL_WRITE_ACL}, {ACL_CHANGE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER}, +#if HAVE_DECL_ACL_SYNCHRONIZE {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}, +#endif #else /* FreeBSD NFSv4 ACL permissions */ {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE}, {ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE}, @@ -337,7 +341,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_ACL +#if HAVE_SUN_NFS4_ACL if (a_access_mask & perms[i].machine) #else if (acl_get_perm_np(opaque_ps, perms[i].machine)) @@ -347,21 +351,23 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps) } static int -#if HAVE_SUN_ACL +#if HAVE_SUN_NFS4_ACL 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_ACL /* Solaris NFSv4 ACL inheritance flags */ +#if HAVE_SUN_NFS4_ACL /* Solaris NFSv4 ACL inheritance flags */ {ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT}, {ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT}, {ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT}, {ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY}, {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS}, {ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS}, +#ifdef ACE_INHERITED_ACE {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED} +#endif #elif HAVE_DARWIN_ACL /* MacOS NFSv4 ACL inheritance flags */ {ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}, {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT}, @@ -380,7 +386,7 @@ acl_flagset_to_bitmap(acl_flagset_t opaque_fs) int i, flagset = 0; for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i) -#if HAVE_SUN_ACL +#if HAVE_SUN_NFS4_ACL if (a_flags & flags[i].machine) #else if (acl_get_flag_np(opaque_fs, flags[i].machine)) @@ -390,13 +396,13 @@ acl_flagset_to_bitmap(acl_flagset_t opaque_fs) } static int -#if HAVE_SUN_ACL +#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_ACL +#if !HAVE_SUN_NFS4_ACL #if HAVE_DARWIN_ACL void *q; uid_t ugid; @@ -409,10 +415,10 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl) acl_tag_t tag_type; acl_permset_t opaque_ps; acl_flagset_t opaque_fs; -#endif /* !HAVE_SUN_ACL */ +#endif /* !HAVE_SUN_NFS4_ACL */ int perms; -#if HAVE_SUN_ACL +#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); @@ -428,7 +434,7 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl) if (perms != myacl->permset) return (0); -#if HAVE_SUN_ACL +#if HAVE_SUN_NFS4_ACL switch (ace->a_type) { case ACE_ACCESS_ALLOWED_ACE_TYPE: if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW) @@ -507,7 +513,7 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl) default: return (0); } -#else /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ +#else /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */ switch (entry_type) { case ACL_ENTRY_TYPE_ALLOW: if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW) @@ -559,14 +565,15 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl) if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0); break; } -#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ +#endif /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */ return (1); } static void compare_acls( -#if HAVE_SUN_ACL - acl_t *acl, +#if HAVE_SUN_NFS4_ACL + void *aclp, + int aclcnt, #else acl_t acl, #endif @@ -575,7 +582,7 @@ compare_acls( int *marker; int matched; int i, n; -#if HAVE_SUN_ACL +#if HAVE_SUN_NFS4_ACL int e; ace_t *acl_entry; #else @@ -587,26 +594,28 @@ compare_acls( marker = malloc(sizeof(marker[0]) * (n + 1)); for (i = 0; i < n; i++) marker[i] = i + start; +#if !HAVE_DARWIN_ACL /* Always include the first ACE. */ if (start > 0) { marker[n] = 0; ++n; } +#endif /* * Iterate over acls in system acl object, try to match each * one with an item in the myacls array. */ -#if HAVE_SUN_ACL - for (e = 0; e < acl->acl_cnt; e++) +#if HAVE_SUN_NFS4_ACL + 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)) #endif { -#if HAVE_SUN_ACL - acl_entry = &((ace_t *)acl->acl_aclp)[e]; +#if HAVE_SUN_NFS4_ACL + acl_entry = &((ace_t *)aclp)[e]; #else /* After the first time... */ entry_id = ACL_NEXT_ENTRY; @@ -711,11 +720,10 @@ DEFINE_TEST(test_acl_platform_nfs4) skipping("NFS4 ACLs are not supported on this platform"); #else char buff[64]; + int i; struct stat st; struct archive *a; struct archive_entry *ae; - int i, n; - char *func; #if HAVE_DARWIN_ACL /* On MacOS we skip trivial ACLs in some tests */ const int regcnt = acls_reg_cnt - 4; const int dircnt = acls_dir_cnt - 4; @@ -723,86 +731,20 @@ DEFINE_TEST(test_acl_platform_nfs4) const int regcnt = acls_reg_cnt; const int dircnt = acls_dir_cnt; #endif -#if HAVE_SUN_ACL - acl_t *acl; -#else /* !HAVE_SUN_ACL */ -#if HAVE_DARWIN_ACL - acl_entry_t aclent; - acl_permset_t permset; - const uid_t uid = 1000; - uuid_t uuid; -#endif /* HAVE_DARWIN_ACL */ +#if HAVE_SUN_NFS4_ACL + void *aclp; + int aclcnt; +#else /* !HAVE_SUN_NFS4_ACL */ acl_t acl; -#endif /* !HAVE_SUN_ACL */ - - /* - * First, do a quick manual set/read of ACL data to - * verify that the local filesystem does support ACLs. - * If it doesn't, we'll simply skip the remaining tests. - */ -#if HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4 - acl = acl_from_text("owner@:rwxp::allow,group@:rwp:f:allow"); - failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno)); - assert((void *)acl != NULL); -#elif HAVE_DARWIN_ACL - acl = acl_init(1); - assert((void *)acl != NULL); - assertEqualInt(0, acl_create_entry(&acl, &aclent)); - assertEqualInt(0, acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW)); - assertEqualInt(0, acl_get_permset(aclent, &permset)); - assertEqualInt(0, acl_add_perm(permset, ACL_READ_DATA)); - assertEqualInt(0, acl_add_perm(permset, ACL_WRITE_DATA)); - assertEqualInt(0, acl_add_perm(permset, ACL_APPEND_DATA)); - assertEqualInt(0, acl_add_perm(permset, ACL_EXECUTE)); - assertEqualInt(0, acl_set_permset(aclent, permset)); - assertEqualInt(0, mbr_identifier_to_uuid(ID_TYPE_UID, &uid, - sizeof(uid_t), uuid)); - assertEqualInt(0, acl_set_qualifier(aclent, uuid)); #endif - /* Create a test dir and try to set an ACL on it. */ - if (!assertMakeDir("pretest", 0755)) { -#if !HAVE_SUN_ACL - acl_free(acl); -#endif + assertMakeFile("pretest", 0644, "a"); + + if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) { + skipping("NFS4 ACLs are not writable on this filesystem"); return; } -#if HAVE_SUN_ACL - func = "acl_get()"; - n = acl_get("pretest", 0, &acl); -#else - func = "acl_set_file()"; -#if HAVE_DARWIN_ACL - n = acl_set_file("pretest", ACL_TYPE_EXTENDED, acl); -#else - n = acl_set_file("pretest", ACL_TYPE_NFS4, acl); -#endif - acl_free(acl); -#endif - if (n != 0) { -#if HAVE_SUN_ACL - if (errno == ENOSYS) -#else - if (errno == EOPNOTSUPP || errno == EINVAL) -#endif - { - skipping("NFS4 ACL is not supported on this filesystem"); - return; - } - } - failure("%s: errno = %d (%s)", func, errno, strerror(errno)); - assertEqualInt(0, n); - -#if HAVE_SUN_ACL - if (acl->acl_type != ACE_T) { - acl_free(acl); - skipping("NFS4 ACL is not supported on this filesystem"); - return; - } - acl_free(acl); -#endif - /* Create a write-to-disk object. */ assert(NULL != (a = archive_write_disk_new())); archive_write_disk_set_options(a, @@ -848,10 +790,10 @@ DEFINE_TEST(test_acl_platform_nfs4) /* Verify the data on disk. */ assertEqualInt(0, stat("testall", &st)); assertEqualInt(st.st_mtime, 123456); -#if HAVE_SUN_ACL - n = acl_get("testall", 0, &acl); - failure("acl_get(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); +#if HAVE_SUN_NFS4_ACL + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall"); + failure("acl(): errno = %d (%s)", errno, strerror(errno)); + assert(aclp != NULL); #else #if HAVE_DARWIN_ACL acl = acl_get_file("testall", ACL_TYPE_EXTENDED); @@ -861,18 +803,25 @@ 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 + compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt); + free(aclp); + aclp = NULL; +#else compare_acls(acl, acls_reg, "testall", 0, regcnt); acl_free(acl); +#endif + /* Verify single-permission dirs on disk. */ for (i = 0; i < dircnt; ++i) { sprintf(buff, "dir%d", i); assertEqualInt(0, stat(buff, &st)); assertEqualInt(st.st_mtime, 123456 + i); -#if HAVE_SUN_ACL - n = acl_get(buff, 0, &acl); - failure("acl_get(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); +#if HAVE_SUN_NFS4_ACL + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff); + failure("acl(): errno = %d (%s)", errno, strerror(errno)); + assert(aclp != NULL); #else #if HAVE_DARWIN_ACL acl = acl_get_file(buff, ACL_TYPE_EXTENDED); @@ -883,17 +832,23 @@ DEFINE_TEST(test_acl_platform_nfs4) strerror(errno)); assert(acl != (acl_t)NULL); #endif +#if HAVE_SUN_NFS4_ACL + compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1); + free(aclp); + aclp = NULL; +#else compare_acls(acl, acls_dir, buff, i, i + 1); acl_free(acl); +#endif } /* Verify "dirall" on disk. */ assertEqualInt(0, stat("dirall", &st)); assertEqualInt(st.st_mtime, 123456); -#if HAVE_SUN_ACL - n = acl_get("dirall", 0, &acl); - failure("acl_get(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); +#if HAVE_SUN_NFS4_ACL + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall"); + failure("acl(): errno = %d (%s)", errno, strerror(errno)); + assert(aclp != NULL); #else #if HAVE_DARWIN_ACL acl = acl_get_file("dirall", ACL_TYPE_EXTENDED); @@ -903,8 +858,14 @@ 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 + compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt); + free(aclp); + aclp = NULL; +#else compare_acls(acl, acls_dir, "dirall", 0, dircnt); acl_free(acl); +#endif /* Read and compare ACL via archive_read_disk */ a = archive_read_disk_new(); diff --git a/libarchive/test/test_acl_platform_posix1e.c b/libarchive/test/test_acl_platform_posix1e.c index b46f65815307..0224a57f1c23 100644 --- a/libarchive/test/test_acl_platform_posix1e.c +++ b/libarchive/test/test_acl_platform_posix1e.c @@ -226,7 +226,7 @@ acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl) static void #if HAVE_SUN_ACL -compare_acls(acl_t *acl, struct archive_test_acl_t *myacls, int n) +compare_acls(void *aclp, int aclcnt, struct archive_test_acl_t *myacls, int n) #else compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n) #endif @@ -254,8 +254,8 @@ compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n) * one with an item in the myacls array. */ #if HAVE_SUN_ACL - for(e = 0; e < acl->acl_cnt; e++) { - acl_entry = &((aclent_t *)acl->acl_aclp)[e]; + for(e = 0; e < aclcnt; e++) { + acl_entry = &((aclent_t *)aclp)[e]; #else while (1 == acl_get_entry(acl, entry_id, &acl_entry)) { /* After the first time... */ @@ -304,84 +304,20 @@ DEFINE_TEST(test_acl_platform_posix1e_restore) struct stat st; struct archive *a; struct archive_entry *ae; - int n, fd; - char *func; #if HAVE_SUN_ACL - acl_t *acl, *acl2; + void *aclp; + int aclcnt; #else acl_t acl; #endif - /* - * First, do a quick manual set/read of ACL data to - * verify that the local filesystem does support ACLs. - * If it doesn't, we'll simply skip the remaining tests. - */ -#if HAVE_SUN_ACL - n = acl_fromtext("user::rwx,user:1:rw-,group::rwx,group:15:r-x,other:rwx,mask:rwx", &acl); - failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); -#else - acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx"); - failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno)); - assert((void *)acl != NULL); -#endif + assertMakeFile("pretest", 0644, "a"); - /* Create a test file and try ACL on it. */ - fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777); - failure("Could not create test file?!"); - if (!assert(fd >= 0)) { - acl_free(acl); + if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_POSIX1E) { + skipping("POSIX.1e ACLs are not writable on this filesystem"); return; } -#if HAVE_SUN_ACL - n = facl_get(fd, 0, &acl2); - if (n != 0) { - close(fd); - acl_free(acl); - } - if (errno == ENOSYS) { - skipping("POSIX.1e ACLs are not supported on this filesystem"); - return; - } - failure("facl_get(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); - - if (acl2->acl_type != ACLENT_T) { - acl_free(acl2); - skipping("POSIX.1e ACLs are not supported on this filesystem"); - return; - } - acl_free(acl2); - - func = "facl_set()"; - n = facl_set(fd, acl); -#else - func = "acl_set_fd()"; - n = acl_set_fd(fd, acl); -#endif - acl_free(acl); - if (n != 0) { -#if HAVE_SUN_ACL - if (errno == ENOSYS) -#else - if (errno == EOPNOTSUPP || errno == EINVAL) -#endif - { - close(fd); - skipping("POSIX.1e ACLs are not supported on this filesystem"); - return; - } - } - failure("%s: errno = %d (%s)", func, errno, strerror(errno)); - assertEqualInt(0, n); - -#if HAVE_SUN_ACL - -#endif - close(fd); - /* Create a write-to-disk object. */ assert(NULL != (a = archive_write_disk_new())); archive_write_disk_set_options(a, @@ -405,16 +341,23 @@ DEFINE_TEST(test_acl_platform_posix1e_restore) assertEqualInt(0, stat("test0", &st)); assertEqualInt(st.st_mtime, 123456); #if HAVE_SUN_ACL - n = acl_get("test0", 0, &acl); - failure("acl_get(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); + aclp = sunacl_get(GETACL, &aclcnt, 0, "test0"); + failure("acl(): errno = %d (%s)", errno, strerror(errno)); + assert(aclp != NULL); #else acl = acl_get_file("test0", ACL_TYPE_ACCESS); failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno)); assert(acl != (acl_t)NULL); #endif +#if HAVE_SUN_ACL + compare_acls(aclp, aclcnt, acls2, sizeof(acls2)/sizeof(acls2[0])); + free(aclp); + aclp = NULL; +#else compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0])); acl_free(acl); +#endif + #endif /* HAVE_SUN_ACL || HAVE_POSIX_ACL */ } @@ -432,7 +375,8 @@ DEFINE_TEST(test_acl_platform_posix1e_read) char *func, *acl_text; const char *acl1_text, *acl2_text, *acl3_text; #if HAVE_SUN_ACL - acl_t *acl, *acl1, *acl2, *acl3; + void *aclp; + int aclcnt; #else acl_t acl1, acl2, acl3; #endif @@ -451,9 +395,14 @@ DEFINE_TEST(test_acl_platform_posix1e_read) "user:1:rw-," "group:15:r-x," "mask:rwx"; - n = acl_fromtext(acl1_text, &acl1); - failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); + aclent_t aclp1[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 1, 4 | 2 }, + { GROUP_OBJ, -1, 4 | 2 | 1 }, + { GROUP, 15, 4 | 1 }, + { CLASS_OBJ, -1, 4 | 2 | 1 }, + { OTHER_OBJ, -1, 4 | 2 | 1 } + }; #else acl1_text = "user::rwx\n" "group::rwx\n" @@ -468,41 +417,36 @@ 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 acl_free(acl1); +#endif return; } #if HAVE_SUN_ACL /* Check if Solaris filesystem supports POSIX.1e ACLs */ - n = facl_get(fd, 0, &acl); - if (n != 0) + aclp = sunacl_get(GETACL, &aclcnt, fd, NULL); + if (aclp == 0) close(fd); - if (n != 0 && errno == ENOSYS) { - acl_free(acl1); + if (errno == ENOSYS || errno == ENOTSUP) { skipping("POSIX.1e ACLs are not supported on this filesystem"); return; } - failure("facl_get(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); + failure("facl(): errno = %d (%s)", errno, strerror(errno)); + assert(aclp != NULL); - if (acl->acl_type != ACLENT_T) { - acl_free(acl); - acl_free(acl1); - close(fd); - skipping("POSIX.1e ACLs are not supported on this filesystem"); - return; - } - - func = "facl_set()"; - n = facl_set(fd, acl1); + func = "facl()"; + n = facl(fd, SETACL, (int)(sizeof(aclp1)/sizeof(aclp1[0])), aclp1); #else func = "acl_set_fd()"; n = acl_set_fd(fd, acl1); #endif +#if !HAVE_SUN_ACL acl_free(acl1); +#endif if (n != 0) { #if HAVE_SUN_ACL - if (errno == ENOSYS) + if (errno == ENOSYS || errno == ENOTSUP) #else if (errno == EOPNOTSUPP || errno == EINVAL) #endif @@ -537,9 +481,14 @@ DEFINE_TEST(test_acl_platform_posix1e_read) "user:1:r--," "group:15:r--," "mask:rwx"; - n = acl_fromtext(acl2_text, &acl2); - failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); + aclent_t aclp2[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 1, 4 }, + { GROUP_OBJ, -1, 4 | 2 | 1}, + { GROUP, 15, 4 }, + { CLASS_OBJ, -1, 4 | 2 | 1}, + { OTHER_OBJ, -1, 0 } + }; #else acl2_text = "user::rwx\n" "group::rwx\n" @@ -554,17 +503,19 @@ 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 acl_free(acl2); +#endif return; } #if HAVE_SUN_ACL - func = "facl_set()"; - n = facl_set(fd, acl2); + func = "facl()"; + n = facl(fd, SETACL, (int)(sizeof(aclp2) / sizeof(aclp2[0])), aclp2); #else func = "acl_set_fd()"; n = acl_set_fd(fd, acl2); -#endif acl_free(acl2); +#endif if (n != 0) close(fd); failure("%s: errno = %d (%s)", func, errno, strerror(errno)); @@ -587,9 +538,20 @@ DEFINE_TEST(test_acl_platform_posix1e_read) "default:group:15:r--," "default:mask:rwx," "default:other:r-x"; - n = acl_fromtext(acl3_text, &acl3); - failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno)); - assertEqualInt(0, n); + aclent_t aclp3[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 2, 4 }, + { GROUP_OBJ, -1, 4 | 1 }, + { GROUP, 16, 2 }, + { CLASS_OBJ, -1, 4 | 2 | 1 }, + { OTHER_OBJ, -1, 4 | 1 }, + { USER_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1 }, + { USER | ACL_DEFAULT, 1, 4 }, + { GROUP_OBJ | ACL_DEFAULT, -1, 4 | 1 }, + { GROUP | ACL_DEFAULT, 15, 4 }, + { CLASS_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1}, + { OTHER_OBJ | ACL_DEFAULT, -1, 4 | 1 } + }; #else acl3_text = "user::rwx\n" "user:1:r--\n" @@ -603,14 +565,13 @@ DEFINE_TEST(test_acl_platform_posix1e_read) #endif #if HAVE_SUN_ACL - func = "acl_set()"; - n = acl_set("d/d2", acl3); + func = "acl()"; + n = acl("d/d2", SETACL, (int)(sizeof(aclp3) / sizeof(aclp3[0])), aclp3); #else func = "acl_set_file()"; n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3); -#endif acl_free(acl3); - +#endif failure("%s: errno = %d (%s)", func, errno, strerror(errno)); assertEqualInt(0, n); diff --git a/libarchive/test/test_read_disk_directory_traversals.c b/libarchive/test/test_read_disk_directory_traversals.c index fdbfbec91e93..705b3d989cd5 100644 --- a/libarchive/test/test_read_disk_directory_traversals.c +++ b/libarchive/test/test_read_disk_directory_traversals.c @@ -1231,8 +1231,8 @@ test_restore_atime(void) * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and * ARCHIVE_READDISK_HONOR_NODUMP */ - assertNodump("at/f1"); - assertNodump("at/f2"); + assertSetNodump("at/f1"); + assertSetNodump("at/f2"); assertUtimes("at/f1", 886600, 0, 886600, 0); assertUtimes("at/f2", 886611, 0, 886611, 0); assertUtimes("at/fe", 886611, 0, 886611, 0); @@ -1450,7 +1450,7 @@ test_nodump(void) assertMakeFile("nd/f1", 0644, "0123456789"); assertMakeFile("nd/f2", 0644, "hello world"); assertMakeFile("nd/fe", 0644, NULL); - assertNodump("nd/f2"); + assertSetNodump("nd/f2"); assertUtimes("nd/f1", 886600, 0, 886600, 0); assertUtimes("nd/f2", 886611, 0, 886611, 0); assertUtimes("nd/fe", 886611, 0, 886611, 0); diff --git a/tar/bsdtar.1 b/tar/bsdtar.1 index b60f09c5fb27..3e7abe884126 100644 --- a/tar/bsdtar.1 +++ b/tar/bsdtar.1 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 24, 2017 +.Dd February 25, 2017 .Dt TAR 1 .Os .Sh NAME @@ -450,14 +450,7 @@ This is the reverse of .Fl p and the default behavior if .Nm -is run as non-root and can be overridden by also specifying -.Fl Fl acls , -.Fl Fl fflags , -.Fl Fl mac-metadata, -.Fl Fl same-owner , -.Fl Fl same-permissions -and -.Fl Fl xattrs . +is run as non-root. .It Fl Fl no-xattrs (c, r, u, x modes only) Do not archive or extract extended attributes. This is the reverse of @@ -648,15 +641,15 @@ This option suppresses these behaviors. Preserve file permissions. Attempt to restore the full permissions, including owner, file modes, ACLs, extended atributes and extended file flags, if available, for each item -extracted from the archive. This is the default, if +extracted from the archive. This is te reverse of +.Fl Fl no-same-permissions +and the default if .Nm -is being run by root and can be overridden by also specifying +is being run by root and can be partially overridden by also specifying .Fl Fl no-acls , .Fl Fl no-fflags , -.Fl Fl no-mac-metadata, -.Fl Fl no-same-owner , -.Fl Fl no-same-permissions -and +.Fl Fl no-mac-metadata +or .Fl Fl no-xattrs . .It Fl Fl passphrase Ar passphrase The diff --git a/tar/bsdtar.c b/tar/bsdtar.c index a9252a5c7c26..9fc68332e5dc 100644 --- a/tar/bsdtar.c +++ b/tar/bsdtar.c @@ -118,11 +118,11 @@ need_report(void) } #endif -static void long_help(void); +static void long_help(void) __LA_DEAD; static void only_mode(struct bsdtar *, const char *opt, const char *valid); static void set_mode(struct bsdtar *, char opt); -static void version(void); +static void version(void) __LA_DEAD; /* A basic set of security flags to request from libarchive. */ #define SECURITY \ diff --git a/tar/bsdtar.h b/tar/bsdtar.h index ee9c6485fccc..10a2cf2f9bd0 100644 --- a/tar/bsdtar.h +++ b/tar/bsdtar.h @@ -189,7 +189,7 @@ void do_chdir(struct bsdtar *); int edit_pathname(struct bsdtar *, struct archive_entry *); int need_report(void); int pathcmp(const char *a, const char *b); -void safe_fprintf(FILE *, const char *fmt, ...); +void safe_fprintf(FILE *, const char *fmt, ...) __LA_PRINTF(2, 3); void set_chdir(struct bsdtar *, const char *newdir); const char *tar_i64toa(int64_t); void tar_mode_c(struct bsdtar *bsdtar); @@ -197,8 +197,8 @@ void tar_mode_r(struct bsdtar *bsdtar); void tar_mode_t(struct bsdtar *bsdtar); void tar_mode_u(struct bsdtar *bsdtar); void tar_mode_x(struct bsdtar *bsdtar); -void usage(void); -int yes(const char *fmt, ...); +void usage(void) __LA_DEAD; +int yes(const char *fmt, ...) __LA_PRINTF(1, 2); #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) void add_substitution(struct bsdtar *, const char *); diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt index 3dd36019eed4..e6054babcf46 100644 --- a/tar/test/CMakeLists.txt +++ b/tar/test/CMakeLists.txt @@ -34,9 +34,11 @@ IF(ENABLE_TAR AND ENABLE_TEST) test_option_U_upper.c test_option_X_upper.c test_option_a.c + test_option_acls.c test_option_b.c test_option_b64encode.c test_option_exclude.c + test_option_fflags.c test_option_gid_gname.c test_option_grzip.c test_option_j.c @@ -71,6 +73,11 @@ IF(ENABLE_TAR AND ENABLE_TEST) # Register target # ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES}) + IF(ENABLE_ACL) + IF(HAVE_LIBACL) + TARGET_LINK_LIBRARIES(bsdtar_test ${ACL_LIBRARY}) + ENDIF(HAVE_LIBACL) + ENDIF(ENABLE_ACL) SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H) # diff --git a/tar/test/test_option_acls.c b/tar/test/test_option_acls.c new file mode 100644 index 000000000000..5c3fbfd156c8 --- /dev/null +++ b/tar/test/test_option_acls.c @@ -0,0 +1,471 @@ +/*- + * 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 "test.h" +__FBSDID("$FreeBSD$"); + +#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL +static const acl_perm_t acl_perms[] = { +#if HAVE_DARWIN_ACL + ACL_READ_DATA, + ACL_LIST_DIRECTORY, + ACL_WRITE_DATA, + ACL_ADD_FILE, + ACL_EXECUTE, + ACL_SEARCH, + ACL_DELETE, + ACL_APPEND_DATA, + ACL_ADD_SUBDIRECTORY, + ACL_DELETE_CHILD, + ACL_READ_ATTRIBUTES, + ACL_WRITE_ATTRIBUTES, + ACL_READ_EXTATTRIBUTES, + ACL_WRITE_EXTATTRIBUTES, + ACL_READ_SECURITY, + ACL_WRITE_SECURITY, + ACL_CHANGE_OWNER, + ACL_SYNCHRONIZE +#else /* !HAVE_DARWIN_ACL */ + ACL_EXECUTE, + ACL_WRITE, + ACL_READ, +#if HAVE_FREEBSD_NFS4_ACL + ACL_READ_DATA, + ACL_LIST_DIRECTORY, + ACL_WRITE_DATA, + ACL_ADD_FILE, + ACL_APPEND_DATA, + ACL_ADD_SUBDIRECTORY, + ACL_READ_NAMED_ATTRS, + ACL_WRITE_NAMED_ATTRS, + ACL_DELETE_CHILD, + ACL_READ_ATTRIBUTES, + ACL_WRITE_ATTRIBUTES, + ACL_DELETE, + ACL_READ_ACL, + ACL_WRITE_ACL, + ACL_WRITE_OWNER, + ACL_SYNCHRONIZE +#endif /* HAVE_FREEBSD_NFS4_ACL */ +#endif /* !HAVE_DARWIN_ACL */ +}; +#if HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL +static const acl_flag_t acl_flags[] = { +#if HAVE_DARWIN_ACL + ACL_FLAG_DEFER_INHERIT, + ACL_FLAG_NO_INHERIT, + ACL_ENTRY_INHERITED, + ACL_ENTRY_FILE_INHERIT, + ACL_ENTRY_DIRECTORY_INHERIT, + ACL_ENTRY_LIMIT_INHERIT, + ACL_ENTRY_ONLY_INHERIT +#else /* HAVE_FREEBSD_NFS4_ACL */ + ACL_ENTRY_FILE_INHERIT, + ACL_ENTRY_DIRECTORY_INHERIT, + ACL_ENTRY_NO_PROPAGATE_INHERIT, + ACL_ENTRY_INHERIT_ONLY, + ACL_ENTRY_SUCCESSFUL_ACCESS, + ACL_ENTRY_FAILED_ACCESS, + ACL_ENTRY_INHERITED +#endif /* HAVE_FREEBSD_NFS4_ACL */ +}; +#endif /* HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL */ + +/* + * Compare two ACL entries on FreeBSD or on Mac OS X + */ +static int +compare_acl_entry(acl_entry_t ae_a, acl_entry_t ae_b, int is_nfs4) +{ + acl_tag_t tag_a, tag_b; + acl_permset_t permset_a, permset_b; + int perm_a, perm_b, perm_start, perm_end; + void *qual_a, *qual_b; +#if HAVE_FREEBSD_NFS4_ACL + acl_entry_type_t type_a, type_b; +#endif +#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL + acl_flagset_t flagset_a, flagset_b; + int flag_a, flag_b; +#endif + int i, r; + + + /* Compare ACL tag */ + r = acl_get_tag_type(ae_a, &tag_a); + failure("acl_get_tag_type() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_tag_type(ae_b, &tag_b); + failure("acl_get_tag_type() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + if (tag_a != tag_b) + return (0); + + /* Compare ACL qualifier */ +#if HAVE_DARWIN_ACL + if (tag_a == ACL_EXTENDED_ALLOW || tag_b == ACL_EXTENDED_DENY) +#else + if (tag_a == ACL_USER || tag_a == ACL_GROUP) +#endif + { + qual_a = acl_get_qualifier(ae_a); + failure("acl_get_qualifier() error: %s", strerror(errno)); + if (assert(qual_a != NULL) == 0) + return (-1); + qual_b = acl_get_qualifier(ae_b); + failure("acl_get_qualifier() error: %s", strerror(errno)); + if (assert(qual_b != NULL) == 0) { + acl_free(qual_a); + return (-1); + } +#if HAVE_DARWIN_ACL + if (memcmp(((guid_t *)qual_a)->g_guid, + ((guid_t *)qual_b)->g_guid, KAUTH_GUID_SIZE) != 0) +#else + if ((tag_a == ACL_USER && + (*(uid_t *)qual_a != *(uid_t *)qual_b)) || + (tag_a == ACL_GROUP && + (*(gid_t *)qual_a != *(gid_t *)qual_b))) +#endif + { + acl_free(qual_a); + acl_free(qual_b); + return (0); + } + acl_free(qual_a); + acl_free(qual_b); + } + +#if HAVE_FREEBSD_NFS4_ACL + if (is_nfs4) { + /* Compare NFS4 ACL type */ + r = acl_get_entry_type_np(ae_a, &type_a); + failure("acl_get_entry_type_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_entry_type_np(ae_b, &type_b); + failure("acl_get_entry_type_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + if (type_a != type_b) + return (0); + } +#endif + + /* Compare ACL perms */ + r = acl_get_permset(ae_a, &permset_a); + failure("acl_get_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_permset(ae_b, &permset_b); + failure("acl_get_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + + perm_start = 0; + perm_end = (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); +#if HAVE_FREEBSD_NFS4_ACL + if (is_nfs4) + perm_start = 3; + else + perm_end = 3; +#endif + /* Cycle through all perms and compare their value */ + for (i = perm_start; i < perm_end; i++) { +#if HAVE_LIBACL + perm_a = acl_get_perm(permset_a, acl_perms[i]); + perm_b = acl_get_perm(permset_b, acl_perms[i]); +#else + perm_a = acl_get_perm_np(permset_a, acl_perms[i]); + perm_b = acl_get_perm_np(permset_b, acl_perms[i]); +#endif + if (perm_a == -1 || perm_b == -1) + return (-1); + if (perm_a != perm_b) + return (0); + } + +#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL + if (is_nfs4) { + r = acl_get_flagset_np(ae_a, &flagset_a); + failure("acl_get_flagset_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + r = acl_get_flagset_np(ae_b, &flagset_b); + failure("acl_get_flagset_np() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + return (-1); + /* Cycle through all flags and compare their status */ + for (i = 0; i < (int)(sizeof(acl_flags) / sizeof(acl_flags[0])); + i++) { + flag_a = acl_get_flag_np(flagset_a, acl_flags[i]); + flag_b = acl_get_flag_np(flagset_b, acl_flags[i]); + if (flag_a == -1 || flag_b == -1) + return (-1); + if (flag_a != flag_b) + return (0); + } + } +#else /* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL*/ + (void)is_nfs4; /* UNUSED */ +#endif + return (1); +} +#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */ + +#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL +/* + * Clear default ACLs or inheritance flags + */ +static void +clear_inheritance_flags(const char *path, int type) +{ + switch (type) { + case ARCHIVE_TEST_ACL_TYPE_POSIX1E: +#if HAVE_POSIX_ACL + acl_delete_def_file(path); +#else + /* Solaris */ + setTestAcl(path); +#endif + break; + case ARCHIVE_TEST_ACL_TYPE_NFS4: +#if HAVE_NFS4_ACL + setTestAcl(path); +#endif + break; + default: + (void)path; /* UNUSED */ + break; + } +} + +static int +compare_acls(const char *path_a, const char *path_b) +{ + int ret = 1; + int is_nfs4 = 0; +#if HAVE_SUN_ACL + void *acl_a, *acl_b; + int aclcnt_a, aclcnt_b; + aclent_t *aclent_a, *aclent_b; + ace_t *ace_a, *ace_b; + int e; +#else + acl_t acl_a, acl_b; + acl_entry_t aclent_a, aclent_b; + int a, b, r; +#endif + + acl_a = NULL; + acl_b = NULL; +#if HAVE_SUN_ACL + acl_a = sunacl_get(GETACL, &aclcnt_a, 0, path_a); + if (acl_a == NULL) { +#if HAVE_SUN_NFS4_ACL + is_nfs4 = 1; + acl_a = sunacl_get(ACE_GETACL, &aclcnt_a, 0, path_a); +#endif + failure("acl_get() error: %s", strerror(errno)); + if (assert(acl_a != NULL) == 0) + return (-1); +#if HAVE_SUN_NFS4_ACL + acl_b = sunacl_get(ACE_GETACL, &aclcnt_b, 0, path_b); +#endif + } else + acl_b = sunacl_get(GETACL, &aclcnt_b, 0, path_b); + if (acl_b == NULL && (errno == ENOSYS || errno == ENOTSUP)) { + free(acl_a); + return (0); + } + failure("acl_get() error: %s", strerror(errno)); + if (assert(acl_b != NULL) == 0) { + free(acl_a); + return (-1); + } + + if (aclcnt_a != aclcnt_b) { + ret = 0; + goto exit_free; + } + + for (e = 0; e < aclcnt_a; e++) { + if (!is_nfs4) { + aclent_a = &((aclent_t *)acl_a)[e]; + aclent_b = &((aclent_t *)acl_b)[e]; + if (aclent_a->a_type != aclent_b->a_type || + aclent_a->a_id != aclent_b->a_id || + aclent_a->a_perm != aclent_b->a_perm) { + ret = 0; + goto exit_free; + } + } +#if HAVE_SUN_NFS4_ACL + else { + ace_a = &((ace_t *)acl_a)[e]; + ace_b = &((ace_t *)acl_b)[e]; + if (ace_a->a_who != ace_b->a_who || + ace_a->a_access_mask != ace_b->a_access_mask || + ace_a->a_flags != ace_b->a_flags || + ace_a->a_type != ace_b->a_type) { + ret = 0; + goto exit_free; + } + } +#endif + } +#else /* !HAVE_SUN_ACL */ +#if HAVE_DARWIN_ACL + is_nfs4 = 1; + acl_a = acl_get_file(path_a, ACL_TYPE_EXTENDED); +#elif HAVE_FREEBSD_NFS4_ACL + acl_a = acl_get_file(path_a, ACL_TYPE_NFS4); + if (acl_a != NULL) + is_nfs4 = 1; +#endif +#if !HAVE_DARWIN_ACL + if (acl_a == NULL) + acl_a = acl_get_file(path_a, ACL_TYPE_ACCESS); +#endif + failure("acl_get_file() error: %s (%s)", path_a, strerror(errno)); + if (assert(acl_a != NULL) == 0) + return (-1); +#if HAVE_DARWIN_ACL + acl_b = acl_get_file(path_b, ACL_TYPE_EXTENDED); +#elif HAVE_FREEBSD_NFS4_ACL + acl_b = acl_get_file(path_b, ACL_TYPE_NFS4); +#endif +#if !HAVE_DARWIN_ACL + if (acl_b == NULL) { +#if HAVE_FREEBSD_NFS4_ACL + if (is_nfs4) { + acl_free(acl_a); + return (0); + } +#endif + acl_b = acl_get_file(path_b, ACL_TYPE_ACCESS); + } + failure("acl_get_file() error: %s (%s)", path_b, strerror(errno)); + if (assert(acl_b != NULL) == 0) { + acl_free(acl_a); + return (-1); + } +#endif + a = acl_get_entry(acl_a, ACL_FIRST_ENTRY, &aclent_a); + if (a == -1) { + ret = 0; + goto exit_free; + } + b = acl_get_entry(acl_b, ACL_FIRST_ENTRY, &aclent_b); + if (b == -1) { + ret = 0; + goto exit_free; + } +#if HAVE_DARWIN_ACL + while (a == 0 && b == 0) +#else /* FreeBSD, Linux */ + while (a == 1 && b == 1) +#endif + { + r = compare_acl_entry(aclent_a, aclent_b, is_nfs4); + if (r != 1) { + ret = r; + goto exit_free; + } + a = acl_get_entry(acl_a, ACL_NEXT_ENTRY, &aclent_a); + b = acl_get_entry(acl_b, ACL_NEXT_ENTRY, &aclent_b); + } + /* Entry count must match */ + if (a != b) + ret = 0; +#endif /* !HAVE_SUN_ACL */ +exit_free: +#if HAVE_SUN_ACL + free(acl_a); + free(acl_b); +#else + acl_free(acl_a); + acl_free(acl_b); +#endif + return (ret); +} +#endif /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */ + +DEFINE_TEST(test_option_acls) +{ +#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_POSIX_ACL + skipping("ACLs are not supported on this platform"); +#else /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */ + int acltype, r; + + assertMakeFile("f", 0644, "a"); + acltype = setTestAcl("f"); + if (acltype == 0) { + skipping("Can't write ACLs on the filesystem"); + return; + } + + /* Archive it with acls */ + r = systemf("%s -c --no-mac-metadata --acls -f acls.tar f >acls.out 2>acls.err", testprog); + assertEqualInt(r, 0); + + /* Archive it without acls */ + r = systemf("%s -c --no-mac-metadata --no-acls -f noacls.tar f >noacls.out 2>noacls.err", testprog); + assertEqualInt(r, 0); + + /* Extract acls with acls */ + assertMakeDir("acls_acls", 0755); + clear_inheritance_flags("acls_acls", acltype); + r = systemf("%s -x -C acls_acls --no-same-permissions --acls -f acls.tar >acls_acls.out 2>acls_acls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "acls_acls/f"); + assertEqualInt(r, 1); + + /* Extractl acls without acls */ + assertMakeDir("acls_noacls", 0755); + clear_inheritance_flags("acls_noacls", acltype); + r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "acls_noacls/f"); + assertEqualInt(r, 0); + + /* Extract noacls with acls flag */ + assertMakeDir("noacls_acls", 0755); + clear_inheritance_flags("noacls_acls", acltype); + r = systemf("%s -x -C noacls_acls --no-same-permissions --acls -f noacls.tar >noacls_acls.out 2>noacls_acls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "noacls_acls/f"); + assertEqualInt(r, 0); + + /* Extract noacls with noacls */ + assertMakeDir("noacls_noacls", 0755); + clear_inheritance_flags("noacls_noacls", acltype); + r = systemf("%s -x -C noacls_noacls -p --no-acls -f noacls.tar >noacls_noacls.out 2>noacls_noacls.err", testprog); + assertEqualInt(r, 0); + r = compare_acls("f", "noacls_noacls/f"); + assertEqualInt(r, 0); +#endif /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */ +} diff --git a/tar/test/test_option_fflags.c b/tar/test/test_option_fflags.c new file mode 100644 index 000000000000..72fc7ce85644 --- /dev/null +++ b/tar/test/test_option_fflags.c @@ -0,0 +1,74 @@ +/*- + * 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 "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_fflags) +{ + int r; + + if (!canNodump()) { + skipping("Can't test nodump flag on this filesystem"); + return; + } + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + /* Set nodump flag on the file */ + assertSetNodump("f"); + + /* Archive it with fflags */ + r = systemf("%s -c --fflags -f fflags.tar f >fflags.out 2>fflags.err", testprog); + assertEqualInt(r, 0); + + /* Archive it without fflags */ + r = systemf("%s -c --no-fflags -f nofflags.tar f >nofflags.out 2>nofflags.err", testprog); + assertEqualInt(r, 0); + + /* Extract fflags with fflags */ + assertMakeDir("fflags_fflags", 0755); + r = systemf("%s -x -C fflags_fflags --no-same-permissions --fflags -f fflags.tar >fflags_fflags.out 2>fflags_fflags.err", testprog); + assertEqualInt(r, 0); + assertEqualFflags("f", "fflags_fflags/f"); + + /* Extract fflags without fflags */ + assertMakeDir("fflags_nofflags", 0755); + r = systemf("%s -x -C fflags_nofflags -p --no-fflags -f fflags.tar >fflags_nofflags.out 2>fflags_nofflags.err", testprog); + assertEqualInt(r, 0); + assertUnequalFflags("f", "fflags_nofflags/f"); + + /* Extract nofflags with fflags */ + assertMakeDir("nofflags_fflags", 0755); + r = systemf("%s -x -C nofflags_fflags --no-same-permissions --fflags -f nofflags.tar >nofflags_fflags.out 2>nofflags_fflags.err", testprog); + assertEqualInt(r, 0); + assertUnequalFflags("f", "nofflags_fflags/f"); + + /* Extract nofflags with nofflags */ + assertMakeDir("nofflags_nofflags", 0755); + r = systemf("%s -x -C nofflags_nofflags -p --no-fflags -f nofflags.tar >nofflags_nofflags.out 2>nofflags_nofflags.err", testprog); + assertEqualInt(r, 0); + assertUnequalFflags("f", "nofflags_nofflags/f"); +} diff --git a/tar/test/test_option_nodump.c b/tar/test/test_option_nodump.c index 768f64a6dd37..815b08ed9251 100644 --- a/tar/test/test_option_nodump.c +++ b/tar/test/test_option_nodump.c @@ -36,7 +36,7 @@ DEFINE_TEST(test_option_nodump) assertMakeFile("file1", 0644, "file1"); assertMakeFile("file2", 0644, "file2"); assertMakeFile("file3", 0644, "file3"); - assertNodump("file2"); + assertSetNodump("file2"); /* Test 1: Without --nodump */ assertEqualInt(0, systemf("%s -cf test1.tar file1 file2 file3", diff --git a/test_utils/test_common.h b/test_utils/test_common.h index 82e8483f0134..0078054178f0 100644 --- a/test_utils/test_common.h +++ b/test_utils/test_common.h @@ -73,6 +73,12 @@ #include #endif #include +#ifdef HAVE_ACL_LIBACL_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif #ifdef HAVE_WINDOWS_H #include #endif @@ -127,26 +133,37 @@ * 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_ACL_USER +#if HAVE_DECL_ACL_USER #define HAVE_POSIX_ACL 1 -#elif HAVE_ACL_TYPE_EXTENDED +#elif HAVE_DECL_ACL_TYPE_EXTENDED #define HAVE_DARWIN_ACL 1 #endif +#if HAVE_DECL_ACL_TYPE_NFS4 +#define HAVE_FREEBSD_NFS4_ACL 1 +#endif #endif /* * If this platform has , acl_get(), facl_get(), acl_set(), * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions */ -#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T -#define HAVE_SUN_ACL 1 +#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_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL -#define HAVE_NFS4_ACL 1 +#if HAVE_FREEBSD_NFS4_ACL || HAVE_SUN_NFS4_ACL || HAVE_DARWIN_ACL +#define HAVE_NFS4_ACL 1 #endif +#define ARCHIVE_TEST_ACL_TYPE_POSIX1E 1 +#define ARCHIVE_TEST_ACL_TYPE_NFS4 2 + /* * Redefine DEFINE_TEST for use in defining the test functions. */ @@ -158,6 +175,9 @@ /* chdir() and error if it fails */ #define assertChdir(path) \ assertion_chdir(__FILE__, __LINE__, path) +/* Assert two files have the same file flags */ +#define assertEqualFflags(patha, pathb) \ + assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0) /* Assert two integers are the same. Reports value of each one if not. */ #define assertEqualInt(v1,v2) \ assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) @@ -239,10 +259,13 @@ assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile) #define assertMakeSymlink(newfile, linkto) \ assertion_make_symlink(__FILE__, __LINE__, newfile, linkto) -#define assertNodump(path) \ - assertion_nodump(__FILE__, __LINE__, path) +#define assertSetNodump(path) \ + assertion_set_nodump(__FILE__, __LINE__, path) #define assertUmask(mask) \ assertion_umask(__FILE__, __LINE__, mask) +/* Assert that two files have unequal file flags */ +#define assertUnequalFflags(patha, pathb) \ + assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 1) #define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \ assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec) #ifndef PROGRAM @@ -265,6 +288,8 @@ void failure(const char *fmt, ...); int assertion_assert(const char *, int, int, const char *, void *); int assertion_chdir(const char *, int, const char *); +int assertion_compare_fflags(const char *, int, const char *, const char *, + int); int assertion_empty_file(const char *, int, const char *); int assertion_equal_file(const char *, int, const char *, const char *); int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *); @@ -295,8 +320,8 @@ int assertion_make_dir(const char *, int, const char *, int); int assertion_make_file(const char *, int, const char *, int, int, const void *); int assertion_make_hardlink(const char *, int, const char *newpath, const char *); int assertion_make_symlink(const char *, int, const char *newpath, const char *); -int assertion_nodump(const char *, int, const char *); int assertion_non_empty_file(const char *, int, const char *); +int assertion_set_nodump(const char *, int, const char *); int assertion_text_file_contents(const char *, int, const char *buff, const char *f); int assertion_umask(const char *, int, int); int assertion_utimes(const char *, int, const char *, long, long, long, long ); @@ -347,9 +372,17 @@ int canXz(void); /* Return true if this filesystem can handle nodump flags. */ int canNodump(void); +/* Set test ACLs */ +int setTestAcl(const char *path); + /* Return true if the file has large i-node number(>0xffffffff). */ int is_LargeInode(const char *); +#if HAVE_SUN_ACL +/* Fetch ACLs on Solaris using acl() or facl() */ +void *sunacl_get(int cmd, int *aclcnt, int fd, const char *path); +#endif + /* Suck file into string allocated via malloc(). Call free() when done. */ /* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */ char *slurpfile(size_t *, const char *fmt, ...); diff --git a/test_utils/test_main.c b/test_utils/test_main.c index 2ae6b38db06e..86ab5f1a489f 100644 --- a/test_utils/test_main.c +++ b/test_utils/test_main.c @@ -56,6 +56,20 @@ #include #include +/* ACL support */ +#ifdef HAVE_ACL_LIBACL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif +#if HAVE_DARWIN_ACL +#include +#endif + /* * * Windows support routines @@ -1883,9 +1897,103 @@ assertion_utimes(const char *file, int line, #endif /* defined(_WIN32) && !defined(__CYGWIN__) */ } +/* Compare file flags */ +int +assertion_compare_fflags(const char *file, int line, const char *patha, + const char *pathb, int nomatch) +{ +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) + struct stat sa, sb; + + assertion_count(file, line); + + if (stat(patha, &sa) < 0) + return (0); + if (stat(pathb, &sb) < 0) + return (0); + if (!nomatch && sa.st_flags != sb.st_flags) { + failure_start(file, line, "File flags should be identical: " + "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb, + sb.st_flags); + failure_finish(NULL); + return (0); + } + if (nomatch && sa.st_flags == sb.st_flags) { + failure_start(file, line, "File flags should be different: " + "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb, + sb.st_flags); + failure_finish(NULL); + return (0); + } +#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \ + defined(FS_NODUMP_FL)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ + && defined(EXT2_NODUMP_FL)) + int fd, r, flagsa, flagsb; + + assertion_count(file, line); + fd = open(patha, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + failure_start(file, line, "Can't open %s\n", patha); + failure_finish(NULL); + return (0); + } + r = ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &flagsa); + close(fd); + if (r < 0) { + failure_start(file, line, "Can't get flags %s\n", patha); + failure_finish(NULL); + return (0); + } + fd = open(pathb, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + failure_start(file, line, "Can't open %s\n", pathb); + failure_finish(NULL); + return (0); + } + r = ioctl(fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &flagsb); + close(fd); + if (r < 0) { + failure_start(file, line, "Can't get flags %s\n", pathb); + failure_finish(NULL); + return (0); + } + if (!nomatch && flagsa != flagsb) { + failure_start(file, line, "File flags should be identical: " + "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb); + failure_finish(NULL); + return (0); + } + if (nomatch && flagsa == flagsb) { + failure_start(file, line, "File flags should be different: " + "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb); + failure_finish(NULL); + return (0); + } +#else + (void)patha; /* UNUSED */ + (void)pathb; /* UNUSED */ + (void)nomatch; /* UNUSED */ + assertion_count(file, line); +#endif + return (1); +} + /* Set nodump, report failures. */ int -assertion_nodump(const char *file, int line, const char *pathname) +assertion_set_nodump(const char *file, int line, const char *pathname) { #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) int r; @@ -2256,11 +2364,10 @@ canXz(void) /* * Can this filesystem handle nodump flags. */ -#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) - int canNodump(void) { +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) const char *path = "cannodumptest"; struct stat sb; @@ -2271,16 +2378,10 @@ canNodump(void) return (0); if (sb.st_flags & UF_NODUMP) return (1); - return (0); -} - #elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) \ && defined(FS_NODUMP_FL)) || \ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ && defined(EXT2_NODUMP_FL)) -int -canNodump(void) -{ const char *path = "cannodumptest"; int fd, r, flags; @@ -2331,18 +2432,230 @@ canNodump(void) if (flags & EXT2_NODUMP_FL) #endif return (1); - return (0); -} - -#else - -int -canNodump() -{ - return (0); -} - #endif + return (0); +} + +#if HAVE_SUN_ACL +/* Fetch ACLs on Solaris using acl() or facl() */ +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 */ + +/* + * Set test ACLs on a path + * Return values: + * 0: error setting ACLs + * ARCHIVE_TEST_ACL_TYPE_POSIX1E: POSIX.1E ACLs have been set + * ARCHIVE_TEST_ACL_TYPE_NFS4: NFSv4 or extended ACLs have been set + */ +int +setTestAcl(const char *path) +{ +#if HAVE_POSIX_ACL || HAVE_NFS4_ACL + int r = 1; +#if !HAVE_SUN_ACL + acl_t acl; +#endif +#if HAVE_POSIX_ACL /* Linux, FreeBSD POSIX.1e */ + const char *acltext_posix1e = "user:1:rw-," + "group:15:r-x," + "user::rwx," + "group::rwx," + "other::r-x," + "mask::rwx"; +#elif HAVE_SUN_ACL /* Solaris POSIX.1e */ + aclent_t aclp_posix1e[] = { + { USER_OBJ, -1, 4 | 2 | 1 }, + { USER, 1, 4 | 2 }, + { GROUP_OBJ, -1, 4 | 2 | 1 }, + { GROUP, 15, 4 | 1 }, + { CLASS_OBJ, -1, 4 | 2 | 1 }, + { OTHER_OBJ, -1, 4 | 2 | 1 } + }; +#endif +#if HAVE_FREEBSD_NFS4_ACL /* FreeBSD NFS4 */ + const char *acltext_nfs4 = "user:1:rwpaRcs::allow:1," + "group:15:rxaRcs::allow:15," + "owner@:rwpxaARWcCos::allow," + "group@:rwpxaRcs::allow," + "everyone@:rxaRcs::allow"; +#elif HAVE_SUN_NFS4_ACL /* Solaris NFS4 */ + ace_t aclp_nfs4[] = { + { 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL | + ACE_SYNCHRONIZE, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, + { 15, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | + ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, + ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE }, + { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_WRITE_ATTRIBUTES | + ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS | + ACE_READ_ACL | ACE_WRITE_ACL | ACE_WRITE_OWNER | ACE_SYNCHRONIZE, + ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE }, + { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | + ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_GROUP | ACE_IDENTIFIER_GROUP, + ACE_ACCESS_ALLOWED_ACE_TYPE }, + { -1, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | + ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, + ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE } + }; +#elif HAVE_DARWIN_ACL /* Mac OS X */ + acl_entry_t aclent; + acl_permset_t permset; + const uid_t uid = 1; + uuid_t uuid; + int i; + const acl_perm_t acl_perms[] = { + ACL_READ_DATA, + ACL_WRITE_DATA, + ACL_APPEND_DATA, + ACL_EXECUTE, + ACL_READ_ATTRIBUTES, + ACL_READ_EXTATTRIBUTES, + ACL_READ_SECURITY, +#if HAVE_DECL_ACL_SYNCHRONIZE + ACL_SYNCHRONIZE +#endif + }; +#endif /* HAVE_DARWIN_ACL */ + +#if HAVE_FREEBSD_NFS4_ACL + acl = acl_from_text(acltext_nfs4); + failure("acl_from_text() error: %s", strerror(errno)); + if (assert(acl != NULL) == 0) + return (0); +#elif HAVE_DARWIN_ACL + acl = acl_init(1); + failure("acl_init() error: %s", strerror(errno)); + if (assert(acl != NULL) == 0) + return (0); + r = acl_create_entry(&acl, &aclent); + failure("acl_create_entry() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW); + failure("acl_set_tag_type() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = acl_get_permset(aclent, &permset); + failure("acl_get_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + for (i = 0; i < (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); i++) { + r = acl_add_perm(permset, acl_perms[i]); + failure("acl_add_perm() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + } + r = acl_set_permset(aclent, permset); + failure("acl_set_permset() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = mbr_identifier_to_uuid(ID_TYPE_UID, &uid, sizeof(uid_t), uuid); + failure("mbr_identifier_to_uuid() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; + r = acl_set_qualifier(aclent, uuid); + failure("acl_set_qualifier() error: %s", strerror(errno)); + if (assertEqualInt(r, 0) == 0) + goto testacl_free; +#endif /* HAVE_DARWIN_ACL */ + +#if HAVE_NFS4_ACL +#if HAVE_FREEBSD_NFS4_ACL + r = acl_set_file(path, ACL_TYPE_NFS4, acl); + acl_free(acl); +#elif HAVE_SUN_NFS4_ACL + r = acl(path, ACE_SETACL, + (int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4); +#elif HAVE_DARWIN_ACL + r = acl_set_file(path, ACL_TYPE_EXTENDED, acl); + acl_free(acl); +#endif + if (r == 0) + return (ARCHIVE_TEST_ACL_TYPE_NFS4); +#endif /* HAVE_NFS4_ACL */ + +#if HAVE_POSIX_ACL || HAVE_SUN_ACL +#if HAVE_POSIX_ACL + acl = acl_from_text(acltext_posix1e); + failure("acl_from_text() error: %s", strerror(errno)); + if (assert(acl != NULL) == 0) + return (0); + + r = acl_set_file(path, ACL_TYPE_ACCESS, acl); + acl_free(acl); +#elif HAVE_SUN_ACL + r = acl(path, SETACL, + (int)(sizeof(aclp_posix1e)/sizeof(aclp_posix1e[0])), aclp_posix1e); +#endif + if (r == 0) + return (ARCHIVE_TEST_ACL_TYPE_POSIX1E); + else + return (0); +#endif /* HAVE_POSIX_ACL || HAVE_SUN_ACL */ +#if HAVE_DARWIN_ACL +testacl_free: + acl_free(acl); +#endif +#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ + (void)path; /* UNUSED */ + return (0); +} /* * Sleep as needed; useful for verifying disk timestamp changes by