Merge pull request #867 from praiskup/cpio-getgrgid
bsdcpio: show numeric uid/gid when names are not found
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 713295d..bddf30c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -462,8 +462,8 @@
IF(LIBLZMA_FOUND)
SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1)
- SET(CMAKE_REQUIRED_INCLUDES ${LZMA_INCLUDE_DIR})
- SET(CMAKE_REQUIRED_LIBRARIES ${LZMA_LIBRARIES})
+ SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES})
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES})
# Test if a macro is needed for the library.
@@ -572,8 +572,14 @@
LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H)
LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H)
LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H)
+
+CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
+#include <linux/fs.h>
+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)
@@ -1613,29 +1619,29 @@
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 <sys/types.h>
#include <sys/acl.h>
-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 <sys/types.h>
+#include <sys/acl.h>
+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.
@@ -1650,15 +1656,20 @@
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 a699dc5..8c573a9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -186,6 +186,7 @@
libarchive/archive_string_composition.h \
libarchive/archive_string_sprintf.c \
libarchive/archive_util.c \
+ libarchive/archive_version_details.c \
libarchive/archive_virtual.c \
libarchive/archive_write.c \
libarchive/archive_write_disk_acl.c \
@@ -951,10 +952,12 @@
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/NEWS b/NEWS
index 907ab67..fdd971d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+Feb 26, 2017: libarchive 3.3.1 released
+ Security & Feature release
+
Feb 19, 2017: libarchive 3.3.0 released
Security & Feature release
@@ -290,7 +293,7 @@
* libarchive: Mark which entry strings are set; be accurate about
distinguishing empty strings ("") from unset ones (NULL)
* tar: Don't crash reading entries with empty filenames
- * libarchive_test, bsdtar_test, bsdcpio_test: Better detaults:
+ * libarchive_test, bsdtar_test, bsdcpio_test: Better defaults:
run all tests, delete temp dirs, summarize repeated failures
* -no-undefined to libtool for Cygwin
* libarchive_test: Skip large file tests on systems with 32-bit off_t
diff --git a/build/autogen.sh b/build/autogen.sh
index 64767b6..e720e9b 100755
--- a/build/autogen.sh
+++ b/build/autogen.sh
@@ -51,6 +51,7 @@
# Remove developer CFLAGS if a release build is being made
if [ -n "${MAKE_LIBARCHIVE_RELEASE}" ]; then
perl -p -i -e "s/^(DEV_CFLAGS.*)/# \$1/" Makefile.am
+ perl -p -i -e 's/CMAKE_BUILD_TYPE "[A-Za-z]*"/CMAKE_BUILD_TYPE "Release"/' CMakeLists.txt
fi
set -xe
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index ec64d99..8c18edf 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -326,15 +326,6 @@
/* 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 @@
/* 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 @@
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 @@
/* 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 @@
/* Define to 1 if you have the `mbrtowc' function. */
#cmakedefine HAVE_MBRTOWC 1
+/* Define to 1 if you have the <membership.h> header file. */
+#cmakedefine HAVE_MEMBERSHIP_H 1
+
/* Define to 1 if you have the `memmove' function. */
#cmakedefine HAVE_MEMMOVE 1
@@ -1099,6 +1133,9 @@
/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
#cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1
+/* Define to 1 if you have a working FS_IOC_GETFLAGS */
+#cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1
+
/* Define to 1 if you have the <zlib.h> header file. */
#cmakedefine HAVE_ZLIB_H 1
diff --git a/build/version b/build/version
index 3cddc6c..6d36e9c 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3003001dev
+3003002dev
diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt
index 7f1ce5e..0623cc3 100644
--- a/cat/test/CMakeLists.txt
+++ b/cat/test/CMakeLists.txt
@@ -29,6 +29,11 @@
# 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 2a31382..355c754 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@
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.1dev])
-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())
@@ -270,6 +270,19 @@
AC_CHECK_HEADERS([inttypes.h io.h langinfo.h limits.h])
AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h linux/magic.h linux/types.h])
+
+AC_CACHE_CHECK([whether FS_IOC_GETFLAGS is usable],
+ [ac_cv_have_decl_FS_IOC_GETFLAGS],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <sys/ioctl.h>
+@%:@include <linux/fs.h>],
+ [int x = FS_IOC_GETFLAGS])],
+ [AS_VAR_SET([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes])],
+ [AS_VAR_SET([ac_cv_have_decl_FS_IOC_GETFLAGS], [no])])])
+
+AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes],
+ [AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1],
+ [Define to 1 if you have a working FS_IOC_GETFLAGS])])
+
AC_CHECK_HEADERS([locale.h paths.h poll.h pthread.h pwd.h])
AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h])
AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h])
@@ -381,7 +394,7 @@
AC_ARG_WITH([lzo2],
AS_HELP_STRING([--with-lzo2], [Build with LZO support from liblzo2]))
-if test "x$with_lzo2" == "xyes"; then
+if test "x$with_lzo2" = "xyes"; then
AC_CHECK_HEADERS([lzo/lzoconf.h lzo/lzo1x.h])
AC_CHECK_LIB(lzo2,lzo1x_decompress_safe)
fi
@@ -686,6 +699,7 @@
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])
@@ -724,31 +738,23 @@
#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 <sys/acl.h>])
+ # FreeBSD and POSIX
+ # MacOS has no ACL_USER in acl.h
+ AC_CHECK_DECLS([ACL_TYPE_NFS4, ACL_USER],
+ [], [],
+ [#include <sys/types.h>
+ #include <sys/acl.h>])
- # 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 <sys/acl.h>])
-
- # MacOS has ACL_TYPE_EXTENDED instead
- AC_CHECK_DECL([ACL_TYPE_EXTENDED],
- [AC_DEFINE(HAVE_ACL_TYPE_EXTENDED, 1, [True for MacOS ACL support])],
- [],
+ # MacOS ACL support
+ AC_CHECK_DECLS([ACL_TYPE_EXTENDED, ACL_SYNCHRONIZE], [], [],
[#include <sys/types.h>
#include <sys/acl.h>])
# Solaris and derivates ACLs
- AC_CHECK_LIB([sec], [acl_get])
AC_CHECK_TYPES([aclent_t], [], [], [[#include <sys/acl.h>]])
AC_CHECK_TYPES([ace_t], [], [], [[#include <sys/acl.h>]])
- 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 <sys/acl.h>])
fi
# Additional requirements
diff --git a/cpio/cpio.c b/cpio/cpio.c
index 5961960..1691c75 100644
--- a/cpio/cpio.c
+++ b/cpio/cpio.c
@@ -108,22 +108,22 @@
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 ec9509b..cc5fe01 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -62,6 +62,11 @@
# 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/CMakeLists.txt b/libarchive/CMakeLists.txt
index 1f85c01..d55fa2d 100644
--- a/libarchive/CMakeLists.txt
+++ b/libarchive/CMakeLists.txt
@@ -106,6 +106,7 @@
archive_string_composition.h
archive_string_sprintf.c
archive_util.c
+ archive_version_details.c
archive_virtual.c
archive_write.c
archive_write_disk_acl.c
diff --git a/libarchive/archive.h b/libarchive/archive.h
index 605cde8..d6913f3 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 <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -155,7 +155,7 @@
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.3.1dev"
+#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);
@@ -1001,6 +1001,10 @@
#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
/* Default: Xattrs are read from disk. */
#define ARCHIVE_READDISK_NO_XATTR (0x0010)
+/* Default: ACLs are read from disk. */
+#define ARCHIVE_READDISK_NO_ACL (0x0020)
+/* Default: File flags are read from disk. */
+#define ARCHIVE_READDISK_NO_FFLAGS (0x0040)
__LA_DECL int archive_read_disk_set_behavior(struct archive *,
int flags);
diff --git a/libarchive/archive_check_magic.c b/libarchive/archive_check_magic.c
index c695e58..288ce23 100644
--- a/libarchive/archive_check_magic.c
+++ b/libarchive/archive_check_magic.c
@@ -62,7 +62,7 @@
}
}
-static void
+static __LA_DEAD void
diediedie(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
diff --git a/libarchive/archive_digest_private.h b/libarchive/archive_digest_private.h
index b58ffb3..b4fd6ca 100644
--- a/libarchive/archive_digest_private.h
+++ b/libarchive/archive_digest_private.h
@@ -143,6 +143,7 @@
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#include <windows.h>
#include <wincrypt.h>
typedef struct {
int valid;
diff --git a/libarchive/archive_entry.3 b/libarchive/archive_entry.3
index f5e22af..f75916c 100644
--- a/libarchive/archive_entry.3
+++ b/libarchive/archive_entry.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd Feburary 2, 2012
+.Dd February 2, 2012
.Dt ARCHIVE_ENTRY 3
.Os
.Sh NAME
diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
index d4f061b..e268194 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -401,7 +401,7 @@
return (NULL);
}
-int64_t
+la_int64_t
archive_entry_gid(struct archive_entry *entry)
{
return (entry->ae_stat.aest_gid);
@@ -502,7 +502,7 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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;
@@ -1649,7 +1649,10 @@
{ "nosappnd", L"nosappnd", SF_APPEND, 0 },
{ "nosappend", L"nosappend", SF_APPEND, 0 },
#endif
-#ifdef EXT2_APPEND_FL /* 'a' */
+#if defined(FS_APPEND_FL) /* 'a' */
+ { "nosappnd", L"nosappnd", FS_APPEND_FL, 0 },
+ { "nosappend", L"nosappend", FS_APPEND_FL, 0 },
+#elif defined(EXT2_APPEND_FL) /* 'a' */
{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 },
{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0 },
#endif
@@ -1662,7 +1665,11 @@
{ "noschange", L"noschange", SF_IMMUTABLE, 0 },
{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 },
#endif
-#ifdef EXT2_IMMUTABLE_FL /* 'i' */
+#if defined(FS_IMMUTABLE_FL) /* 'i' */
+ { "noschg", L"noschg", FS_IMMUTABLE_FL, 0 },
+ { "noschange", L"noschange", FS_IMMUTABLE_FL, 0 },
+ { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0 },
+#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */
{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 },
{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 },
{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 },
@@ -1686,7 +1693,9 @@
#ifdef UF_NODUMP
{ "nodump", L"nodump", 0, UF_NODUMP},
#endif
-#ifdef EXT2_NODUMP_FL /* 'd' */
+#if defined(FS_NODUMP_FL) /* 'd' */
+ { "nodump", L"nodump", 0, FS_NODUMP_FL},
+#elif defined(EXT2_NODUMP_FL) /* 'd' */
{ "nodump", L"nodump", 0, EXT2_NODUMP_FL},
#endif
#ifdef UF_OPAQUE
@@ -1699,65 +1708,124 @@
#ifdef UF_COMPRESSED
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
#endif
-#ifdef EXT2_UNRM_FL
+#if defined(FS_UNRM_FL)
+ { "nouunlink", L"nouunlink", FS_UNRM_FL, 0},
+#elif defined(EXT2_UNRM_FL)
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
#endif
-#ifdef EXT2_BTREE_FL
+#if defined(FS_BTREE_FL)
+ { "nobtree", L"nobtree", FS_BTREE_FL, 0 },
+#elif defined(EXT2_BTREE_FL)
{ "nobtree", L"nobtree", EXT2_BTREE_FL, 0 },
#endif
-#ifdef EXT2_ECOMPR_FL
+#if defined(FS_ECOMPR_FL)
+ { "nocomperr", L"nocomperr", FS_ECOMPR_FL, 0 },
+#elif defined(EXT2_ECOMPR_FL)
{ "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 },
#endif
-#ifdef EXT2_COMPR_FL /* 'c' */
+#if defined(FS_COMPR_FL) /* 'c' */
+ { "nocompress", L"nocompress", FS_COMPR_FL, 0 },
+#elif defined(EXT2_COMPR_FL) /* 'c' */
{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0 },
#endif
-#ifdef EXT2_NOATIME_FL /* 'A' */
+#if defined(FS_NOATIME_FL) /* 'A' */
+ { "noatime", L"noatime", 0, FS_NOATIME_FL},
+#elif defined(EXT2_NOATIME_FL) /* 'A' */
{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},
#endif
-#ifdef EXT2_DIRTY_FL
+#if defined(FS_DIRTY_FL)
+ { "nocompdirty",L"nocompdirty", FS_DIRTY_FL, 0},
+#elif defined(EXT2_DIRTY_FL)
{ "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0},
#endif
-#ifdef EXT2_COMPRBLK_FL
-#ifdef EXT2_NOCOMPR_FL
+#if defined(FS_COMPRBLK_FL)
+#if defined(FS_NOCOMPR_FL)
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, FS_NOCOMPR_FL},
+#else
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, 0},
+#endif
+#elif defined(EXT2_COMPRBLK_FL)
+#if defined(EXT2_NOCOMPR_FL)
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
#else
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0},
#endif
#endif
-#ifdef EXT2_DIRSYNC_FL
+#if defined(FS_DIRSYNC_FL)
+ { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},
+#elif defined(EXT2_DIRSYNC_FL)
{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
#endif
-#ifdef EXT2_INDEX_FL
+#if defined(FS_INDEX_FL)
+ { "nohashidx", L"nohashidx", FS_INDEX_FL, 0},
+#elif defined(EXT2_INDEX_FL)
{ "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0},
#endif
-#ifdef EXT2_IMAGIC_FL
+#if defined(FS_IMAGIC_FL)
+ { "noimagic", L"noimagic", FS_IMAGIC_FL, 0},
+#elif defined(EXT2_IMAGIC_FL)
{ "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0},
#endif
-#ifdef EXT3_JOURNAL_DATA_FL
+#if defined(FS_JOURNAL_DATA_FL)
+ { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},
+#elif defined(EXT3_JOURNAL_DATA_FL)
{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
#endif
-#ifdef EXT2_SECRM_FL
+#if defined(FS_SECRM_FL)
+ { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},
+#elif defined(EXT2_SECRM_FL)
{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
#endif
-#ifdef EXT2_SYNC_FL
+#if defined(FS_SYNC_FL)
+ { "nosync", L"nosync", FS_SYNC_FL, 0},
+#elif defined(EXT2_SYNC_FL)
{ "nosync", L"nosync", EXT2_SYNC_FL, 0},
#endif
-#ifdef EXT2_NOTAIL_FL
+#if defined(FS_NOTAIL_FL)
+ { "notail", L"notail", 0, FS_NOTAIL_FL},
+#elif defined(EXT2_NOTAIL_FL)
{ "notail", L"notail", 0, EXT2_NOTAIL_FL},
#endif
-#ifdef EXT2_TOPDIR_FL
+#if defined(FS_TOPDIR_FL)
+ { "notopdir", L"notopdir", FS_TOPDIR_FL, 0},
+#elif defined(EXT2_TOPDIR_FL)
{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
#endif
-#ifdef EXT2_RESERVED_FL
+#ifdef FS_ENCRYPT_FL
+ { "noencrypt", L"noencrypt", FS_ENCRYPT_FL, 0},
+#endif
+#ifdef FS_HUGE_FILE_FL
+ { "nohugefile", L"nohugefile", FS_HUGE_FILE_FL, 0},
+#endif
+#ifdef FS_EXTENT_FL
+ { "noextent", L"noextent", FS_EXTENT_FL, 0},
+#endif
+#ifdef FS_EA_INODE_FL
+ { "noeainode", L"noeainode", FS_EA_INODE_FL, 0},
+#endif
+#ifdef FS_EOFBLOCKS_FL
+ { "noeofblocks",L"noeofblocks", FS_EOFBLOCKS_FL, 0},
+#endif
+#ifdef FS_NOCOW_FL
+ { "nocow", L"nocow", FS_NOCOW_FL, 0},
+#endif
+#ifdef FS_INLINE_DATA_FL
+ { "noinlinedata",L"noinlinedata", FS_INLINE_DATA_FL, 0},
+#endif
+#ifdef FS_PROJINHERIT_FL
+ { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},
+#endif
+#if defined(FS_RESERVED_FL)
+ { "noreserved", L"noreserved", FS_RESERVED_FL, 0},
+#elif defined(EXT2_RESERVED_FL)
{ "noreserved", L"noreserved", EXT2_RESERVED_FL, 0},
#endif
-
{ NULL, NULL, 0, 0 }
};
diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h
index 7645f0c..bcc2962 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 c5115f7..534dbfa 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 ,
@@ -267,7 +267,7 @@
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
Do not propagate inherit flags. Only first-level entries inherit ACLs.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
-Trigger alarm or audit on succesful access.
+Trigger alarm or audit on successful access.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
Trigger alarm or audit on failed access.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
@@ -279,7 +279,7 @@
.Fn archive_entry_acl_add_entry_w
add a single ACL entry.
For the access ACL and non-extended principals, the classic Unix permissions
-are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
+are updated. An archive entry cannot contain both POSIX.1e and NFSv4 ACL
entries.
.Pp
.Fn archive_entry_acl_clear
@@ -303,7 +303,7 @@
for NFSv4 ACLs. For POSIX.1e ACLs if
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
is included and at least one extended ACL entry is found,
-the three non-extened ACLs are added.
+the three non-extended ACLs are added.
.Pp
.Fn archive_entry_acl_from_text
and
@@ -367,7 +367,7 @@
.Fn archive_entry_acl_to_text_w
convert the ACL entries for the given type into a
.Pq wide
-string of ACL entries separated by newline. If the the pointer
+string of ACL entries separated by newline. If the pointer
.Fa len_p
is not NULL, then the function shall return the length of the string
.Pq not including the NULL terminator
diff --git a/libarchive/archive_entry_paths.3 b/libarchive/archive_entry_paths.3
index fd22cf7..f647212 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 340c5ea..aae3648 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_hmac.c b/libarchive/archive_hmac.c
index 1e0ae28..f299655 100644
--- a/libarchive/archive_hmac.c
+++ b/libarchive/archive_hmac.c
@@ -76,6 +76,10 @@
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#ifndef BCRYPT_HASH_REUSABLE_FLAG
+# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
+#endif
+
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h
index c9a9602..01d6a70 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 <sys/acl.h>, acl_get(), facl_get(), acl_set(),
+ * If this platform has <sys/acl.h>, acl(), facl() and ACLENT_T
* facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
*/
-#if HAVE_SYS_ACL_H && HAVE_ACL_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 2a5c130..55e4bbb 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 @@
.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 @@
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 591a212..1c94afd 100644
--- a/libarchive/archive_read_disk_entry_from_file.c
+++ b/libarchive/archive_read_disk_entry_from_file.c
@@ -40,8 +40,6 @@
#endif
#ifdef HAVE_DARWIN_ACL
#include <membership.h>
-#include <grp.h>
-#include <pwd.h>
#endif
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
@@ -124,11 +122,9 @@
#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
@@ -203,15 +199,17 @@
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
/* On FreeBSD, we get flags for free with the stat. */
/* TODO: Does this belong in copy_stat()? */
- if (st->st_flags != 0)
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
archive_entry_set_fflags(entry, st->st_flags, 0);
#endif
-#if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/* Linux requires an extra ioctl to pull the flags. Although
* this is an extra step, it has a nice side-effect: We get an
* open file descriptor which we can use in the subsequent lookups. */
- if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
+ (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
if (fd < 0) {
if (a->tree != NULL)
fd = a->open_on_current_dir(a->tree, path,
@@ -223,7 +221,13 @@
}
if (fd >= 0) {
int stflags;
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
+ r = ioctl(fd,
+#if defined(FS_IOC_GETFLAGS)
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &stflags);
if (r == 0 && stflags != 0)
archive_entry_set_fflags(entry, stflags, 0);
}
@@ -269,13 +273,15 @@
}
#endif /* HAVE_READLINK || HAVE_READLINKAT */
- r = setup_acls(a, entry, &fd);
- if (!a->suppress_xattr) {
+ r = 0;
+ if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
+ r = setup_acls(a, entry, &fd);
+ if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
}
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
r1 = setup_mac_metadata(a, entry, &fd);
if (r1 < r)
r = r1;
@@ -425,14 +431,71 @@
#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
@@ -444,7 +507,8 @@
{
const char *accpath;
#if HAVE_SUN_ACL
- acl_t *acl;
+ void *aclp;
+ int aclcnt;
#else
acl_t acl;
#endif
@@ -481,14 +545,17 @@
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
@@ -502,47 +569,62 @@
&& (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
/*
@@ -559,12 +641,16 @@
}
#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);
@@ -573,25 +659,56 @@
&& (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");
@@ -599,6 +716,7 @@
}
}
+#if !HAVE_SUN_ACL
/* Only directories can have default ACLs. */
if (S_ISDIR(archive_entry_mode(entry))) {
#if HAVE_ACL_GET_FD_NP
@@ -618,7 +736,8 @@
}
}
}
-#endif /* HAVE_POSIX_ACL */
+#endif /* !HAVE_SUN_ACL */
+#endif /* HAVE_POSIX_ACL || HAVE_SUN_ACL */
return (ARCHIVE_OK);
}
@@ -664,12 +783,14 @@
{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},
@@ -698,14 +819,16 @@
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},
@@ -720,7 +843,7 @@
{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 */
@@ -731,8 +854,6 @@
void *q;
uid_t ugid;
int r, idtype;
- struct passwd *pwd;
- struct group *grp;
q = acl_get_qualifier(acl_entry);
if (q == NULL)
@@ -744,24 +865,12 @@
}
if (idtype == ID_TYPE_UID) {
*ae_tag = ARCHIVE_ENTRY_ACL_USER;
- pwd = getpwuuid(q);
- if (pwd == NULL) {
- *ae_id = ugid;
- *ae_name = NULL;
- } else {
- *ae_id = pwd->pw_uid;
- *ae_name = archive_read_disk_uname(a, *ae_id);
- }
+ *ae_id = ugid;
+ *ae_name = archive_read_disk_uname(a, *ae_id);
} else if (idtype == ID_TYPE_GID) {
*ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
- grp = getgruuid(q);
- if (grp == NULL) {
- *ae_id = ugid;
- *ae_name = NULL;
- } else {
- *ae_id = grp->gr_gid;
- *ae_name = archive_read_disk_gname(a, *ae_id);
- }
+ *ae_id = ugid;
+ *ae_name = archive_read_disk_gname(a, *ae_id);
} else
r = 1;
@@ -863,9 +972,11 @@
* 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;
@@ -876,30 +987,25 @@
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
*
@@ -984,13 +1090,13 @@
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.
@@ -998,8 +1104,7 @@
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);
@@ -1008,6 +1113,9 @@
}
*trivialp = 1;
+#else /* !HAVE_SUN_NFS4_ACL */
+ (void)aclp; /* UNUSED */
+#endif /* !HAVE_SUN_NFS4_ACL */
return (0);
}
#endif /* HAVE_SUN_ACL */
@@ -1018,27 +1126,29 @@
*/
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) {
@@ -1090,8 +1200,10 @@
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
@@ -1138,7 +1250,8 @@
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);
@@ -1155,11 +1268,11 @@
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;
@@ -1171,7 +1284,7 @@
#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.
@@ -1262,7 +1375,7 @@
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;
@@ -1297,9 +1410,9 @@
// 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
*/
@@ -1326,7 +1439,7 @@
"Invalid NFSv4 ACL entry type");
return (ARCHIVE_WARN);
}
-#endif /* HAVE_ACL_TYPE_NFS4 */
+#endif /* HAVE_FREEBSD_NFS4_ACL */
/*
* Libarchive stores "flag" (NFSv4 inheritance bits)
@@ -1351,7 +1464,7 @@
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,
@@ -1372,6 +1485,11 @@
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_disk_posix.c b/libarchive/archive_read_disk_posix.c
index b893704..6961ae6 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -465,8 +465,7 @@
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
a->open_on_current_dir = open_on_current_dir;
a->tree_current_dir_fd = tree_current_dir_fd;
a->tree_enter_working_dir = tree_enter_working_dir;
@@ -563,25 +562,19 @@
int
archive_read_disk_set_atime_restored(struct archive *_a)
{
-#ifndef HAVE_UTIMES
- static int warning_done = 0;
-#endif
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
#ifdef HAVE_UTIMES
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
#else
- if (warning_done)
- /* Warning was already emitted; suppress further warnings. */
- return (ARCHIVE_OK);
-
+ /* Display warning and unset flag */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore access time on this system");
- warning_done = 1;
+ a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME;
return (ARCHIVE_WARN);
#endif
}
@@ -595,29 +588,14 @@
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
- if (flags & ARCHIVE_READDISK_NO_XATTR)
- a->suppress_xattr = 1;
- else
- a->suppress_xattr = 0;
return (r);
}
@@ -918,7 +896,7 @@
} while (lst == NULL);
#ifdef __APPLE__
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
/* If we're using copyfile(), ignore "._XXX" files. */
const char *bname = strrchr(tree_current_path(t), '/');
if (bname == NULL)
@@ -989,7 +967,7 @@
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
descend = 0;
}
@@ -999,12 +977,14 @@
* Honor nodump flag.
* If the file is marked with nodump flag, do not return this entry.
*/
- if (a->honor_nodump) {
+ if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) {
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
if (st->st_flags & UF_NODUMP)
return (ARCHIVE_RETRY);
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
- defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
int stflags;
@@ -1013,9 +993,18 @@
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
__archive_ensure_cloexec_flag(t->entry_fd);
if (t->entry_fd >= 0) {
- r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
+ r = ioctl(t->entry_fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
&stflags);
+#ifdef FS_NODUMP_FL
+ if (r == 0 && (stflags & FS_NODUMP_FL) != 0)
+#else
if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
+#endif
return (ARCHIVE_RETRY);
}
}
@@ -1340,10 +1329,11 @@
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
a->tree = tree_open(pathname, a->symlink_mode,
- a->restore_time);
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
@@ -2132,7 +2122,7 @@
static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->flags |= onInitialDir;
t->visit_type = 0;
t->tree_errno = 0;
diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h
index 2569321..b5a8328 100644
--- a/libarchive/archive_read_disk_private.h
+++ b/libarchive/archive_read_disk_private.h
@@ -63,16 +63,8 @@
int (*tree_current_dir_fd)(struct tree*);
int (*tree_enter_working_dir)(struct tree*);
- /* Set 1 if users request to restore atime . */
- int restore_time;
- /* Set 1 if users request to honor nodump flag . */
- int honor_nodump;
- /* Set 1 if users request to enable mac copyfile. */
- int enable_copyfile;
- /* Set 1 if users request to traverse mount points. */
- int traverse_mount_points;
- /* Set 1 if users want to suppress xattr information. */
- int suppress_xattr;
+ /* Bitfield with ARCHIVE_READDISK_* tunables */
+ int flags;
const char * (*lookup_gname)(void *private, int64_t gid);
void (*cleanup_gname)(void *private);
diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c
index 27b75e3..3b90330 100644
--- a/libarchive/archive_read_disk_windows.c
+++ b/libarchive/archive_read_disk_windows.c
@@ -398,8 +398,7 @@
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
return (&a->archive);
}
@@ -495,7 +494,7 @@
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
@@ -510,25 +509,14 @@
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
return (r);
}
@@ -852,7 +840,7 @@
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
return (ARCHIVE_RETRY);
}
@@ -1219,9 +1207,11 @@
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
- a->tree = tree_open(pathname, a->symlink_mode, a->restore_time);
+ a->tree = tree_open(pathname, a->symlink_mode,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate directory traversal data");
@@ -1519,7 +1509,7 @@
struct archive_wstring ws;
wchar_t *pathname, *p, *base;
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->visit_type = 0;
t->tree_errno = 0;
t->full_path_dir_length = 0;
diff --git a/libarchive/archive_read_format.3 b/libarchive/archive_read_format.3
index 53b9a7e..91c5d2c 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 4d8272c..0249456 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_mtree.c b/libarchive/archive_read_support_format_mtree.c
index 4231ff5..00d3250 100644
--- a/libarchive/archive_read_support_format_mtree.c
+++ b/libarchive/archive_read_support_format_mtree.c
@@ -1857,33 +1857,38 @@
* Note that this implementation does not (and should not!) obey
* locale settings; you cannot simply substitute strtol here, since
* it does obey locale.
+ *
+ * Convert the number pointed to by 'p' into a 64-bit signed integer.
+ * On return, 'p' points to the first non-digit following the number.
+ * On overflow, the function returns INT64_MIN or INT64_MAX.
*/
static int64_t
mtree_atol10(char **p)
{
- int64_t l, limit, last_digit_limit;
- int base, digit, sign;
-
- base = 10;
+ const int base = 10;
+ const int64_t limit = INT64_MAX / base;
+ const int64_t last_digit_limit = INT64_MAX % base;
+ int64_t l;
+ int sign;
if (**p == '-') {
sign = -1;
- limit = ((uint64_t)(INT64_MAX) + 1) / base;
- last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
++(*p);
} else {
sign = 1;
- limit = INT64_MAX / base;
- last_digit_limit = INT64_MAX % base;
}
l = 0;
- digit = **p - '0';
- while (digit >= 0 && digit < base) {
- if (l > limit || (l == limit && digit > last_digit_limit))
+ while (**p >= '0' && **p < '0' + base) {
+ int digit = **p - '0';
+ if (l > limit || (l == limit && digit > last_digit_limit)) {
+ while (**p >= '0' && **p < '0' + base) {
+ ++(*p);
+ }
return (sign < 0) ? INT64_MIN : INT64_MAX;
+ }
l = (l * base) + digit;
- digit = *++(*p) - '0';
+ ++(*p);
}
return (sign < 0) ? -l : l;
}
diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c
index bd7f13d..30d5bc8 100644
--- a/libarchive/archive_read_support_format_tar.c
+++ b/libarchive/archive_read_support_format_tar.c
@@ -155,6 +155,7 @@
int compat_2x;
int process_mac_extensions;
int read_concatenated_archives;
+ int realsize_override;
};
static int archive_block_is_null(const char *p);
@@ -527,6 +528,7 @@
tar->entry_offset = 0;
gnu_clear_sparse_list(tar);
tar->realsize = -1; /* Mark this as "unset" */
+ tar->realsize_override = 0;
/* Setup default string conversion. */
tar->sconv = tar->opt_sconv;
@@ -1894,6 +1896,7 @@
if (strcmp(key, "GNU.sparse.size") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
+ tar->realsize_override = 1;
}
/* GNU "0.1" sparse pax format. */
@@ -1925,6 +1928,7 @@
if (strcmp(key, "GNU.sparse.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
+ tar->realsize_override = 1;
}
break;
case 'L':
@@ -1977,6 +1981,7 @@
tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
+ tar->realsize_override = 1;
archive_entry_set_size(entry, tar->realsize);
} else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
pax_attribute_schily_xattr(entry, key, value,
@@ -2055,14 +2060,12 @@
tar->entry_bytes_remaining
= tar_atol10(value, strlen(value));
/*
- * But, "size" is not necessarily the size of
- * the file on disk; if this is a sparse file,
- * the disk size may have already been set from
- * GNU.sparse.realsize or GNU.sparse.size or
- * an old GNU header field or SCHILY.realsize
- * or ....
+ * The "size" pax header keyword always overrides the
+ * "size" field in the tar header.
+ * GNU.sparse.realsize, GNU.sparse.size and
+ * SCHILY.realsize override this value.
*/
- if (tar->realsize < 0) {
+ if (!tar->realsize_override) {
archive_entry_set_size(entry,
tar->entry_bytes_remaining);
tar->realsize
@@ -2206,6 +2209,7 @@
tar->realsize
= tar_atol(header->realsize, sizeof(header->realsize));
archive_entry_set_size(entry, tar->realsize);
+ tar->realsize_override = 1;
}
if (header->sparse[0].offset[0] != 0) {
diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c
index 5e22438..e875385 100644
--- a/libarchive/archive_read_support_format_warc.c
+++ b/libarchive/archive_read_support_format_warc.c
@@ -543,7 +543,7 @@
/* as a courtesy to our callers, and since this is a non-standard
* routine, we skip leading whitespace */
- while (isblank((unsigned char)*s))
+ while (*s == ' ' || *s == '\t')
++s;
/* read year */
@@ -589,6 +589,7 @@
_warc_rdver(const char *buf, size_t bsz)
{
static const char magic[] = "WARC/";
+ const char *c;
unsigned int ver = 0U;
unsigned int end = 0U;
@@ -599,9 +600,10 @@
/* 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;
@@ -615,11 +617,12 @@
* WARC below version 0.12 has a space-separated header
* WARC 0.12 and above terminates the version with a CRLF
*/
+ c = buf + 3U + end;
if (ver >= 1200U) {
- if (memcmp(buf + 3U + end, "\r\n", 2U) != 0)
+ if (memcmp(c, "\r\n", 2U) != 0)
ver = 0U;
} else if (ver < 1200U) {
- if (!isblank(*(buf + 3U + end)))
+ if (*c != ' ' && *c != '\t')
ver = 0U;
}
}
@@ -643,7 +646,7 @@
}
/* overread whitespace */
- while (val < eol && isblank((unsigned char)*val))
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
if (val + 8U == eol) {
@@ -673,7 +676,7 @@
return res;
}
- while (val < eol && isblank((unsigned char)*val))
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
/* overread URL designators */
@@ -684,7 +687,7 @@
/* 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;
}
@@ -731,10 +734,10 @@
}
/* skip leading whitespace */
- while (val < eol && isblank(*val))
+ 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_util.c b/libarchive/archive_util.c
index 6b3bd61..a751868 100644
--- a/libarchive/archive_util.c
+++ b/libarchive/archive_util.c
@@ -89,88 +89,6 @@
return (ARCHIVE_VERSION_STRING);
}
-const char *
-archive_version_details(void)
-{
- static struct archive_string str;
- static int init = 0;
- const char *zlib = archive_zlib_version();
- const char *liblzma = archive_liblzma_version();
- const char *bzlib = archive_bzlib_version();
- const char *liblz4 = archive_liblz4_version();
-
- if (!init) {
- archive_string_init(&str);
-
- archive_strcat(&str, ARCHIVE_VERSION_STRING);
- if (zlib != NULL) {
- archive_strcat(&str, " zlib/");
- archive_strcat(&str, zlib);
- }
- if (liblzma) {
- archive_strcat(&str, " liblzma/");
- archive_strcat(&str, liblzma);
- }
- if (bzlib) {
- const char *p = bzlib;
- const char *sep = strchr(p, ',');
- if (sep == NULL)
- sep = p + strlen(p);
- archive_strcat(&str, " bz2lib/");
- archive_strncat(&str, p, sep - p);
- }
- if (liblz4) {
- archive_strcat(&str, " liblz4/");
- archive_strcat(&str, liblz4);
- }
- }
- return str.s;
-}
-
-const char *
-archive_zlib_version(void)
-{
-#ifdef HAVE_ZLIB_H
- return ZLIB_VERSION;
-#else
- return NULL;
-#endif
-}
-
-const char *
-archive_liblzma_version(void)
-{
-#ifdef HAVE_LZMA_H
- return LZMA_VERSION_STRING;
-#else
- return NULL;
-#endif
-}
-
-const char *
-archive_bzlib_version(void)
-{
-#ifdef HAVE_BZLIB_H
- return BZ2_bzlibVersion();
-#else
- return NULL;
-#endif
-}
-
-const char *
-archive_liblz4_version(void)
-{
-#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
-#define str(s) #s
-#define NUMBER(x) str(x)
- return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
-#undef NUMBER
-#undef str
-#else
- return NULL;
-#endif
-}
-
int
archive_errno(struct archive *a)
{
diff --git a/libarchive/archive_version_details.c b/libarchive/archive_version_details.c
new file mode 100644
index 0000000..813f0f3
--- /dev/null
+++ b/libarchive/archive_version_details.c
@@ -0,0 +1,133 @@
+/*-
+ * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+#ifdef HAVE_LZMA_H
+#include <lzma.h>
+#endif
+#ifdef HAVE_BZLIB_H
+#include <bzlib.h>
+#endif
+#ifdef HAVE_LZ4_H
+#include <lz4.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+
+const char *
+archive_version_details(void)
+{
+ static struct archive_string str;
+ static int init = 0;
+ const char *zlib = archive_zlib_version();
+ const char *liblzma = archive_liblzma_version();
+ const char *bzlib = archive_bzlib_version();
+ const char *liblz4 = archive_liblz4_version();
+
+ if (!init) {
+ archive_string_init(&str);
+
+ archive_strcat(&str, ARCHIVE_VERSION_STRING);
+ if (zlib != NULL) {
+ archive_strcat(&str, " zlib/");
+ archive_strcat(&str, zlib);
+ }
+ if (liblzma) {
+ archive_strcat(&str, " liblzma/");
+ archive_strcat(&str, liblzma);
+ }
+ if (bzlib) {
+ const char *p = bzlib;
+ const char *sep = strchr(p, ',');
+ if (sep == NULL)
+ sep = p + strlen(p);
+ archive_strcat(&str, " bz2lib/");
+ archive_strncat(&str, p, sep - p);
+ }
+ if (liblz4) {
+ archive_strcat(&str, " liblz4/");
+ archive_strcat(&str, liblz4);
+ }
+ }
+ return str.s;
+}
+
+const char *
+archive_zlib_version(void)
+{
+#ifdef HAVE_ZLIB_H
+ return ZLIB_VERSION;
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_liblzma_version(void)
+{
+#ifdef HAVE_LZMA_H
+ return LZMA_VERSION_STRING;
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_bzlib_version(void)
+{
+#ifdef HAVE_BZLIB_H
+ return BZ2_bzlibVersion();
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_liblz4_version(void)
+{
+#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
+#define str(s) #s
+#define NUMBER(x) str(x)
+ return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
+#undef NUMBER
+#undef str
+#else
+ return NULL;
+#endif
+}
diff --git a/libarchive/archive_write_data.3 b/libarchive/archive_write_data.3
index 0cdd25f..9c16cd9 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 @@
.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 ba6c970..4891b85 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 @@
.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 @@
.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 144ab7e..4979274 100644
--- a/libarchive/archive_write_disk_acl.c
+++ b/libarchive/archive_write_disk_acl.c
@@ -61,17 +61,18 @@
#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_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 @@
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 @@
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 @@
{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 @@
#endif
#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
+#endif /* !HAVE_SUN_ACL || HAVE_SUN_NFS4_ACL */
#if HAVE_NFS4_ACL
/*
@@ -192,14 +199,16 @@
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 @@
{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 @@
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 @@
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 @@
#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);
@@ -392,8 +424,7 @@
acl_set_tag_type(acl_entry, ACL_USER);
acl_set_qualifier(acl_entry, &ae_uid);
#else /* MacOS */
- if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
- sizeof(uid_t), ae_uuid) != 0)
+ if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0)
continue;
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
continue;
@@ -405,8 +436,7 @@
acl_set_tag_type(acl_entry, ACL_GROUP);
acl_set_qualifier(acl_entry, &ae_gid);
#else /* MacOS */
- if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
- sizeof(gid_t), ae_uuid) != 0)
+ if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0)
continue;
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
continue;
@@ -425,7 +455,7 @@
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 +469,11 @@
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 +498,7 @@
else
r = -1;
break;
+#endif
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
if (aclent == NULL)
r = -1;
@@ -497,7 +529,7 @@
#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 +543,20 @@
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 +571,7 @@
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 +588,11 @@
#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 +648,7 @@
#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 +667,7 @@
} 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 +685,11 @@
}
}
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 20450ba..bf58b6d 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -1712,7 +1712,8 @@
const void *metadata;
size_t metadata_size;
metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
- if (metadata == NULL || metadata_size == 0) {
+ if ((a->todo & TODO_MAC_METADATA) == 0 ||
+ metadata == NULL || metadata_size == 0) {
#endif
r2 = archive_write_disk_set_acls(&a->archive, a->fd,
archive_entry_pathname(a->entry),
@@ -2293,7 +2294,8 @@
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
#ifdef HAVE_DARWIN_ACL
- if (p->mac_metadata == NULL ||
+ if ((p->fixup & TODO_MAC_METADATA) == 0 ||
+ p->mac_metadata == NULL ||
p->mac_metadata_size == 0)
#endif
archive_write_disk_set_acls(&a->archive,
@@ -2465,7 +2467,7 @@
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);
}
/*
@@ -2571,7 +2573,7 @@
* 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;
}
@@ -2580,7 +2582,7 @@
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;
}
@@ -2597,7 +2599,7 @@
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;
@@ -2616,7 +2618,7 @@
/*
if (!S_ISLNK(path)) {
fsobj_error(a_eno, a_estr, 0,
- "Removing symlink %s", path);
+ "Removing symlink ", path);
}
*/
/* Symlink gone. No more problem! */
@@ -2628,7 +2630,7 @@
tail[0] = c;
fsobj_error(a_eno, a_estr, 0,
"Cannot remove intervening "
- "symlink %s", path);
+ "symlink ", path);
res = ARCHIVE_FAILED;
break;
}
@@ -2650,7 +2652,7 @@
} else {
fsobj_error(a_eno, a_estr,
errno,
- "Could not stat %s", path);
+ "Could not stat ", path);
res = (ARCHIVE_FAILED);
break;
}
@@ -2659,7 +2661,7 @@
tail[0] = c;
fsobj_error(a_eno, a_estr,
errno,
- "Could not chdir %s", path);
+ "Could not chdir ", path);
res = (ARCHIVE_FATAL);
break;
}
@@ -2672,14 +2674,14 @@
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;
}
@@ -3465,12 +3467,19 @@
#ifdef UF_APPEND
critical_flags |= UF_APPEND;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ critical_flags |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
critical_flags |= EXT2_APPEND_FL;
#endif
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ critical_flags |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
critical_flags |= EXT2_IMMUTABLE_FL;
#endif
+#ifdef FS_JOURNAL_DATA_FL
+ critical_flags |= FS_JOURNAL_DATA_FL;
+#endif
if (a->todo & TODO_FFLAGS) {
archive_entry_fflags(a->entry, &set, &clear);
@@ -3582,7 +3591,10 @@
return (ARCHIVE_WARN);
}
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/*
* Linux uses ioctl() to read and write file flags.
*/
@@ -3595,7 +3607,7 @@
int newflags, oldflags;
int sf_mask = 0;
- if (set == 0 && clear == 0)
+ if (set == 0 && clear == 0)
return (ARCHIVE_OK);
/* Only regular files and dirs can have flags. */
if (!S_ISREG(mode) && !S_ISDIR(mode))
@@ -3616,12 +3628,19 @@
* defines. (?) The code below degrades reasonably gracefully
* if sf_mask is incomplete.
*/
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ sf_mask |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
sf_mask |= EXT2_IMMUTABLE_FL;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ sf_mask |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
sf_mask |= EXT2_APPEND_FL;
#endif
+#if defined(FS_JOURNAL_DATA_FL)
+ sf_mask |= FS_JOURNAL_DATA_FL;
+#endif
/*
* XXX As above, this would be way simpler if we didn't have
* to read the current flags from disk. XXX
@@ -3629,12 +3648,24 @@
ret = ARCHIVE_OK;
/* Read the current file flags. */
- if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &oldflags) < 0)
goto fail;
/* Try setting the flags as given. */
newflags = (oldflags & ~clear) | set;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
if (errno != EPERM)
goto fail;
@@ -3643,7 +3674,13 @@
newflags &= ~sf_mask;
oldflags &= sf_mask;
newflags |= oldflags;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
/* We couldn't set the flags, so report the failure. */
diff --git a/libarchive/archive_write_finish_entry.3 b/libarchive/archive_write_finish_entry.3
index c5ef69e..dc1b94b 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 @@
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 d4ba6ab..aaafb0a 100644
--- a/libarchive/archive_write_format.3
+++ b/libarchive/archive_write_format.3
@@ -108,7 +108,6 @@
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/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c
index 4e91097..c0ca435 100644
--- a/libarchive/archive_write_set_format_iso9660.c
+++ b/libarchive/archive_write_set_format_iso9660.c
@@ -4074,8 +4074,10 @@
memset(info.s, 0, info_size);
opt = 0;
#if defined(HAVE__CTIME64_S)
- __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
- _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
+ {
+ __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
+ _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
+ }
#elif defined(HAVE_CTIME_R)
ctime_r(&(iso9660->birth_time), buf);
#else
diff --git a/libarchive/mtree.5 b/libarchive/mtree.5
index 16c8abe..e607e4a 100644
--- a/libarchive/mtree.5
+++ b/libarchive/mtree.5
@@ -48,7 +48,7 @@
.Pp
When encoding file or pathnames, any backslash character or
character outside of the 95 printable ASCII characters must be
-encoded as a a backslash followed by three
+encoded as a backslash followed by three
octal digits.
When reading mtree files, any appearance of a backslash
followed by three octal digits should be converted into the
diff --git a/libarchive/test/test_acl_platform_nfs4.c b/libarchive/test/test_acl_platform_nfs4.c
index 01c1dc5..c885408 100644
--- a/libarchive/test/test_acl_platform_nfs4.c
+++ b/libarchive/test/test_acl_platform_nfs4.c
@@ -254,12 +254,14 @@
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 @@
}
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_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 @@
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 @@
}
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 @@
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 @@
}
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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 b46f658..0224a57 100644
--- a/libarchive/test/test_acl_platform_posix1e.c
+++ b/libarchive/test/test_acl_platform_posix1e.c
@@ -226,7 +226,7 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
"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 @@
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 @@
"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 @@
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 @@
"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 @@
#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_fuzz.c b/libarchive/test/test_fuzz.c
index 71bf3ff..ce7b866 100644
--- a/libarchive/test/test_fuzz.c
+++ b/libarchive/test/test_fuzz.c
@@ -110,8 +110,9 @@
} else {
for (i = 0; filesets[n].names[i] != NULL; ++i)
{
+ char *newraw;
tmp = slurpfile(&size, filesets[n].names[i]);
- char *newraw = realloc(rawimage, oldsize + size);
+ newraw = realloc(rawimage, oldsize + size);
if (!assert(newraw != NULL))
{
free(rawimage);
diff --git a/libarchive/test/test_read_disk.c b/libarchive/test/test_read_disk.c
index bd36c39..43d7d86 100644
--- a/libarchive/test/test_read_disk.c
+++ b/libarchive/test/test_read_disk.c
@@ -61,6 +61,7 @@
return ("NOTFOO");
}
+#if !defined(__CYGWIN__) && !defined(__HAIKU__)
/* We test GID lookup by looking up the name of group number zero and
* checking it against the following list. If your system uses a
* different conventional name for group number zero, please extend
@@ -71,13 +72,16 @@
"root", /* Linux */
"wheel" /* BSD */
};
+#endif
DEFINE_TEST(test_read_disk)
{
struct archive *a;
int gmagic = 0x13579, umagic = 0x1234;
+#if !defined(__CYGWIN__) && !defined(__HAIKU__)
const char *p;
size_t i;
+#endif
assert((a = archive_read_disk_new()) != NULL);
@@ -115,8 +119,6 @@
/* Some platforms don't have predictable names for
* uid=0, so we skip this part of the test. */
skipping("standard uname/gname lookup");
- i = 0;
- p = zero_groups[0]; /* avoid unused warnings */
#else
/* XXX Someday, we may need to generalize this the
* same way we generalized the group name check below.
diff --git a/libarchive/test/test_read_disk_directory_traversals.c b/libarchive/test/test_read_disk_directory_traversals.c
index c9aca8f..705b3d9 100644
--- a/libarchive/test/test_read_disk_directory_traversals.c
+++ b/libarchive/test/test_read_disk_directory_traversals.c
@@ -1228,11 +1228,11 @@
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
- * Test4: Traversals with archive_read_disk_set_atime_restored() and
- * archive_read_disk_honor_nodump().
+ * 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 @@
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);
@@ -1460,7 +1460,7 @@
assert((a = archive_read_disk_new()) != NULL);
/*
- * Test1: Traversals without archive_read_disk_honor_nodump().
+ * Test1: Traversals without ARCHIVE_READDISK_HONOR_NODUMP
*/
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
@@ -1513,7 +1513,7 @@
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
- * Test2: Traversals with archive_read_disk_honor_nodump().
+ * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP
*/
assertUtimes("nd/f1", 886600, 0, 886600, 0);
assertUtimes("nd/f2", 886611, 0, 886611, 0);
diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
index 9eadaaf..0537bf3 100644
--- a/tar/bsdtar.1
+++ b/tar/bsdtar.1
@@ -1,4 +1,5 @@
.\" Copyright (c) 2003-2007 Tim Kientzle
+.\" Copyright (c) 2017 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 16, 2014
+.Dd February 25, 2017
.Dt TAR 1
.Os
.Sh NAME
@@ -124,7 +125,7 @@
all operating modes.
.Bl -tag -width indent
.It Cm @ Ns Pa archive
-(c and r mode only)
+(c and r modes only)
The specified archive is opened and the entries
in it will be appended to the current archive.
As a simple example,
@@ -164,6 +165,16 @@
.Dl Nm Fl a Fl jcf Pa archive.xxx source.c source.h
if it is unknown suffix or no suffix, creates a new archive with
restricted pax format and bzip2 compression.
+.It Fl Fl acls
+(c, r, u, x modes only)
+Archive or extract POSIX.1e or NFSv4 ACLs. This is the reverse of
+.Fl Fl no-acls
+and the default behavior in c, r, and u modes (except Mac OS X) or if
+.Nm
+is run in x mode as root. On Mac OS X this option translates extended ACLs
+to NFSv4 ACLs. To store extended ACLs the
+.Fl Fl mac-metadata
+option is preferred.
.It Fl B , Fl Fl read-full-blocks
Ignored for compatibility with other
.Xr tar 1
@@ -188,15 +199,18 @@
(x mode only)
Before removing file system objects to replace them, clear platform-specific
file flags that might prevent removal.
-.It Fl Fl disable-copyfile
-Mac OS X specific.
-Disable the use of
-.Xr copyfile 3 .
.It Fl Fl exclude Ar pattern
Do not process files or directories that match the
specified pattern.
Note that exclusions take precedence over patterns or filenames
specified on the command line.
+.It Fl Fl fflags
+(c, r, u, x modes only)
+Archive or extract file flags. This is the reverse of
+.Fl Fl no-fflags
+and the default behavior in c, r, and u modes or if
+.Nm
+is run in x mode as root.
.It Fl Fl format Ar format
(c, r, u mode only)
Use the specified format for the created archive.
@@ -245,11 +259,11 @@
in the archive;
the name will not be verified against the system group database.
.It Fl H
-(c and r mode only)
+(c and r modes only)
Symbolic links named on the command line will be followed; the
target of the link will be archived, not the link itself.
.It Fl h
-(c and r mode only)
+(c and r modes only)
Synonym for
.Fl L .
.It Fl I
@@ -259,7 +273,8 @@
Show usage.
.It Fl Fl hfsCompression
(x mode only)
-Mac OS X specific(v10.6 or later). Compress extracted regular files with HFS+ compression.
+Mac OS X specific (v10.6 or later). Compress extracted regular files with HFS+
+compression.
.It Fl Fl ignore-zeros
An alias of
.Fl Fl options Cm read_concatenated_archives
@@ -310,7 +325,7 @@
Do not overwrite existing files that are newer than the
versions appearing in the archive being extracted.
.It Fl L , Fl Fl dereference
-(c and r mode only)
+(c and r modes only)
All symbolic links will be followed.
Normally, symbolic links are archived as such.
With this option, the target of the link will be archived instead.
@@ -345,6 +360,16 @@
(x mode only)
Do not extract modification time.
By default, the modification time is set to the time stored in the archive.
+.It Fl Fl mac-metadata
+(c, r, u and x mode only)
+Mac OS X specific. Archive or extract extended ACLs and extended attributes
+using
+.Xr copyfile 3
+in AppleDouble format. This is the reverse of
+.Fl Fl no-mac-metadata .
+and the default behavior in c, r, and u modes or if
+.Nm
+is run in x mode as root.
.It Fl n , Fl Fl norecurse , Fl Fl no-recursion
(c, r, u modes only)
Do not recursively archive the contents of directories.
@@ -385,6 +410,30 @@
.Fl print0
option to
.Xr find 1 .
+.It Fl Fl no-acls
+(c, r, u, x modes only)
+Do not archive or extract POSIX.1e or NFSv4 ACLs. This is the reverse of
+.Fl Fl acls
+and the default behavior if
+.Nm
+is run as non-root in x mode (on Mac OS X also in c, r and u modes).
+.It Fl Fl no-fflags
+(c, r, u, x modes only)
+Do not archive or extract file flags. This is the reverse of
+.Fl Fl fflags
+and the default behavior if
+.Nm
+is run as non-root in x mode.
+.It Fl Fl no-mac-metadata
+(x mode only)
+Mac OS X specific. Do not archive or extract ACLs and extended attributes using
+.Xr copyfile 3
+in AppleDouble format. This is the reverse of
+.Fl Fl mac-metadata .
+and the default behavior if
+.Nm
+is run as non-root in x mode.
+.It Fl n , Fl Fl norecurse , Fl Fl no-recursion
.It Fl Fl no-same-owner
(x mode only)
Do not extract owner and group IDs.
@@ -402,6 +451,13 @@
and the default behavior if
.Nm
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
+.Fl Fl xattrs
+and the default behavior if
+.Nm
+is run as non-root in x mode.
.It Fl Fl numeric-owner
This is equivalent to
.Fl Fl uname
@@ -583,14 +639,18 @@
.It Fl p , Fl Fl insecure , Fl Fl preserve-permissions
(x mode only)
Preserve file permissions.
-Attempt to restore the full permissions, including owner, file modes, file
-flags and ACLs, if available, for each item extracted from the archive.
-This is the default, if
+Attempt to restore the full permissions, including owner, file modes, ACLs,
+extended attributes and extended file flags, if available, for each item
+extracted from the archive. This is te reverse of
+.Fl Fl no-same-permissions
+and the default if
.Nm
-is being run by root and can be overridden by also specifying
-.Fl Fl no-same-owner
-and
-.Fl Fl no-same-permissions .
+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
+or
+.Fl Fl no-xattrs .
.It Fl Fl passphrase Ar passphrase
The
.Pa passphrase
@@ -692,7 +752,7 @@
.Fl n
as well.
.It Fl Fl totals
-(c, r, u mode only)
+(c, r, u modes only)
After archiving all files, print a summary to stderr.
.It Fl U , Fl Fl unlink , Fl Fl unlink-first
(x mode only)
@@ -754,6 +814,13 @@
See
.Fl Fl exclude
for more information about the handling of exclusions.
+.It Fl Fl xattrs
+(c, r, u, x modes only)
+Archive or extract extended attributes. This is the reverse of
+.Fl Fl no-xattrs
+and the default behavior in c, r, and u modes or if
+.Nm
+is run in x mode as root.
.It Fl y
(c mode only)
Compress the resulting archive with
diff --git a/tar/bsdtar.c b/tar/bsdtar.c
index 93bf60a..9fc6833 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -118,11 +118,11 @@
}
#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 \
@@ -137,7 +137,6 @@
char compression, compression2;
const char *compression_name, *compression2_name;
const char *compress_program;
- char option_a, option_o;
char possible_help_request;
char buff[16];
@@ -150,7 +149,7 @@
bsdtar->fd = -1; /* Mark as "unused" */
bsdtar->gid = -1;
bsdtar->uid = -1;
- option_a = option_o = 0;
+ bsdtar->flags = 0;
compression = compression2 = '\0';
compression_name = compression2_name = NULL;
compress_program = NULL;
@@ -233,6 +232,14 @@
if (getenv(COPYFILE_DISABLE_VAR))
bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE;
#endif
+#if defined(__APPLE__)
+ /*
+ * On Mac OS ACLs are archived with copyfile() (--mac-metadata)
+ * Translation to NFSv4 ACLs has to be requested explicitly with --acls
+ */
+ bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL;
+#endif
+
bsdtar->matching = archive_match_new();
if (bsdtar->matching == NULL)
lafe_errc(1, errno, "Out of memory");
@@ -252,7 +259,12 @@
while ((opt = bsdtar_getopt(bsdtar)) != -1) {
switch (opt) {
case 'a': /* GNU tar */
- option_a = 1; /* Record it and resolve it later. */
+ bsdtar->flags |= OPTFLAG_AUTO_COMPRESS;
+ break;
+ case OPTION_ACLS: /* GNU tar */
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
+ bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_ACL;
+ bsdtar->flags |= OPTFLAG_ACLS;
break;
case 'B': /* GNU tar */
/* libarchive doesn't need this; just ignore it. */
@@ -285,24 +297,26 @@
set_mode(bsdtar, opt);
break;
case OPTION_CHECK_LINKS: /* GNU tar */
- bsdtar->option_warn_links = 1;
+ bsdtar->flags |= OPTFLAG_WARN_LINKS;
break;
case OPTION_CHROOT: /* NetBSD */
- bsdtar->option_chroot = 1;
+ bsdtar->flags |= OPTFLAG_CHROOT;
break;
case OPTION_CLEAR_NOCHANGE_FFLAGS:
bsdtar->extract_flags |=
ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS;
break;
- case OPTION_DISABLE_COPYFILE: /* Mac OS X */
- bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE;
- break;
case OPTION_EXCLUDE: /* GNU tar */
if (archive_match_exclude_pattern(
bsdtar->matching, bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0,
"Couldn't exclude %s\n", bsdtar->argument);
break;
+ case OPTION_FFLAGS:
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
+ bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_FFLAGS;
+ bsdtar->flags |= OPTFLAG_FFLAGS;
+ break;
case OPTION_FORMAT: /* GNU tar, others */
cset_set_format(bsdtar->cset, bsdtar->argument);
break;
@@ -344,7 +358,7 @@
ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED;
break;
case OPTION_IGNORE_ZEROS:
- bsdtar->option_ignore_zeros = 1;
+ bsdtar->flags |= OPTFLAG_IGNORE_ZEROS;
break;
case 'I': /* GNU tar */
/*
@@ -398,7 +412,7 @@
break;
case 'l': /* SUSv2 and GNU tar beginning with 1.16 */
/* GNU tar 1.13 used -l for --one-file-system */
- bsdtar->option_warn_links = 1;
+ bsdtar->flags |= OPTFLAG_WARN_LINKS;
break;
case OPTION_LRZIP:
case OPTION_LZ4:
@@ -421,8 +435,13 @@
case 'm': /* SUSv2 */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME;
break;
+ case OPTION_MAC_METADATA: /* Mac OS X */
+ bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE;
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA;
+ bsdtar->flags |= OPTFLAG_MAC_METADATA;
+ break;
case 'n': /* GNU tar */
- bsdtar->option_no_subdirs = 1;
+ bsdtar->flags |= OPTFLAG_NO_SUBDIRS;
break;
/*
* Selecting files by time:
@@ -466,6 +485,21 @@
bsdtar->extract_flags |=
ARCHIVE_EXTRACT_NO_HFS_COMPRESSION;
break;
+ case OPTION_NO_ACLS: /* GNU tar */
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL;
+ bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL;
+ bsdtar->flags |= OPTFLAG_NO_ACLS;
+ break;
+ case OPTION_NO_FFLAGS:
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS;
+ bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_FFLAGS;
+ bsdtar->flags |= OPTFLAG_NO_FFLAGS;
+ break;
+ case OPTION_NO_MAC_METADATA: /* Mac OS X */
+ bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE;
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA;
+ bsdtar->flags |= OPTFLAG_NO_MAC_METADATA;
+ break;
case OPTION_NO_SAME_OWNER: /* GNU tar */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
@@ -476,23 +510,24 @@
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS;
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA;
break;
- case OPTION_NO_XATTR: /* Issue #131 */
+ case OPTION_NO_XATTRS: /* GNU tar */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR;
bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_XATTR;
+ bsdtar->flags |= OPTFLAG_NO_XATTRS;
break;
case OPTION_NULL: /* GNU tar */
- bsdtar->option_null++;
+ bsdtar->flags |= OPTFLAG_NULL;
break;
case OPTION_NUMERIC_OWNER: /* GNU tar */
bsdtar->uname = "";
bsdtar->gname = "";
- bsdtar->option_numeric_owner++;
+ bsdtar->flags |= OPTFLAG_NUMERIC_OWNER;
break;
case 'O': /* GNU tar */
- bsdtar->option_stdout = 1;
+ bsdtar->flags |= OPTFLAG_STDOUT;
break;
case 'o': /* SUSv2 and GNU conflict here, but not fatally */
- option_o = 1; /* Record it and resolve it later. */
+ bsdtar->flags |= OPTFLAG_O;
break;
/*
* Selecting files by time:
@@ -548,7 +583,7 @@
#endif
case 'P': /* GNU tar */
bsdtar->extract_flags &= ~SECURITY;
- bsdtar->option_absolute_paths = 1;
+ bsdtar->flags |= OPTFLAG_ABSOLUTE_PATHS;
break;
case 'p': /* GNU tar, star */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM;
@@ -564,7 +599,7 @@
cset_set_format(bsdtar->cset, "pax");
break;
case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */
- bsdtar->option_fast_read = 1;
+ bsdtar->flags |= OPTFLAG_FAST_READ;
break;
case 'r': /* SUSv2 */
set_mode(bsdtar, opt);
@@ -601,11 +636,11 @@
bsdtar->verbose++;
break;
case OPTION_TOTALS: /* GNU tar */
- bsdtar->option_totals++;
+ bsdtar->flags |= OPTFLAG_TOTALS;
break;
case 'U': /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK;
- bsdtar->option_unlink_first = 1;
+ bsdtar->flags |= OPTFLAG_UNLINK_FIRST;
break;
case 'u': /* SUSv2 */
set_mode(bsdtar, opt);
@@ -643,7 +678,7 @@
break;
#endif
case 'w': /* SUSv2 */
- bsdtar->option_interactive = 1;
+ bsdtar->flags |= OPTFLAG_INTERACTIVE;
break;
case 'X': /* GNU tar */
if (archive_match_exclude_pattern_from_file(
@@ -655,6 +690,11 @@
case 'x': /* SUSv2 */
set_mode(bsdtar, opt);
break;
+ case OPTION_XATTRS: /* GNU tar */
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
+ bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_XATTR;
+ bsdtar->flags |= OPTFLAG_XATTRS;
+ break;
case 'y': /* FreeBSD version of GNU tar */
if (compression != '\0')
lafe_errc(1, 0,
@@ -703,11 +743,11 @@
"Must specify one of -c, -r, -t, -u, -x");
/* Check boolean options only permitted in certain modes. */
- if (option_a)
+ if (bsdtar->flags & OPTFLAG_AUTO_COMPRESS)
only_mode(bsdtar, "-a", "c");
if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
only_mode(bsdtar, "--one-file-system", "cru");
- if (bsdtar->option_fast_read)
+ if (bsdtar->flags & OPTFLAG_FAST_READ)
only_mode(bsdtar, "--fast-read", "xt");
if (bsdtar->extract_flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED)
only_mode(bsdtar, "--hfsCompression", "x");
@@ -715,9 +755,23 @@
only_mode(bsdtar, "--nopreserveHFSCompression", "x");
if (bsdtar->readdisk_flags & ARCHIVE_READDISK_HONOR_NODUMP)
only_mode(bsdtar, "--nodump", "cru");
- if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_XATTR)
- only_mode(bsdtar, "--no-xattr", "crux");
- if (option_o > 0) {
+ if (bsdtar->flags & OPTFLAG_ACLS)
+ only_mode(bsdtar, "--acls", "crux");
+ if (bsdtar->flags & OPTFLAG_NO_ACLS)
+ only_mode(bsdtar, "--no-acls", "crux");
+ if (bsdtar->flags & OPTFLAG_XATTRS)
+ only_mode(bsdtar, "--xattrs", "crux");
+ if (bsdtar->flags & OPTFLAG_NO_XATTRS)
+ only_mode(bsdtar, "--no-xattrs", "crux");
+ if (bsdtar->flags & OPTFLAG_FFLAGS)
+ only_mode(bsdtar, "--fflags", "crux");
+ if (bsdtar->flags & OPTFLAG_NO_FFLAGS)
+ only_mode(bsdtar, "--no-fflags", "crux");
+ if (bsdtar->flags & OPTFLAG_MAC_METADATA)
+ only_mode(bsdtar, "--mac-metadata", "crux");
+ if (bsdtar->flags & OPTFLAG_NO_MAC_METADATA)
+ only_mode(bsdtar, "--no-mac-metadata", "crux");
+ if (bsdtar->flags & OPTFLAG_O) {
switch (bsdtar->mode) {
case 'c':
/*
@@ -730,7 +784,7 @@
break;
case 'x':
/* POSIX-compatible behavior. */
- bsdtar->option_no_owner = 1;
+ bsdtar->flags |= OPTFLAG_NO_OWNER;
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
default:
@@ -738,16 +792,17 @@
break;
}
}
- if (bsdtar->option_no_subdirs)
+ if (bsdtar->flags & OPTFLAG_NO_SUBDIRS)
only_mode(bsdtar, "-n", "cru");
- if (bsdtar->option_stdout)
+ if (bsdtar->flags & OPTFLAG_STDOUT)
only_mode(bsdtar, "-O", "xt");
- if (bsdtar->option_unlink_first)
+ if (bsdtar->flags & OPTFLAG_UNLINK_FIRST)
only_mode(bsdtar, "-U", "x");
- if (bsdtar->option_warn_links)
+ if (bsdtar->flags & OPTFLAG_WARN_LINKS)
only_mode(bsdtar, "--check-links", "cr");
- if (option_a && cset_auto_compress(bsdtar->cset, bsdtar->filename)) {
+ if ((bsdtar->flags & OPTFLAG_AUTO_COMPRESS) &&
+ cset_auto_compress(bsdtar->cset, bsdtar->filename)) {
/* Ignore specified compressions if auto-compress works. */
compression = '\0';
compression2 = '\0';
diff --git a/tar/bsdtar.h b/tar/bsdtar.h
index 4b84ba1..10a2cf2 100644
--- a/tar/bsdtar.h
+++ b/tar/bsdtar.h
@@ -50,6 +50,7 @@
int bytes_per_block; /* -b block_size */
int bytes_in_last_block; /* See -b handling. */
int verbose; /* -v */
+ unsigned int flags; /* Bitfield of boolean options */
int extract_flags; /* Flags for extract operation */
int readdisk_flags; /* Flags for read disk operation */
int strip_components; /* Remove this many leading dirs */
@@ -60,20 +61,7 @@
const char *passphrase; /* --passphrase */
char mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */
char symlink_mode; /* H or L, per BSD conventions */
- char option_absolute_paths; /* -P */
- char option_chroot; /* --chroot */
- char option_fast_read; /* --fast-read */
const char *option_options; /* --options */
- char option_ignore_zeros; /* --ignore-zeros */
- char option_interactive; /* -w */
- char option_no_owner; /* -o */
- char option_no_subdirs; /* -n */
- char option_numeric_owner; /* --numeric-owner */
- char option_null; /* --null */
- char option_stdout; /* -O */
- char option_totals; /* --totals */
- char option_unlink_first; /* -U */
- char option_warn_links; /* --check-links */
char day_first; /* show day before month in -tv output */
struct creation_set *cset;
@@ -114,14 +102,40 @@
char *ppbuff; /* for util.c */
};
+/* Options for flags bitfield */
+#define OPTFLAG_AUTO_COMPRESS (0x00000001) /* -a */
+#define OPTFLAG_ABSOLUTE_PATHS (0x00000002) /* -P */
+#define OPTFLAG_CHROOT (0x00000004) /* --chroot */
+#define OPTFLAG_FAST_READ (0x00000008) /* --fast-read */
+#define OPTFLAG_IGNORE_ZEROS (0x00000010) /* --ignore-zeros */
+#define OPTFLAG_INTERACTIVE (0x00000020) /* -w */
+#define OPTFLAG_NO_OWNER (0x00000040) /* -o */
+#define OPTFLAG_NO_SUBDIRS (0x00000080) /* -n */
+#define OPTFLAG_NULL (0x00000100) /* --null */
+#define OPTFLAG_NUMERIC_OWNER (0x00000200) /* --numeric-owner */
+#define OPTFLAG_O (0x00000400) /* -o */
+#define OPTFLAG_STDOUT (0x00000800) /* -O */
+#define OPTFLAG_TOTALS (0x00001000) /* --totals */
+#define OPTFLAG_UNLINK_FIRST (0x00002000) /* -U */
+#define OPTFLAG_WARN_LINKS (0x00004000) /* --check-links */
+#define OPTFLAG_NO_XATTRS (0x00008000) /* --no-xattrs */
+#define OPTFLAG_XATTRS (0x00010000) /* --xattrs */
+#define OPTFLAG_NO_ACLS (0x00020000) /* --no-acls */
+#define OPTFLAG_ACLS (0x00040000) /* --acls */
+#define OPTFLAG_NO_FFLAGS (0x00080000) /* --no-fflags */
+#define OPTFLAG_FFLAGS (0x00100000) /* --fflags */
+#define OPTFLAG_NO_MAC_METADATA (0x00200000) /* --no-mac-metadata */
+#define OPTFLAG_MAC_METADATA (0x00400000) /* --mac-metadata */
+
/* Fake short equivalents for long options that otherwise lack them. */
enum {
- OPTION_B64ENCODE = 1,
+ OPTION_ACLS = 1,
+ OPTION_B64ENCODE,
OPTION_CHECK_LINKS,
OPTION_CHROOT,
OPTION_CLEAR_NOCHANGE_FFLAGS,
- OPTION_DISABLE_COPYFILE,
OPTION_EXCLUDE,
+ OPTION_FFLAGS,
OPTION_FORMAT,
OPTION_GID,
OPTION_GNAME,
@@ -136,15 +150,19 @@
OPTION_LZIP,
OPTION_LZMA,
OPTION_LZOP,
+ OPTION_MAC_METADATA,
OPTION_NEWER_CTIME,
OPTION_NEWER_CTIME_THAN,
OPTION_NEWER_MTIME,
OPTION_NEWER_MTIME_THAN,
OPTION_NODUMP,
OPTION_NOPRESERVE_HFS_COMPRESSION,
+ OPTION_NO_ACLS,
+ OPTION_NO_FFLAGS,
+ OPTION_NO_MAC_METADATA,
OPTION_NO_SAME_OWNER,
OPTION_NO_SAME_PERMISSIONS,
- OPTION_NO_XATTR,
+ OPTION_NO_XATTRS,
OPTION_NULL,
OPTION_NUMERIC_OWNER,
OPTION_OLDER_CTIME,
@@ -162,7 +180,8 @@
OPTION_UNAME,
OPTION_USE_COMPRESS_PROGRAM,
OPTION_UUENCODE,
- OPTION_VERSION
+ OPTION_VERSION,
+ OPTION_XATTRS
};
int bsdtar_getopt(struct bsdtar *);
@@ -170,7 +189,7 @@
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);
@@ -178,8 +197,8 @@
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/cmdline.c b/tar/cmdline.c
index c87741c..e36c545 100644
--- a/tar/cmdline.c
+++ b/tar/cmdline.c
@@ -65,6 +65,7 @@
} tar_longopts[] = {
{ "absolute-paths", 0, 'P' },
{ "append", 0, 'r' },
+ { "acls", 0, OPTION_ACLS },
{ "auto-compress", 0, 'a' },
{ "b64encode", 0, OPTION_B64ENCODE },
{ "block-size", 1, 'b' },
@@ -81,11 +82,12 @@
{ "create", 0, 'c' },
{ "dereference", 0, 'L' },
{ "directory", 1, 'C' },
- { "disable-copyfile", 0, OPTION_DISABLE_COPYFILE },
+ { "disable-copyfile", 0, OPTION_NO_MAC_METADATA },
{ "exclude", 1, OPTION_EXCLUDE },
{ "exclude-from", 1, 'X' },
{ "extract", 0, 'x' },
{ "fast-read", 0, 'q' },
+ { "fflags", 0, OPTION_FFLAGS },
{ "file", 1, 'f' },
{ "files-from", 1, 'T' },
{ "format", 1, OPTION_FORMAT },
@@ -108,6 +110,7 @@
{ "lzip", 0, OPTION_LZIP },
{ "lzma", 0, OPTION_LZMA },
{ "lzop", 0, OPTION_LZOP },
+ { "mac-metadata", 0, OPTION_MAC_METADATA },
{ "modification-time", 0, 'm' },
{ "newer", 1, OPTION_NEWER_CTIME },
{ "newer-ctime", 1, OPTION_NEWER_CTIME },
@@ -115,10 +118,14 @@
{ "newer-mtime", 1, OPTION_NEWER_MTIME },
{ "newer-mtime-than", 1, OPTION_NEWER_MTIME_THAN },
{ "newer-than", 1, OPTION_NEWER_CTIME_THAN },
+ { "no-acls", 0, OPTION_NO_ACLS },
+ { "no-fflags", 0, OPTION_NO_FFLAGS },
+ { "no-mac-metadata", 0, OPTION_NO_MAC_METADATA },
{ "no-recursion", 0, 'n' },
{ "no-same-owner", 0, OPTION_NO_SAME_OWNER },
{ "no-same-permissions", 0, OPTION_NO_SAME_PERMISSIONS },
- { "no-xattr", 0, OPTION_NO_XATTR },
+ { "no-xattr", 0, OPTION_NO_XATTRS },
+ { "no-xattrs", 0, OPTION_NO_XATTRS },
{ "nodump", 0, OPTION_NODUMP },
{ "nopreserveHFSCompression",0, OPTION_NOPRESERVE_HFS_COMPRESSION },
{ "norecurse", 0, 'n' },
@@ -151,6 +158,7 @@
{ "uuencode", 0, OPTION_UUENCODE },
{ "verbose", 0, 'v' },
{ "version", 0, OPTION_VERSION },
+ { "xattrs", 0, OPTION_XATTRS },
{ "xz", 0, 'J' },
{ NULL, 0, 0 }
};
diff --git a/tar/read.c b/tar/read.c
index 3c6cb0c..658c810 100644
--- a/tar/read.c
+++ b/tar/read.c
@@ -105,7 +105,7 @@
writer = archive_write_disk_new();
if (writer == NULL)
lafe_errc(1, ENOMEM, "Cannot allocate disk writer object");
- if (!bsdtar->option_numeric_owner)
+ if ((bsdtar->flags & OPTFLAG_NUMERIC_OWNER) == 0)
archive_write_disk_set_standard_lookup(writer);
archive_write_disk_set_options(writer, bsdtar->extract_flags);
@@ -177,7 +177,7 @@
if (bsdtar->names_from_file != NULL)
if (archive_match_include_pattern_from_file(
bsdtar->matching, bsdtar->names_from_file,
- bsdtar->option_null) != ARCHIVE_OK)
+ (bsdtar->flags & OPTFLAG_NULL)) != ARCHIVE_OK)
lafe_errc(1, 0, "Error inclusion pattern: %s",
archive_error_string(bsdtar->matching));
@@ -208,7 +208,7 @@
}
if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
lafe_errc(1, 0, "%s", archive_error_string(a));
- if (bsdtar->option_ignore_zeros)
+ if (bsdtar->flags & OPTFLAG_IGNORE_ZEROS)
if (archive_read_set_options(a,
"read_concatenated_archives") != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(a));
@@ -234,7 +234,7 @@
&progress_data);
}
- if (mode == 'x' && bsdtar->option_chroot) {
+ if (mode == 'x' && (bsdtar->flags & OPTFLAG_CHROOT)) {
#if HAVE_CHROOT
if (chroot(".") != 0)
lafe_errc(1, errno, "Can't chroot to \".\"");
@@ -245,7 +245,7 @@
}
#if defined(_WIN32) && !defined(__CYGWIN__)
- if (mode == 'x' && bsdtar->option_stdout) {
+ if (mode == 'x' && (bsdtar->flags & OPTFLAG_STDOUT)) {
_setmode(1, _O_BINARY);
}
#endif
@@ -253,7 +253,7 @@
for (;;) {
/* Support --fast-read option */
const char *p;
- if (bsdtar->option_fast_read &&
+ if ((bsdtar->flags & OPTFLAG_FAST_READ) &&
archive_match_path_unmatched_inclusions(bsdtar->matching) == 0)
break;
@@ -307,7 +307,8 @@
if (mode == 't') {
/* Perversely, gtar uses -O to mean "send to stderr"
* when used with -t. */
- out = bsdtar->option_stdout ? stderr : stdout;
+ out = (bsdtar->flags & OPTFLAG_STDOUT) ?
+ stderr : stdout;
/*
* TODO: Provide some reasonable way to
@@ -345,7 +346,7 @@
if (edit_pathname(bsdtar, entry))
continue; /* Excluded by a rewrite failure. */
- if (bsdtar->option_interactive &&
+ if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
!yes("extract '%s'", archive_entry_pathname(entry)))
continue;
@@ -364,7 +365,7 @@
/* TODO siginfo_printinfo(bsdtar, 0); */
- if (bsdtar->option_stdout)
+ if (bsdtar->flags & OPTFLAG_STDOUT)
r = archive_read_data_into_fd(a, 1);
else
r = archive_read_extract2(a, entry, writer);
diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt
index 3dd3601..e6054ba 100644
--- a/tar/test/CMakeLists.txt
+++ b/tar/test/CMakeLists.txt
@@ -34,9 +34,11 @@
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 @@
# 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 0000000..bfe2b99
--- /dev/null
+++ b/tar/test/test_option_acls.c
@@ -0,0 +1,469 @@
+/*-
+ * 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_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 0000000..77a4e3e
--- /dev/null
+++ b/tar/test/test_option_fflags.c
@@ -0,0 +1,106 @@
+/*-
+ * 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$");
+
+static void
+clear_fflags(const char *pathname)
+{
+#if defined(HAVE_STRUCT_STAT_ST_FLAGS)
+ chflags(pathname, 0);
+#elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
+ int fd;
+
+ fd = open(pathname, O_RDONLY | O_NONBLOCK);
+ if (fd < 0)
+ return;
+ ioctl(fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ 0);
+#else
+ (void)pathname; /* UNUSED */
+#endif
+ return;
+}
+
+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");
+
+ /* FreeBSD ZFS workaround: ZFS sets uarch on all touched files and dirs */
+ chmod("f", 0644);
+
+ /* 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);
+ clear_fflags("fflags_fflags");
+ 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);
+ clear_fflags("fflags_nofflags");
+ 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);
+ clear_fflags("nofflags_fflags");
+ 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);
+ clear_fflags("nofflags_nofflags");
+ 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 768f64a..815b08e 100644
--- a/tar/test/test_option_nodump.c
+++ b/tar/test/test_option_nodump.c
@@ -36,7 +36,7 @@
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/tar/util.c b/tar/util.c
index 8f65b17..662db5b 100644
--- a/tar/util.c
+++ b/tar/util.c
@@ -534,7 +534,7 @@
}
}
- if (!bsdtar->option_absolute_paths) {
+ if ((bsdtar->flags & OPTFLAG_ABSOLUTE_PATHS) == 0) {
/* By default, don't write or restore absolute pathnames. */
name = strip_absolute_path(bsdtar, name);
if (*name == '\0')
diff --git a/tar/write.c b/tar/write.c
index 532abb2..9c24566 100644
--- a/tar/write.c
+++ b/tar/write.c
@@ -583,7 +583,7 @@
archive_read_free(bsdtar->diskreader);
bsdtar->diskreader = NULL;
- if (bsdtar->option_totals) {
+ if (bsdtar->flags & OPTFLAG_TOTALS) {
fprintf(stderr, "Total bytes written: %s\n",
tar_i64toa(archive_filter_bytes(a, -1)));
}
@@ -606,7 +606,8 @@
bsdtar->next_line_is_dir = 0;
- lr = lafe_line_reader(bsdtar->names_from_file, bsdtar->option_null);
+ lr = lafe_line_reader(bsdtar->names_from_file,
+ (bsdtar->flags & OPTFLAG_NULL));
while ((line = lafe_line_reader_next(lr)) != NULL) {
if (bsdtar->next_line_is_dir) {
if (*line != '\0')
@@ -617,7 +618,8 @@
bsdtar->return_value = 1;
}
bsdtar->next_line_is_dir = 0;
- } else if (!bsdtar->option_null && strcmp(line, "-C") == 0)
+ } else if (((bsdtar->flags & OPTFLAG_NULL) == 0) &&
+ strcmp(line, "-C") == 0)
bsdtar->next_line_is_dir = 1;
else {
if (*line != '/')
@@ -690,7 +692,7 @@
while (ARCHIVE_OK == (e = archive_read_next_header(ina, &in_entry))) {
if (archive_match_excluded(bsdtar->matching, in_entry))
continue;
- if (bsdtar->option_interactive &&
+ if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
!yes("copy '%s'", archive_entry_pathname(in_entry)))
continue;
if (bsdtar->verbose > 1) {
@@ -809,11 +811,11 @@
{
struct bsdtar *bsdtar = (struct bsdtar *)_data;
- if (bsdtar->option_no_subdirs)
+ if (bsdtar->flags & OPTFLAG_NO_SUBDIRS)
return;
if (!archive_read_disk_can_descend(a))
return;
- if (bsdtar->option_interactive &&
+ if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
!yes("add '%s'", archive_entry_pathname(entry)))
return;
archive_read_disk_descend(a);
@@ -844,12 +846,13 @@
* check would veto this file, we shouldn't bother
* the user with it.
*/
- if (bsdtar->option_interactive &&
+ if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
!yes("add '%s'", archive_entry_pathname(entry)))
return (0);
/* Note: if user vetoes, we won't descend. */
- if (!bsdtar->option_no_subdirs && archive_read_disk_can_descend(a))
+ if (((bsdtar->flags & OPTFLAG_NO_SUBDIRS) == 0) &&
+ archive_read_disk_can_descend(a))
archive_read_disk_descend(a);
return (1);
diff --git a/test_utils/test_common.h b/test_utils/test_common.h
index 82e8483..44215a3 100644
--- a/test_utils/test_common.h
+++ b/test_utils/test_common.h
@@ -73,6 +73,12 @@
#include <unistd.h>
#endif
#include <wchar.h>
+#ifdef HAVE_ACL_LIBACL_H
+#include <acl/libacl.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#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 && HAVE_MEMBERSHIP_H
#define HAVE_DARWIN_ACL 1
#endif
+#if HAVE_DECL_ACL_TYPE_NFS4
+#define HAVE_FREEBSD_NFS4_ACL 1
+#endif
#endif
/*
* If this platform has <sys/acl.h>, acl_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_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 @@
/* 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 b0b6c2b..5d0e287 100644
--- a/test_utils/test_main.c
+++ b/test_utils/test_main.c
@@ -45,6 +45,9 @@
#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
#endif
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h>
+#endif
#include <limits.h>
#include <locale.h>
#ifdef HAVE_SIGNAL_H
@@ -53,6 +56,20 @@
#include <stdarg.h>
#include <time.h>
+/* ACL support */
+#ifdef HAVE_ACL_LIBACL_H
+#include <acl/libacl.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
+#if HAVE_DARWIN_ACL
+#include <membership.h>
+#endif
+
/*
*
* Windows support routines
@@ -1880,9 +1897,103 @@
#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;
@@ -1894,8 +2005,10 @@
failure_finish(NULL);
return (0);
}
-#elif defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)\
- && defined(EXT2_NODUMP_FL)
+#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, flags;
assertion_count(file, line);
@@ -1905,14 +2018,31 @@
failure_finish(NULL);
return (0);
}
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
+ r = ioctl(fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &flags);
if (r < 0) {
failure_start(file, line, "Can't get flags %s\n", pathname);
failure_finish(NULL);
return (0);
}
+#ifdef FS_NODUMP_FL
+ flags |= FS_NODUMP_FL;
+#else
flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+#endif
+
+ r = ioctl(fd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &flags);
if (r < 0) {
failure_start(file, line, "Can't set nodump %s\n", pathname);
failure_finish(NULL);
@@ -2234,11 +2364,10 @@
/*
* 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;
@@ -2249,15 +2378,10 @@
return (0);
if (sb.st_flags & UF_NODUMP)
return (1);
- return (0);
-}
-
-#elif defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)\
- && defined(EXT2_NODUMP_FL)
-
-int
-canNodump(void)
-{
+#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))
const char *path = "cannodumptest";
int fd, r, flags;
@@ -2265,35 +2389,273 @@
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd < 0)
return (0);
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
+ r = ioctl(fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &flags);
if (r < 0)
return (0);
+#ifdef FS_NODUMP_FL
+ flags |= FS_NODUMP_FL;
+#else
flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
+#endif
+ r = ioctl(fd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &flags);
if (r < 0)
return (0);
close(fd);
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd < 0)
return (0);
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
+ r = ioctl(fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &flags);
if (r < 0)
return (0);
close(fd);
- if (flags & EXT2_NODUMP_FL)
- return (1);
- return (0);
-}
-
+#ifdef FS_NODUMP_FL
+ if (flags & FS_NODUMP_FL)
#else
-
-int
-canNodump()
-{
+ if (flags & EXT2_NODUMP_FL)
+#endif
+ return (1);
+#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_uid_to_uuid(uid, uuid);
+ failure("mbr_uid_to_uuid() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+ r = acl_set_qualifier(aclent, uuid);
+ failure("acl_set_qualifier() error: %s", strerror(errno));
+ if (assertEqualInt(r, 0) == 0)
+ goto testacl_free;
+#endif /* HAVE_DARWIN_ACL */
+
+#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