diff options
-rw-r--r-- | usr.bin/tar/bsdtar.c | 1 | ||||
-rw-r--r-- | usr.bin/tar/bsdtar_platform.h | 61 | ||||
-rw-r--r-- | usr.bin/tar/configure.ac.in | 68 | ||||
-rw-r--r-- | usr.bin/tar/fts.c | 10 | ||||
-rw-r--r-- | usr.bin/tar/write.c | 10 |
5 files changed, 120 insertions, 30 deletions
diff --git a/usr.bin/tar/bsdtar.c b/usr.bin/tar/bsdtar.c index c2ea3c5..87ac5f1 100644 --- a/usr.bin/tar/bsdtar.c +++ b/usr.bin/tar/bsdtar.c @@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$"); #include <sys/stat.h> #include <archive.h> #include <archive_entry.h> -#include <dirent.h> #include <errno.h> #include <fcntl.h> #ifdef HAVE_GETOPT_LONG diff --git a/usr.bin/tar/bsdtar_platform.h b/usr.bin/tar/bsdtar_platform.h index a437446..d4eca6f 100644 --- a/usr.bin/tar/bsdtar_platform.h +++ b/usr.bin/tar/bsdtar_platform.h @@ -43,6 +43,11 @@ /* A default configuration for FreeBSD, used if there is no config.h. */ #define PACKAGE_NAME "bsdtar" +#if __FreeBSD__ > 4 +#define HAVE_ACL_GET_PERM 0 +#define HAVE_ACL_GET_PERM_NP 1 +#define HAVE_ACL_PERMSET_T 1 +#endif #define HAVE_BZLIB_H 1 #define HAVE_CHFLAGS 1 #define HAVE_DIRENT_D_NAMLEN 1 @@ -81,9 +86,7 @@ #define HAVE_STRRCHR 1 #define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 #define HAVE_STRUCT_STAT_ST_RDEV 1 -#if __FreeBSD__ > 4 #define HAVE_SYS_ACL_H 1 -#endif #define HAVE_SYS_IOCTL_H 1 #define HAVE_SYS_PARAM_H 1 #define HAVE_SYS_STAT_H 1 @@ -95,8 +98,8 @@ #define STDC_HEADERS 1 #else /* !__FreeBSD__ */ -/* Warn if the library hasn't been (automatically or manually) configured. */ -#error Oops: No config.h and no built-in configuration in archive_platform.h. +/* Warn if bsdtar hasn't been (automatically or manually) configured. */ +#error Oops: No config.h and no built-in configuration in bsdtar_platform.h. #endif /* !__FreeBSD__ */ #endif /* !HAVE_CONFIG_H */ @@ -112,12 +115,56 @@ #error Configuration error: did not find libarchive. #endif -/* TODO: Test for the functions we use as well... */ -#if HAVE_SYS_ACL_H -#define HAVE_POSIX_ACLS 1 +/* + * Does this platform have complete-looking POSIX-style ACL support, + * including some variant of the acl_get_perm() function (which was + * omitted from the POSIX.1e draft)? + */ +#if HAVE_SYS_ACL_H && HAVE_ACL_PERMSET_T +#if HAVE_ACL_GET_PERM || HAVE_ACL_GET_PERM_NP +#define HAVE_POSIX_ACL 1 +#endif +#endif + +#if HAVE_ACL_GET_PERM +#define ACL_GET_PERM acl_get_perm +#else +#if HAVE_ACL_GET_PERM_NP +#define ACL_GET_PERM acl_get_perm_np +#endif #endif /* + * Include "dirent.h" (or it's equivalent on several different platforms). + * + * This is slightly modified from the GNU autoconf recipe. + * In particular, FreeBSD includes d_namlen in it's dirent structure, + * so my configure script includes an explicit test for the d_namlen + * field. + */ +#if HAVE_DIRENT_H +# include <dirent.h> +# if HAVE_DIRENT_D_NAMLEN +# define DIRENT_NAMLEN(dirent) (dirent)->d_namlen +# else +# define DIRENT_NAMLEN(dirent) strlen((dirent)->d_name) +# endif +#else +# define dirent direct +# define DIRENT_NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + + +/* * We need to be able to display a filesize using printf(). The type * and format string here must be compatible with one another and * large enough for any file. diff --git a/usr.bin/tar/configure.ac.in b/usr.bin/tar/configure.ac.in index 4b78fb5..83a0e83 100644 --- a/usr.bin/tar/configure.ac.in +++ b/usr.bin/tar/configure.ac.in @@ -13,7 +13,7 @@ AC_PROG_YACC # Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC -AC_CHECK_HEADERS([bzlib.h fcntl.h inttypes.h langinfo.h limits.h locale.h paths.h stdint.h stdlib.h string.h sys/acl.h sys/ioctl.h sys/param.h unistd.h zlib.h]) +AC_CHECK_HEADERS([bzlib.h fcntl.h inttypes.h langinfo.h limits.h locale.h paths.h stdint.h stdlib.h string.h sys/ioctl.h sys/param.h unistd.h zlib.h]) # Checks for libraries. AC_CHECK_LIB([z], [inflate]) @@ -27,18 +27,63 @@ AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_CHECK_TYPE(id_t, [unsigned long]) -AC_CHECK_MEMBERS([struct stat.st_rdev, struct stat.st_mtimespec.tv_nsec, struct stat.st_mtim.tv_nsec, struct dirent.d_namlen]) +AC_CHECK_MEMBERS([struct stat.st_rdev, struct stat.st_mtimespec.tv_nsec, struct stat.st_mtim.tv_nsec]) + + AC_CHECK_DECL([D_MD_ORDER], - [AC_DEFINE(HAVE_D_MD_ORDER, 1, [Define to 1 if nl_langinfo supports D_MD_ORDER])], - [], - [#include <langinfo.h>]) +[AC_DEFINE(HAVE_D_MD_ORDER, 1, [Define to 1 if nl_langinfo supports D_MD_ORDER])], +[], +[#if HAVE_LANGINFO_H +#include <langinfo.h> +#endif +]) + +AC_FUNC_FNMATCH AC_CHECK_DECL([FNM_LEADING_DIR], - [AC_DEFINE(HAVE_FNM_LEADING_DIR, 1, [Define to 1 if fnmatch(3) supports the FNM_LEADING_DIR flag])], - [], - [#include <fnmatch.h>]) +[AC_DEFINE(HAVE_FNM_LEADING_DIR, 1, [Define to 1 if fnmatch(3) supports the FNM_LEADING_DIR flag])], +[], +[#if HAVE_FNMATCH +#define _GNU_SOURCE /* Required on Linux to get GNU extensions */ +#include <fnmatch.h> +#endif +]) + +# Check for dirent.d_namlen field explicitly +AC_CHECK_MEMBER(struct dirent.d_namlen,,, +[#if HAVE_DIRENT_H +#include <dirent.h> +#endif +]) + +# Check for ACL support +AC_CHECK_HEADERS([sys/acl.h]) + +AC_CHECK_TYPES(acl_permset_t,,, +[#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_SYS_ACL_H +#include <sys/acl.h> +#endif +]) + +# The "acl_get_perm()" function was omitted from the POSIX draft. +# (It's a pretty obvious oversight; otherwise, there's no way to +# test for specific permissions in a permset.) Linux uses the obvious +# name, FreeBSD adds _np to mark it as "non-Posix extension." +# Test for both as a double-check that we really have POSIX-style ACL support. +AC_CHECK_FUNCS(acl_get_perm_np acl_get_perm,,, +[#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_SYS_ACL_H +#include <sys/acl.h> +#endif +]) + +AC_CHECK_LIB(acl,acl_get_file) # Checks for library functions. -AC_FUNC_FNMATCH AC_PROG_GCC_TRADITIONAL AC_FUNC_LSTAT AC_HEADER_MAJOR @@ -46,9 +91,8 @@ AC_FUNC_MALLOC AC_FUNC_STAT AC_FUNC_STRFTIME AC_FUNC_VPRINTF -AC_CHECK_TYPE([uintmax_t]) -AC_CHECK_TYPE([unsigned long long]) -AC_CHECK_FUNCS([chflags fchdir ftruncate getopt_long memmove memset nl_langinfo setlocale strchr strdup strerror strrchr sys/acl.h]) +AC_CHECK_TYPES([uintmax_t, unsigned long long]) +AC_CHECK_FUNCS([chflags fchdir ftruncate getopt_long memmove memset nl_langinfo reallocf setlocale strchr strdup strerror strrchr]) # # If any of the common 64-bit types is defined, set "int64_t" diff --git a/usr.bin/tar/fts.c b/usr.bin/tar/fts.c index 69cd396..f512c11 100644 --- a/usr.bin/tar/fts.c +++ b/usr.bin/tar/fts.c @@ -65,8 +65,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/param.h> #include <sys/stat.h> - -#include <dirent.h> +/* #include <dirent.h> */ /* bsdtar: see bsdtar_platform.h */ #include <errno.h> #include <fcntl.h> #include <fts.h> @@ -740,11 +739,8 @@ fts_build(sp, type) /* Read the directory, attaching each entry to the `link' pointer. */ doadjust = 0; for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { -#ifdef HAVE_STRUCT_DIRENT_D_NAMLEN /* bsdtar: Not everyone has d_namlen. */ -#define dnamlen dp->d_namlen -#else - int dnamlen = strlen(dp->d_name); -#endif + /* See bsdtar_platform.h for DIRENT_NAMLEN. */ + int dnamlen = DIRENT_NAMLEN(dp); if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) continue; diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c index 9d430aa..dfcbcba 100644 --- a/usr.bin/tar/write.c +++ b/usr.bin/tar/write.c @@ -1103,11 +1103,15 @@ setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry, acl_get_permset(acl_entry, &acl_permset); ae_perm = 0; - if (acl_get_perm_np(acl_permset, ACL_EXECUTE)) + /* + * acl_get_perm() is spelled differently on different + * platforms; see bsdtar_platform.h for details. + */ + if (ACL_GET_PERM(acl_permset, ACL_EXECUTE)) ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; - if (acl_get_perm_np(acl_permset, ACL_READ)) + if (ACL_GET_PERM(acl_permset, ACL_READ)) ae_perm |= ARCHIVE_ENTRY_ACL_READ; - if (acl_get_perm_np(acl_permset, ACL_WRITE)) + if (ACL_GET_PERM(acl_permset, ACL_WRITE)) ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; archive_entry_acl_add_entry(entry, |