aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2017-03-02 21:02:17 +0000
committerMartin Matuska <mm@FreeBSD.org>2017-03-02 21:02:17 +0000
commit4b729aff5b4c807ecf8795452187ca06d5eb042d (patch)
treefefc76886e467f8a662770c4f394a8b76ebaf606
parentb2ee1181b4555230a015f1b8f27a1e7ec3c2bb6e (diff)
downloadsrc-4b729aff5b4c807ecf8795452187ca06d5eb042d.tar.gz
src-4b729aff5b4c807ecf8795452187ca06d5eb042d.zip
Update vendor/libarchive to git d6b1bb9f7ea7bc153b7356e8e345c9e48005821avendor/libarchive/3.3.1
Release 3.3.1 Notable vendor changes: PR #501: improvements in ACL path handling PR #724: fix hang when reading malformed cpio files PR #864: fix out of bounds read with malformed GNU tar archives Test suite improvements New options to bsdtar that enable or disable reading and/or writing of: Access Control Lists (--acls, --no-acls) Extended file flags (--fflags, --no-fflags) Extended attributes (--xattrs, --no-xattrs)
Notes
Notes: svn path=/vendor/libarchive/dist/; revision=314565 svn path=/vendor/libarchive/3.3.1/; revision=314566; tag=vendor/libarchive/3.3.1
-rw-r--r--CMakeLists.txt17
-rw-r--r--Makefile.am27
-rw-r--r--NEWS8
-rwxr-xr-xbuild/autogen.sh1
-rw-r--r--build/cmake/config.h.in3
-rw-r--r--build/version2
-rw-r--r--cat/test/CMakeLists.txt3
-rw-r--r--cat/test/main.c3072
-rw-r--r--cat/test/test.h336
-rw-r--r--cat/test/test_version.c67
-rw-r--r--configure.ac19
-rw-r--r--cpio/test/CMakeLists.txt3
-rw-r--r--cpio/test/main.c3073
-rw-r--r--cpio/test/test.h340
-rw-r--r--cpio/test/test_option_version.c88
-rw-r--r--libarchive/archive.h8
-rw-r--r--libarchive/archive_digest_private.h1
-rw-r--r--libarchive/archive_entry.c110
-rw-r--r--libarchive/archive_entry.h27
-rw-r--r--libarchive/archive_hmac.c4
-rw-r--r--libarchive/archive_read_disk_entry_from_file.c171
-rw-r--r--libarchive/archive_read_disk_posix.c64
-rw-r--r--libarchive/archive_read_disk_private.h12
-rw-r--r--libarchive/archive_read_disk_windows.c30
-rw-r--r--libarchive/archive_read_support_format_tar.c5
-rw-r--r--libarchive/archive_read_support_format_warc.c14
-rw-r--r--libarchive/archive_write_disk_posix.c77
-rw-r--r--libarchive/archive_write_set_format_iso9660.c6
-rw-r--r--libarchive/test/CMakeLists.txt3
-rw-r--r--libarchive/test/test.h390
-rw-r--r--libarchive/test/test_acl_nfs4.c12
-rw-r--r--libarchive/test/test_acl_pax.c25
-rw-r--r--libarchive/test/test_acl_platform_posix1e.c12
-rw-r--r--libarchive/test/test_acl_posix1e.c15
-rw-r--r--libarchive/test/test_acl_text.c28
-rw-r--r--libarchive/test/test_archive_api_feature.c8
-rw-r--r--libarchive/test/test_compat_solaris_tar_acl.c10
-rw-r--r--libarchive/test/test_compat_star_acl.c12
-rw-r--r--libarchive/test/test_fuzz.c3
-rw-r--r--libarchive/test/test_read_disk.c6
-rw-r--r--libarchive/test/test_read_disk_directory_traversals.c8
-rw-r--r--tar/bsdtar.1108
-rw-r--r--tar/bsdtar.c119
-rw-r--r--tar/bsdtar.h53
-rw-r--r--tar/cmdline.c12
-rw-r--r--tar/read.c19
-rw-r--r--tar/test/CMakeLists.txt3
-rw-r--r--tar/test/main.c3072
-rw-r--r--tar/test/test.h340
-rw-r--r--tar/test/test_version.c73
-rw-r--r--tar/util.c2
-rw-r--r--tar/write.c21
-rw-r--r--test_utils/test_common.h434
-rw-r--r--test_utils/test_main.c (renamed from libarchive/test/main.c)336
54 files changed, 1473 insertions, 11239 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eb36b5b99e44..1ca9d8fdc066 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@ endif()
# RelWithDebInfo : Release build with Debug Info
# MinSizeRel : Release Min Size build
IF(NOT CMAKE_BUILD_TYPE)
- SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
+ SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
# value type is "UNINITIALIZED".
@@ -44,13 +44,13 @@ SET(CMAKE_MACOSX_RPATH ON)
#
FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version)
STRING(REGEX REPLACE
- "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version})
+ "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version})
STRING(REGEX REPLACE
- "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version})
+ "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version})
STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version})
+ "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version})
STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version})
+ "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version})
SET(_version_number ${_major}${_minor}${_revision})
STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor})
STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision})
@@ -462,6 +462,8 @@ ENDIF()
IF(LIBLZMA_FOUND)
SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1)
+ 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.
@@ -570,6 +572,11 @@ LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H)
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("memory.h" HAVE_MEMORY_H)
diff --git a/Makefile.am b/Makefile.am
index dd1fc813e564..f22a918729ae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,7 +23,7 @@ TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $
DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio
# The next line is commented out by default in shipping libarchive releases.
# It is uncommented by default in trunk.
-DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
+# DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
AM_CFLAGS=$(DEV_CFLAGS)
PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@
AM_CPPFLAGS=$(PLATFORMCPPFLAGS)
@@ -310,7 +310,9 @@ pkgconfig_DATA = build/pkgconfig/libarchive.pc
# Sources needed by all test programs
test_utils_SOURCES= \
test_utils/test_utils.c \
- test_utils/test_utils.h
+ test_utils/test_utils.h \
+ test_utils/test_main.c \
+ test_utils/test_common.h
#
#
@@ -320,7 +322,6 @@ test_utils_SOURCES= \
libarchive_test_SOURCES= \
$(libarchive_la_SOURCES) \
$(test_utils_SOURCES) \
- libarchive/test/main.c \
libarchive/test/read_open_memory.c \
libarchive/test/test.h \
libarchive/test/test_acl_nfs4.c \
@@ -586,7 +587,13 @@ libarchive_test_SOURCES= \
libarchive/test/test_write_read_format_zip.c \
libarchive/test/test_zip_filename_encoding.c
-libarchive_test_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/test_utils -I$(top_builddir)/libarchive/test -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS)
+libarchive_test_CPPFLAGS= \
+ -I$(top_srcdir)/libarchive \
+ -I$(top_srcdir)/libarchive/test \
+ -I$(top_srcdir)/test_utils \
+ -I$(top_builddir)/libarchive/test \
+ -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS)
+
libarchive_test_LDADD= $(LTLIBICONV)
# The "list.h" file just lists all of the tests defined in all of the sources.
@@ -918,7 +925,6 @@ endif
bsdtar_test_SOURCES= \
$(test_utils_SOURCES) \
- tar/test/main.c \
tar/test/test.h \
tar/test/test_0.c \
tar/test/test_basic.c \
@@ -981,7 +987,8 @@ bsdtar_test_SOURCES= \
bsdtar_test_CPPFLAGS=\
-I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
-I$(top_srcdir)/test_utils \
- -I$(top_srcdir)/tar -I$(top_builddir)/tar/test \
+ -I$(top_srcdir)/tar -I$(top_srcdir)/tar/test \
+ -I$(top_builddir)/tar/test \
$(PLATFORMCPPFLAGS)
tar/test/list.h: Makefile
@@ -1076,7 +1083,6 @@ endif
bsdcpio_test_SOURCES= \
$(test_utils_SOURCES) \
cpio/cmdline.c \
- cpio/test/main.c \
cpio/test/test.h \
cpio/test/test_0.c \
cpio/test/test_basic.c \
@@ -1128,7 +1134,8 @@ bsdcpio_test_SOURCES= \
bsdcpio_test_CPPFLAGS= \
-I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
-I$(top_srcdir)/test_utils \
- -I$(top_srcdir)/cpio -I$(top_builddir)/cpio/test \
+ -I$(top_srcdir)/cpio -I$(top_srcdir)/cpio/test \
+ -I$(top_builddir)/cpio/test \
$(PLATFORMCPPFLAGS)
bsdcpio_test_LDADD=libarchive_fe.la
@@ -1223,7 +1230,6 @@ endif
bsdcat_test_SOURCES= \
$(test_utils_SOURCES) \
- cat/test/main.c \
cat/test/test.h \
cat/test/test_0.c \
cat/test/test_empty_gz.c \
@@ -1244,7 +1250,8 @@ bsdcat_test_SOURCES= \
bsdcat_test_CPPFLAGS= \
-I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
-I$(top_srcdir)/test_utils \
- -I$(top_srcdir)/cat -I$(top_builddir)/cat/test \
+ -I$(top_srcdir)/cat -I$(top_srcdir)/cat/test \
+ -I$(top_builddir)/cat/test \
$(PLATFORMCPPFLAGS)
bsdcat_test_LDADD=libarchive_fe.la
diff --git a/NEWS b/NEWS
index 7b5c31f75c7d..281c1768c30b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+Feb 26, 2017: libarchive 3.3.1 released
+ Security & Feature release
+
+Feb 19, 2017: libarchive 3.3.0 released
+ Security & Feature release
+
Jan 29, 2017: Limited NFSv4 ACL support for Mac OS (Darwin)
Jan 10, 2017: POSIX.1e and NFSv4 ACL support for Solaris and derivates
@@ -5,6 +11,8 @@ Jan 10, 2017: POSIX.1e and NFSv4 ACL support for Solaris and derivates
Dec 27, 2016: NFSv4 ACL read and write support for pax
Deprecated functions: archive_entry_acl_text(), archive_entry_acl_text_w()
+Nov, 2016: libarchive is now being tested by the OSS-Fuzz project
+
Oct 26, 2016: Remove liblzmadec support
Oct 23, 2016: libarchive 3.2.2 released
diff --git a/build/autogen.sh b/build/autogen.sh
index 64767b6ee6ca..e720e9b789b5 100755
--- a/build/autogen.sh
+++ b/build/autogen.sh
@@ -51,6 +51,7 @@ perl -p -i -e 's/(m4_define\(\[LIBARCHIVE_VERSION_N\]),.*\)/$1,['"$VN"'])/' conf
# 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 ec64d9937fab..923a78e51738 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -1099,6 +1099,9 @@ typedef uint64_t uintmax_t;
/* 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 f54ddaaefc3d..ef8345726c8a 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3002002
+3003001
diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt
index c4642aea4794..7f1ce5e77d13 100644
--- a/cat/test/CMakeLists.txt
+++ b/cat/test/CMakeLists.txt
@@ -6,7 +6,7 @@
IF(ENABLE_CAT AND ENABLE_TEST)
SET(bsdcat_test_SOURCES
../../test_utils/test_utils.c
- main.c
+ ../../test_utils/test_main.c
test.h
test_0.c
test_empty_gz.c
@@ -54,6 +54,7 @@ IF(ENABLE_CAT AND ENABLE_TEST)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
+ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cat/test)
# Experimental new test handling
ADD_CUSTOM_TARGET(run_bsdcat_test
diff --git a/cat/test/main.c b/cat/test/main.c
deleted file mode 100644
index cdfdd9bd6d75..000000000000
--- a/cat/test/main.c
+++ /dev/null
@@ -1,3072 +0,0 @@
-/*
- * Copyright (c) 2003-2009 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 "test.h"
-#include "test_utils.h"
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_ICONV_H
-#include <iconv.h>
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h> /* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
-#endif
-#include <limits.h>
-#include <locale.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <stdarg.h>
-#include <time.h>
-
-/*
- * This same file is used pretty much verbatim for all test harnesses.
- *
- * The next few lines are the only differences.
- * TODO: Move this into a separate configuration header, have all test
- * suites share one copy of this file.
- */
-#define KNOWNREF "test_expand.Z.uu"
-#define ENVBASE "BSDCAT" /* Prefix for environment variables. */
-#define PROGRAM "bsdcat" /* Name of program being tested. */
-#define PROGRAM_ALIAS "cat" /* Generic alias for program */
-#undef LIBRARY /* Not testing a library. */
-#undef EXTRA_DUMP /* How to dump extra data */
-#undef EXTRA_ERRNO /* How to dump errno */
-/* How to generate extra version info. */
-#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
-
-/*
- *
- * Windows support routines
- *
- * Note: Configuration is a tricky issue. Using HAVE_* feature macros
- * in the test harness is dangerous because they cover up
- * configuration errors. The classic example of this is omitting a
- * configure check. If libarchive and libarchive_test both look for
- * the same feature macro, such errors are hard to detect. Platform
- * macros (e.g., _WIN32 or __GNUC__) are a little better, but can
- * easily lead to very messy code. It's best to limit yourself
- * to only the most generic programming techniques in the test harness
- * and thus avoid conditionals altogether. Where that's not possible,
- * try to minimize conditionals by grouping platform-specific tests in
- * one place (e.g., test_acl_freebsd) or by adding new assert()
- * functions (e.g., assertMakeHardlink()) to cover up platform
- * differences. Platform-specific coding in libarchive_test is often
- * a symptom that some capability is missing from libarchive itself.
- */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
-#include <direct.h>
-#include <windows.h>
-#ifndef F_OK
-#define F_OK (0)
-#endif
-#ifndef S_ISDIR
-#define S_ISDIR(m) ((m) & _S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(m) ((m) & _S_IFREG)
-#endif
-#if !defined(__BORLANDC__)
-#define access _access
-#undef chdir
-#define chdir _chdir
-#endif
-#ifndef fileno
-#define fileno _fileno
-#endif
-/*#define fstat _fstat64*/
-#if !defined(__BORLANDC__)
-#define getcwd _getcwd
-#endif
-#define lstat stat
-/*#define lstat _stat64*/
-/*#define stat _stat64*/
-#define rmdir _rmdir
-#if !defined(__BORLANDC__)
-#define strdup _strdup
-#define umask _umask
-#endif
-#define int64_t __int64
-#endif
-
-#if defined(HAVE__CrtSetReportMode)
-# include <crtdbg.h>
-#endif
-
-mode_t umasked(mode_t expected_mode)
-{
- mode_t mode = umask(0);
- umask(mode);
- return expected_mode & ~mode;
-}
-
-/* Path to working directory for current test */
-const char *testworkdir;
-#ifdef PROGRAM
-/* Pathname of exe to be tested. */
-const char *testprogfile;
-/* Name of exe to use in printf-formatted command strings. */
-/* On Windows, this includes leading/trailing quotes. */
-const char *testprog;
-#endif
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static void *GetFunctionKernel32(const char *);
-static int my_CreateSymbolicLinkA(const char *, const char *, int);
-static int my_CreateHardLinkA(const char *, const char *);
-static int my_GetFileInformationByName(const char *,
- BY_HANDLE_FILE_INFORMATION *);
-
-static void *
-GetFunctionKernel32(const char *name)
-{
- static HINSTANCE lib;
- static int set;
- if (!set) {
- set = 1;
- lib = LoadLibrary("kernel32.dll");
- }
- if (lib == NULL) {
- fprintf(stderr, "Can't load kernel32.dll?!\n");
- exit(1);
- }
- return (void *)GetProcAddress(lib, name);
-}
-
-static int
-my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateSymbolicLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, flags);
-}
-
-static int
-my_CreateHardLinkA(const char *linkname, const char *target)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateHardLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, NULL);
-}
-
-static int
-my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
-{
- HANDLE h;
- int r;
-
- memset(bhfi, 0, sizeof(*bhfi));
- h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE)
- return (0);
- r = GetFileInformationByHandle(h, bhfi);
- CloseHandle(h);
- return (r);
-}
-#endif
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
-static void
-invalid_parameter_handler(const wchar_t * expression,
- const wchar_t * function, const wchar_t * file,
- unsigned int line, uintptr_t pReserved)
-{
- /* nop */
-}
-#endif
-
-/*
- *
- * OPTIONS FLAGS
- *
- */
-
-/* Enable core dump on failure. */
-static int dump_on_failure = 0;
-/* Default is to remove temp dirs and log data for successful tests. */
-static int keep_temp_files = 0;
-/* Default is to run the specified tests once and report errors. */
-static int until_failure = 0;
-/* Default is to just report pass/fail for each test. */
-static int verbosity = 0;
-#define VERBOSITY_SUMMARY_ONLY -1 /* -q */
-#define VERBOSITY_PASSFAIL 0 /* Default */
-#define VERBOSITY_LIGHT_REPORT 1 /* -v */
-#define VERBOSITY_FULL 2 /* -vv */
-/* A few places generate even more output for verbosity > VERBOSITY_FULL,
- * mostly for debugging the test harness itself. */
-/* Cumulative count of assertion failures. */
-static int failures = 0;
-/* Cumulative count of reported skips. */
-static int skips = 0;
-/* Cumulative count of assertions checked. */
-static int assertions = 0;
-
-/* Directory where uuencoded reference files can be found. */
-static const char *refdir;
-
-/*
- * Report log information selectively to console and/or disk log.
- */
-static int log_console = 0;
-static FILE *logfile;
-static void
-vlogprintf(const char *fmt, va_list ap)
-{
-#ifdef va_copy
- va_list lfap;
- va_copy(lfap, ap);
-#endif
- if (log_console)
- vfprintf(stdout, fmt, ap);
- if (logfile != NULL)
-#ifdef va_copy
- vfprintf(logfile, fmt, lfap);
- va_end(lfap);
-#else
- vfprintf(logfile, fmt, ap);
-#endif
-}
-
-static void
-logprintf(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogprintf(fmt, ap);
- va_end(ap);
-}
-
-/* Set up a message to display only if next assertion fails. */
-static char msgbuff[4096];
-static const char *msg, *nextmsg;
-void
-failure(const char *fmt, ...)
-{
- va_list ap;
- if (fmt == NULL) {
- nextmsg = NULL;
- } else {
- va_start(ap, fmt);
- vsprintf(msgbuff, fmt, ap);
- va_end(ap);
- nextmsg = msgbuff;
- }
-}
-
-/*
- * Copy arguments into file-local variables.
- * This was added to permit vararg assert() functions without needing
- * variadic wrapper macros. Turns out that the vararg capability is almost
- * never used, so almost all of the vararg assertions can be simplified
- * by removing the vararg capability and reworking the wrapper macro to
- * pass __FILE__, __LINE__ directly into the function instead of using
- * this hook. I suspect this machinery is used so rarely that we
- * would be better off just removing it entirely. That would simplify
- * the code here noticeably.
- */
-static const char *skipping_filename;
-static int skipping_line;
-void skipping_setup(const char *filename, int line)
-{
- skipping_filename = filename;
- skipping_line = line;
-}
-
-/* Called at the beginning of each assert() function. */
-static void
-assertion_count(const char *file, int line)
-{
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- ++assertions;
- /* Proper handling of "failure()" message. */
- msg = nextmsg;
- nextmsg = NULL;
- /* Uncomment to print file:line after every assertion.
- * Verbose, but occasionally useful in tracking down crashes. */
- /* printf("Checked %s:%d\n", file, line); */
-}
-
-/*
- * For each test source file, we remember how many times each
- * assertion was reported. Cleared before each new test,
- * used by test_summarize().
- */
-static struct line {
- int count;
- int skip;
-} failed_lines[10000];
-const char *failed_filename;
-
-/* Count this failure, setup up log destination and handle initial report. */
-static void
-failure_start(const char *filename, int line, const char *fmt, ...)
-{
- va_list ap;
-
- /* Record another failure for this line. */
- ++failures;
- failed_filename = filename;
- failed_lines[line].count++;
-
- /* Determine whether to log header to console. */
- switch (verbosity) {
- case VERBOSITY_LIGHT_REPORT:
- log_console = (failed_lines[line].count < 2);
- break;
- default:
- log_console = (verbosity >= VERBOSITY_FULL);
- }
-
- /* Log file:line header for this failure */
- va_start(ap, fmt);
-#if _MSC_VER
- logprintf("%s(%d): ", filename, line);
-#else
- logprintf("%s:%d: ", filename, line);
-#endif
- vlogprintf(fmt, ap);
- va_end(ap);
- logprintf("\n");
-
- if (msg != NULL && msg[0] != '\0') {
- logprintf(" Description: %s\n", msg);
- msg = NULL;
- }
-
- /* Determine whether to log details to console. */
- if (verbosity == VERBOSITY_LIGHT_REPORT)
- log_console = 0;
-}
-
-/* Complete reporting of failed tests. */
-/*
- * The 'extra' hook here is used by libarchive to include libarchive
- * error messages with assertion failures. It could also be used
- * to add strerror() output, for example. Just define the EXTRA_DUMP()
- * macro appropriately.
- */
-static void
-failure_finish(void *extra)
-{
- (void)extra; /* UNUSED (maybe) */
-#ifdef EXTRA_DUMP
- if (extra != NULL) {
- logprintf(" errno: %d\n", EXTRA_ERRNO(extra));
- logprintf(" detail: %s\n", EXTRA_DUMP(extra));
- }
-#endif
-
- if (dump_on_failure) {
- fprintf(stderr,
- " *** forcing core dump so failure can be debugged ***\n");
- abort();
- }
-}
-
-/* Inform user that we're skipping some checks. */
-void
-test_skipping(const char *fmt, ...)
-{
- char buff[1024];
- va_list ap;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- va_end(ap);
- /* Use failure() message if set. */
- msg = nextmsg;
- nextmsg = NULL;
- /* failure_start() isn't quite right, but is awfully convenient. */
- failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff);
- --failures; /* Undo failures++ in failure_start() */
- /* Don't failure_finish() here. */
- /* Mark as skip, so doesn't count as failed test. */
- failed_lines[skipping_line].skip = 1;
- ++skips;
-}
-
-/*
- *
- * ASSERTIONS
- *
- */
-
-/* Generic assert() just displays the failed condition. */
-int
-assertion_assert(const char *file, int line, int value,
- const char *condition, void *extra)
-{
- assertion_count(file, line);
- if (!value) {
- failure_start(file, line, "Assertion failed: %s", condition);
- failure_finish(extra);
- }
- return (value);
-}
-
-/* chdir() and report any errors */
-int
-assertion_chdir(const char *file, int line, const char *pathname)
-{
- assertion_count(file, line);
- if (chdir(pathname) == 0)
- return (1);
- failure_start(file, line, "chdir(\"%s\")", pathname);
- failure_finish(NULL);
- return (0);
-
-}
-
-/* Verify two integers are equal. */
-int
-assertion_equal_int(const char *file, int line,
- long long v1, const char *e1, long long v2, const char *e2, void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Utility to convert a single UTF-8 sequence.
- */
-static int
-_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
- static const char utf8_count[256] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */
- 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */
- 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
- };
- int ch;
- int cnt;
- uint32_t wc;
-
- *pwc = 0;
-
- /* Sanity check. */
- if (n == 0)
- return (0);
- /*
- * Decode 1-4 bytes depending on the value of the first byte.
- */
- ch = (unsigned char)*s;
- if (ch == 0)
- return (0); /* Standard: return 0 for end-of-string. */
- cnt = utf8_count[ch];
-
- /* Invalid sequence or there are not plenty bytes. */
- if (n < (size_t)cnt)
- return (-1);
-
- /* Make a Unicode code point from a single UTF-8 sequence. */
- switch (cnt) {
- case 1: /* 1 byte sequence. */
- *pwc = ch & 0x7f;
- return (cnt);
- case 2: /* 2 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
- return (cnt);
- case 3: /* 3 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x0f) << 12)
- | ((s[1] & 0x3f) << 6)
- | (s[2] & 0x3f);
- if (wc < 0x800)
- return (-1);/* Overlong sequence. */
- break;
- case 4: /* 4 bytes sequence. */
- if (n < 4)
- return (-1);
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- if ((s[3] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x07) << 18)
- | ((s[1] & 0x3f) << 12)
- | ((s[2] & 0x3f) << 6)
- | (s[3] & 0x3f);
- if (wc < 0x10000)
- return (-1);/* Overlong sequence. */
- break;
- default:
- return (-1);
- }
-
- /* The code point larger than 0x10FFFF is not legal
- * Unicode values. */
- if (wc > 0x10FFFF)
- return (-1);
- /* Correctly gets a Unicode, returns used bytes. */
- *pwc = wc;
- return (cnt);
-}
-
-static void strdump(const char *e, const char *p, int ewidth, int utf8)
-{
- const char *q = p;
-
- logprintf(" %*s = ", ewidth, e);
- if (p == NULL) {
- logprintf("NULL\n");
- return;
- }
- logprintf("\"");
- while (*p != '\0') {
- unsigned int c = 0xff & *p++;
- switch (c) {
- case '\a': logprintf("\\a"); break;
- case '\b': logprintf("\\b"); break;
- case '\n': logprintf("\\n"); break;
- case '\r': logprintf("\\r"); break;
- default:
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else
- logprintf("\\x%02X", c);
- }
- }
- logprintf("\"");
- logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q));
-
- /*
- * If the current string is UTF-8, dump its code points.
- */
- if (utf8) {
- size_t len;
- uint32_t uc;
- int n;
- int cnt = 0;
-
- p = q;
- len = strlen(p);
- logprintf(" [");
- while ((n = _utf8_to_unicode(&uc, p, len)) > 0) {
- if (p != q)
- logprintf(" ");
- logprintf("%04X", uc);
- p += n;
- len -= n;
- cnt++;
- }
- logprintf("]");
- logprintf(" (count %d", cnt);
- if (n < 0) {
- logprintf(",unknown %d bytes", len);
- }
- logprintf(")");
-
- }
- logprintf("\n");
-}
-
-/* Verify two strings are equal, dump them if not. */
-int
-assertion_equal_string(const char *file, int line,
- const char *v1, const char *e1,
- const char *v2, const char *e2,
- void *extra, int utf8)
-{
- int l1, l2;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- l1 = (int)strlen(e1);
- l2 = (int)strlen(e2);
- if (l1 < l2)
- l1 = l2;
- strdump(e1, v1, l1, utf8);
- strdump(e2, v2, l1, utf8);
- failure_finish(extra);
- return (0);
-}
-
-static void
-wcsdump(const char *e, const wchar_t *w)
-{
- logprintf(" %s = ", e);
- if (w == NULL) {
- logprintf("(null)");
- return;
- }
- logprintf("\"");
- while (*w != L'\0') {
- unsigned int c = *w++;
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else if (c < 256)
- logprintf("\\x%02X", c);
- else if (c < 0x10000)
- logprintf("\\u%04X", c);
- else
- logprintf("\\U%08X", c);
- }
- logprintf("\"\n");
-}
-
-#ifndef HAVE_WCSCMP
-static int
-wcscmp(const wchar_t *s1, const wchar_t *s2)
-{
-
- while (*s1 == *s2++) {
- if (*s1++ == L'\0')
- return 0;
- }
- if (*s1 > *--s2)
- return 1;
- else
- return -1;
-}
-#endif
-
-/* Verify that two wide strings are equal, dump them if not. */
-int
-assertion_equal_wstring(const char *file, int line,
- const wchar_t *v1, const char *e1,
- const wchar_t *v2, const char *e2,
- void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- wcsdump(e1, v1);
- wcsdump(e2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Pretty standard hexdump routine. As a bonus, if ref != NULL, then
- * any bytes in p that differ from ref will be highlighted with '_'
- * before and after the hex value.
- */
-static void
-hexdump(const char *p, const char *ref, size_t l, size_t offset)
-{
- size_t i, j;
- char sep;
-
- if (p == NULL) {
- logprintf("(null)\n");
- return;
- }
- for(i=0; i < l; i+=16) {
- logprintf("%04x", (unsigned)(i + offset));
- sep = ' ';
- for (j = 0; j < 16 && i + j < l; j++) {
- if (ref != NULL && p[i + j] != ref[i + j])
- sep = '_';
- logprintf("%c%02x", sep, 0xff & (int)p[i+j]);
- if (ref != NULL && p[i + j] == ref[i + j])
- sep = ' ';
- }
- for (; j < 16; j++) {
- logprintf("%c ", sep);
- sep = ' ';
- }
- logprintf("%c", sep);
- for (j=0; j < 16 && i + j < l; j++) {
- int c = p[i + j];
- if (c >= ' ' && c <= 126)
- logprintf("%c", c);
- else
- logprintf(".");
- }
- logprintf("\n");
- }
-}
-
-/* Verify that two blocks of memory are the same, display the first
- * block of differences if they're not. */
-int
-assertion_equal_mem(const char *file, int line,
- const void *_v1, const char *e1,
- const void *_v2, const char *e2,
- size_t l, const char *ld, void *extra)
-{
- const char *v1 = (const char *)_v1;
- const char *v2 = (const char *)_v2;
- size_t offset;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0))
- return (1);
- if (v1 == NULL || v2 == NULL)
- return (0);
-
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" size %s = %d\n", ld, (int)l);
- /* Dump 48 bytes (3 lines) so that the first difference is
- * in the second line. */
- offset = 0;
- while (l > 64 && memcmp(v1, v2, 32) == 0) {
- /* Two lines agree, so step forward one line. */
- v1 += 16;
- v2 += 16;
- l -= 16;
- offset += 16;
- }
- logprintf(" Dump of %s\n", e1);
- hexdump(v1, v2, l < 128 ? l : 128, offset);
- logprintf(" Dump of %s\n", e2);
- hexdump(v2, v1, l < 128 ? l : 128, offset);
- logprintf("\n");
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that a block of memory is filled with the specified byte. */
-int
-assertion_memory_filled_with(const char *file, int line,
- const void *_v1, const char *vd,
- size_t l, const char *ld,
- char b, const char *bd, void *extra)
-{
- const char *v1 = (const char *)_v1;
- size_t c = 0;
- size_t i;
- (void)ld; /* UNUSED */
-
- assertion_count(file, line);
-
- for (i = 0; i < l; ++i) {
- if (v1[i] == b) {
- ++c;
- }
- }
- if (c == l)
- return (1);
-
- failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
- logprintf(" Only %d bytes were correct\n", (int)c);
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that the named file exists and is empty. */
-int
-assertion_empty_file(const char *filename, int line, const char *f1)
-{
- char buff[1024];
- struct stat st;
- ssize_t s;
- FILE *f;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0)
- return (1);
-
- failure_start(filename, line, "File should be empty: %s", f1);
- logprintf(" File size: %d\n", (int)st.st_size);
- logprintf(" Contents:\n");
- f = fopen(f1, "rb");
- if (f == NULL) {
- logprintf(" Unable to open %s\n", f1);
- } else {
- s = ((off_t)sizeof(buff) < st.st_size) ?
- (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
- s = fread(buff, 1, s, f);
- hexdump(buff, NULL, s, 0);
- fclose(f);
- }
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file exists and is not empty. */
-int
-assertion_non_empty_file(const char *filename, int line, const char *f1)
-{
- struct stat st;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0) {
- failure_start(filename, line, "File empty: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify that two files have the same contents. */
-/* TODO: hexdump the first bytes that actually differ. */
-int
-assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2)
-{
- char buff1[1024];
- char buff2[1024];
- FILE *f1, *f2;
- int n1, n2;
-
- assertion_count(filename, line);
-
- f1 = fopen(fn1, "rb");
- f2 = fopen(fn2, "rb");
- if (f1 == NULL || f2 == NULL) {
- if (f1) fclose(f1);
- if (f2) fclose(f2);
- return (0);
- }
- for (;;) {
- n1 = (int)fread(buff1, 1, sizeof(buff1), f1);
- n2 = (int)fread(buff2, 1, sizeof(buff2), f2);
- if (n1 != n2)
- break;
- if (n1 == 0 && n2 == 0) {
- fclose(f1);
- fclose(f2);
- return (1);
- }
- if (memcmp(buff1, buff2, n1) != 0)
- break;
- }
- fclose(f1);
- fclose(f2);
- failure_start(filename, line, "Files not identical");
- logprintf(" file1=\"%s\"\n", fn1);
- logprintf(" file2=\"%s\"\n", fn2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file does exist. */
-int
-assertion_file_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (!_access(f, 0))
- return (1);
-#else
- if (!access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file doesn't exist. */
-int
-assertion_file_not_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (_access(f, 0))
- return (1);
-#else
- if (access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should not exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Compare the contents of a file to a block of memory. */
-int
-assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn)
-{
- char *contents;
- FILE *f;
- int n;
-
- assertion_count(filename, line);
-
- f = fopen(fn, "rb");
- if (f == NULL) {
- failure_start(filename, line,
- "File should exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- contents = malloc(s * 2);
- n = (int)fread(contents, 1, s * 2, f);
- fclose(f);
- if (n == s && memcmp(buff, contents, s) == 0) {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "File contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0)
- hexdump(contents, buff, n > 512 ? 512 : n, 0);
- else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s > 512 ? 512 : s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Check the contents of a text file, being tolerant of line endings. */
-int
-assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn)
-{
- char *contents;
- const char *btxt, *ftxt;
- FILE *f;
- int n, s;
-
- assertion_count(filename, line);
- f = fopen(fn, "r");
- if (f == NULL) {
- failure_start(filename, line,
- "File doesn't exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- s = (int)strlen(buff);
- contents = malloc(s * 2 + 128);
- n = (int)fread(contents, 1, s * 2 + 128 - 1, f);
- if (n >= 0)
- contents[n] = '\0';
- fclose(f);
- /* Compare texts. */
- btxt = buff;
- ftxt = (const char *)contents;
- while (*btxt != '\0' && *ftxt != '\0') {
- if (*btxt == *ftxt) {
- ++btxt;
- ++ftxt;
- continue;
- }
- if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') {
- /* Pass over different new line characters. */
- ++btxt;
- ftxt += 2;
- continue;
- }
- break;
- }
- if (*btxt == '\0' && *ftxt == '\0') {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "Contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0) {
- hexdump(contents, buff, n, 0);
- logprintf(" expected\n", fn);
- hexdump(buff, contents, s, 0);
- } else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Verify that a text file contains the specified lines, regardless of order */
-/* This could be more efficient if we sorted both sets of lines, etc, but
- * since this is used only for testing and only ever deals with a dozen or so
- * lines at a time, this relatively crude approach is just fine. */
-int
-assertion_file_contains_lines_any_order(const char *file, int line,
- const char *pathname, const char *lines[])
-{
- char *buff;
- size_t buff_size;
- size_t expected_count, actual_count, i, j;
- char **expected = NULL;
- char *p, **actual = NULL;
- char c;
- int expected_failure = 0, actual_failure = 0;
-
- assertion_count(file, line);
-
- buff = slurpfile(&buff_size, "%s", pathname);
- if (buff == NULL) {
- failure_start(pathname, line, "Can't read file: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- /* Make a copy of the provided lines and count up the expected
- * file size. */
- for (i = 0; lines[i] != NULL; ++i) {
- }
- expected_count = i;
- if (expected_count) {
- expected = malloc(sizeof(char *) * expected_count);
- if (expected == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- free(expected);
- return (0);
- }
- for (i = 0; lines[i] != NULL; ++i) {
- expected[i] = strdup(lines[i]);
- }
- }
-
- /* Break the file into lines */
- actual_count = 0;
- for (c = '\0', p = buff; p < buff + buff_size; ++p) {
- if (*p == '\x0d' || *p == '\x0a')
- *p = '\0';
- if (c == '\0' && *p != '\0')
- ++actual_count;
- c = *p;
- }
- if (actual_count) {
- actual = calloc(sizeof(char *), actual_count);
- if (actual == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- free(expected);
- return (0);
- }
- for (j = 0, p = buff; p < buff + buff_size;
- p += 1 + strlen(p)) {
- if (*p != '\0') {
- actual[j] = p;
- ++j;
- }
- }
- }
-
- /* Erase matching lines from both lists */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] == NULL)
- continue;
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] == NULL)
- continue;
- if (strcmp(expected[i], actual[j]) == 0) {
- free(expected[i]);
- expected[i] = NULL;
- actual[j] = NULL;
- break;
- }
- }
- }
-
- /* If there's anything left, it's a failure */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL)
- ++expected_failure;
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- ++actual_failure;
- }
- if (expected_failure == 0 && actual_failure == 0) {
- free(buff);
- free(expected);
- free(actual);
- return (1);
- }
- failure_start(file, line, "File doesn't match: %s", pathname);
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL) {
- logprintf(" Expected but not present: %s\n", expected[i]);
- free(expected[i]);
- }
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- logprintf(" Present but not expected: %s\n", actual[j]);
- }
- failure_finish(NULL);
- free(buff);
- free(expected);
- free(actual);
- return (0);
-}
-
-/* Verify that a text file does not contains the specified strings */
-int
-assertion_file_contains_no_invalid_strings(const char *file, int line,
- const char *pathname, const char *strings[])
-{
- char *buff;
- int i;
-
- buff = slurpfile(NULL, "%s", pathname);
- if (buff == NULL) {
- failure_start(file, line, "Can't read file: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- for (i = 0; strings[i] != NULL; ++i) {
- if (strstr(buff, strings[i]) != NULL) {
- failure_start(file, line, "Invalid string in %s: %s", pathname,
- strings[i]);
- failure_finish(NULL);
- free(buff);
- return(0);
- }
- }
-
- free(buff);
- return (0);
-}
-
-/* Test that two paths point to the same file. */
-/* As a side-effect, asserts that both files exist. */
-static int
-is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(path1, &bhfi1);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path1);
- failure_finish(NULL);
- return (0);
- }
- r = my_GetFileInformationByName(path2, &bhfi2);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path2);
- failure_finish(NULL);
- return (0);
- }
- return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber
- && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
- && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
-#else
- struct stat st1, st2;
- int r;
-
- assertion_count(file, line);
- r = lstat(path1, &st1);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path1);
- failure_finish(NULL);
- return (0);
- }
- r = lstat(path2, &st2);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path2);
- failure_finish(NULL);
- return (0);
- }
- return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
-#endif
-}
-
-int
-assertion_is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s are not hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-int
-assertion_is_not_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (!is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s should not be hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify a/b/mtime of 'pathname'. */
-/* If 'recent', verify that it's within last 10 seconds. */
-static int
-assertion_file_time(const char *file, int line,
- const char *pathname, long t, long nsec, char type, int recent)
-{
- long long filet, filet_nsec;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME (116444736000000000ULL)
- FILETIME fxtime, fbirthtime, fatime, fmtime;
- ULARGE_INTEGER wintm;
- HANDLE h;
- fxtime.dwLowDateTime = 0;
- fxtime.dwHighDateTime = 0;
-
- assertion_count(file, line);
- /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
- * a directory file. If not, CreateFile() will fail when
- * the pathname is a directory. */
- h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = GetFileTime(h, &fbirthtime, &fatime, &fmtime);
- switch (type) {
- case 'a': fxtime = fatime; break;
- case 'b': fxtime = fbirthtime; break;
- case 'm': fxtime = fmtime; break;
- }
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't GetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- wintm.LowPart = fxtime.dwLowDateTime;
- wintm.HighPart = fxtime.dwHighDateTime;
- filet = (wintm.QuadPart - EPOC_TIME) / 10000000;
- filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100;
- nsec = (nsec / 100) * 100; /* Round the request */
-#else
- struct stat st;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- switch (type) {
- case 'a': filet = st.st_atime; break;
- case 'm': filet = st.st_mtime; break;
- case 'b': filet = 0; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
-#if defined(__FreeBSD__)
- switch (type) {
- case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
- case 'b': filet = st.st_birthtime;
- /* FreeBSD filesystems that don't support birthtime
- * (e.g., UFS1) always return -1 here. */
- if (filet == -1) {
- return (1);
- }
- filet_nsec = st.st_birthtimespec.tv_nsec; break;
- case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
- /* FreeBSD generally only stores to microsecond res, so round. */
- filet_nsec = (filet_nsec / 1000) * 1000;
- nsec = (nsec / 1000) * 1000;
-#else
- filet_nsec = nsec = 0; /* Generic POSIX only has whole seconds. */
- if (type == 'b') return (1); /* Generic POSIX doesn't have birthtime */
-#if defined(__HAIKU__)
- if (type == 'a') return (1); /* Haiku doesn't have atime. */
-#endif
-#endif
-#endif
- if (recent) {
- /* Check that requested time is up-to-date. */
- time_t now = time(NULL);
- if (filet < now - 10 || filet > now + 1) {
- failure_start(file, line,
- "File %s has %ctime %lld, %lld seconds ago\n",
- pathname, type, filet, now - filet);
- failure_finish(NULL);
- return (0);
- }
- } else if (filet != t || filet_nsec != nsec) {
- failure_start(file, line,
- "File %s has %ctime %lld.%09lld, expected %lld.%09lld",
- pathname, type, filet, filet_nsec, t, nsec);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify atime of 'pathname'. */
-int
-assertion_file_atime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'a', 0);
-}
-
-/* Verify atime of 'pathname' is up-to-date. */
-int
-assertion_file_atime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'a', 1);
-}
-
-/* Verify birthtime of 'pathname'. */
-int
-assertion_file_birthtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'b', 0);
-}
-
-/* Verify birthtime of 'pathname' is up-to-date. */
-int
-assertion_file_birthtime_recent(const char *file, int line,
- const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'b', 1);
-}
-
-/* Verify mode of 'pathname'. */
-int
-assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode)
-{
- int mode;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- failure_start(file, line, "assertFileMode not yet implemented for Windows");
- (void)mode; /* UNUSED */
- (void)r; /* UNUSED */
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- mode = (int)(st.st_mode & 0777);
- }
- if (r == 0 && mode == expected_mode)
- return (1);
- failure_start(file, line, "File %s has mode %o, expected %o",
- pathname, mode, expected_mode);
-#endif
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify mtime of 'pathname'. */
-int
-assertion_file_mtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'm', 0);
-}
-
-/* Verify mtime of 'pathname' is up-to-date. */
-int
-assertion_file_mtime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'm', 1);
-}
-
-/* Verify number of links to 'pathname'. */
-int
-assertion_file_nlinks(const char *file, int line,
- const char *pathname, int nlinks)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(pathname, &bhfi);
- if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, bhfi.nNumberOfLinks, nlinks);
- failure_finish(NULL);
- return (0);
-#else
- struct stat st;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, st.st_nlink, nlinks);
- failure_finish(NULL);
- return (0);
-#endif
-}
-
-/* Verify size of 'pathname'. */
-int
-assertion_file_size(const char *file, int line, const char *pathname, long size)
-{
- int64_t filesize;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- {
- BY_HANDLE_FILE_INFORMATION bhfi;
- r = !my_GetFileInformationByName(pathname, &bhfi);
- filesize = ((int64_t)bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow;
- }
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- filesize = st.st_size;
- }
-#endif
- if (r == 0 && filesize == size)
- return (1);
- failure_start(file, line, "File %s has size %ld, expected %ld",
- pathname, (long)filesize, (long)size);
- failure_finish(NULL);
- return (0);
-}
-
-/* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */
-int
-assertion_is_dir(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Dir should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISDIR(st.st_mode)) {
- failure_start(file, line, "%s is not a dir", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "Dir %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Verify that 'pathname' is a regular file. If 'mode' is >= 0,
- * verify that too. */
-int
-assertion_is_reg(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0 || !S_ISREG(st.st_mode)) {
- failure_start(file, line, "File should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "File %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Check whether 'pathname' is a symbolic link. If 'contents' is
- * non-NULL, verify that the symlink has those contents. */
-static int
-is_symlink(const char *file, int line,
- const char *pathname, const char *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)pathname; /* UNUSED */
- (void)contents; /* UNUSED */
- assertion_count(file, line);
- /* Windows sort-of has real symlinks, but they're only usable
- * by privileged users and are crippled even then, so there's
- * really not much point in bothering with this. */
- return (0);
-#else
- char buff[300];
- struct stat st;
- ssize_t linklen;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line,
- "Symlink should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISLNK(st.st_mode))
- return (0);
- if (contents == NULL)
- return (1);
- linklen = readlink(pathname, buff, sizeof(buff));
- if (linklen < 0) {
- failure_start(file, line, "Can't read symlink %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- buff[linklen] = '\0';
- if (strcmp(buff, contents) != 0)
- return (0);
- return (1);
-#endif
-}
-
-/* Assert that path is a symlink that (optionally) contains contents. */
-int
-assertion_is_symlink(const char *file, int line,
- const char *path, const char *contents)
-{
- if (is_symlink(file, line, path, contents))
- return (1);
- if (contents)
- failure_start(file, line, "File %s is not a symlink to %s",
- path, contents);
- else
- failure_start(file, line, "File %s is not a symlink", path);
- failure_finish(NULL);
- return (0);
-}
-
-
-/* Create a directory and report any errors. */
-int
-assertion_make_dir(const char *file, int line, const char *dirname, int mode)
-{
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
- if (0 == _mkdir(dirname))
- return (1);
-#else
- if (0 == mkdir(dirname, mode)) {
- if (0 == chmod(dirname, mode)) {
- assertion_file_mode(file, line, dirname, mode);
- return (1);
- }
- }
-#endif
- failure_start(file, line, "Could not create directory %s", dirname);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a file with the specified contents and report any failures. */
-int
-assertion_make_file(const char *file, int line,
- const char *path, int mode, int csize, const void *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* TODO: Rework this to set file mode as well. */
- FILE *f;
- (void)mode; /* UNUSED */
- assertion_count(file, line);
- f = fopen(path, "wb");
- if (f == NULL) {
- failure_start(file, line, "Could not create file %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (contents != NULL) {
- size_t wsize;
-
- if (csize < 0)
- wsize = strlen(contents);
- else
- wsize = (size_t)csize;
- if (wsize != fwrite(contents, 1, wsize, f)) {
- fclose(f);
- failure_start(file, line,
- "Could not write file %s", path);
- failure_finish(NULL);
- return (0);
- }
- }
- fclose(f);
- return (1);
-#else
- int fd;
- assertion_count(file, line);
- fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
- if (fd < 0) {
- failure_start(file, line, "Could not create %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (0 != chmod(path, mode)) {
- failure_start(file, line, "Could not chmod %s", path);
- failure_finish(NULL);
- close(fd);
- return (0);
- }
- if (contents != NULL) {
- ssize_t wsize;
-
- if (csize < 0)
- wsize = (ssize_t)strlen(contents);
- else
- wsize = (ssize_t)csize;
- if (wsize != write(fd, contents, wsize)) {
- close(fd);
- failure_start(file, line,
- "Could not write to %s", path);
- failure_finish(NULL);
- close(fd);
- return (0);
- }
- }
- close(fd);
- assertion_file_mode(file, line, path, mode);
- return (1);
-#endif
-}
-
-/* Create a hardlink and report any failures. */
-int
-assertion_make_hardlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
- int succeeded;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- succeeded = my_CreateHardLinkA(newpath, linkto);
-#elif HAVE_LINK
- succeeded = !link(linkto, newpath);
-#else
- succeeded = 0;
-#endif
- if (succeeded)
- return (1);
- failure_start(file, line, "Could not create hardlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a symlink and report any failures. */
-int
-assertion_make_symlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- int targetIsDir = 0; /* TODO: Fix this */
- assertion_count(file, line);
- if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
- return (1);
-#elif HAVE_SYMLINK
- assertion_count(file, line);
- if (0 == symlink(linkto, newpath))
- return (1);
-#endif
- failure_start(file, line, "Could not create symlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Set umask, report failures. */
-int
-assertion_umask(const char *file, int line, int mask)
-{
- assertion_count(file, line);
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- umask(mask);
- return (1);
-}
-
-/* Set times, report failures. */
-int
-assertion_utimes(const char *file, int line,
- const char *pathname, long at, long at_nsec, long mt, long mt_nsec)
-{
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
- + (((nsec)/1000)*10))
- HANDLE h;
- ULARGE_INTEGER wintm;
- FILETIME fatime, fmtime;
- FILETIME *pat, *pmt;
-
- assertion_count(file, line);
- h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (at > 0 || at_nsec > 0) {
- wintm.QuadPart = WINTIME(at, at_nsec);
- fatime.dwLowDateTime = wintm.LowPart;
- fatime.dwHighDateTime = wintm.HighPart;
- pat = &fatime;
- } else
- pat = NULL;
- if (mt > 0 || mt_nsec > 0) {
- wintm.QuadPart = WINTIME(mt, mt_nsec);
- fmtime.dwLowDateTime = wintm.LowPart;
- fmtime.dwHighDateTime = wintm.HighPart;
- pmt = &fmtime;
- } else
- pmt = NULL;
- if (pat != NULL || pmt != NULL)
- r = SetFileTime(h, NULL, pat, pmt);
- else
- r = 1;
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't SetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#else /* defined(_WIN32) && !defined(__CYGWIN__) */
- struct stat st;
- struct timeval times[2];
-
-#if !defined(__FreeBSD__)
- mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */
-#endif
- if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0)
- return (1);
-
- r = lstat(pathname, &st);
- if (r < 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (mt == 0 && mt_nsec == 0) {
- mt = st.st_mtime;
-#if defined(__FreeBSD__)
- mt_nsec = st.st_mtimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- mt_nsec = (mt_nsec / 1000) * 1000;
-#endif
- }
- if (at == 0 && at_nsec == 0) {
- at = st.st_atime;
-#if defined(__FreeBSD__)
- at_nsec = st.st_atimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- at_nsec = (at_nsec / 1000) * 1000;
-#endif
- }
-
- times[1].tv_sec = mt;
- times[1].tv_usec = mt_nsec / 1000;
-
- times[0].tv_sec = at;
- times[0].tv_usec = at_nsec / 1000;
-
-#ifdef HAVE_LUTIMES
- r = lutimes(pathname, times);
-#else
- r = utimes(pathname, times);
-#endif
- if (r < 0) {
- failure_start(file, line, "Can't utimes %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
-}
-
-/* Set nodump, report failures. */
-int
-assertion_nodump(const char *file, int line, const char *pathname)
-{
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
- int r;
-
- assertion_count(file, line);
- r = chflags(pathname, UF_NODUMP);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-#elif defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)\
- && defined(EXT2_NODUMP_FL)
- int fd, r, flags;
-
- assertion_count(file, line);
- fd = open(pathname, O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
- failure_start(file, line, "Can't open %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't get flags %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- close(fd);
-#else
- (void)pathname; /* UNUSED */
- assertion_count(file, line);
-#endif
- return (1);
-}
-
-/*
- *
- * UTILITIES for use by tests.
- *
- */
-
-/*
- * Check whether platform supports symlinks. This is intended
- * for tests to use in deciding whether to bother testing symlink
- * support; if the platform doesn't support symlinks, there's no point
- * in checking whether the program being tested can create them.
- *
- * Note that the first time this test is called, we actually go out to
- * disk to create and verify a symlink. This is necessary because
- * symlink support is actually a property of a particular filesystem
- * and can thus vary between directories on a single system. After
- * the first call, this returns the cached result from memory, so it's
- * safe to call it as often as you wish.
- */
-int
-canSymlink(void)
-{
- /* Remember the test result */
- static int value = 0, tested = 0;
- if (tested)
- return (value);
-
- ++tested;
- assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a");
- /* Note: Cygwin has its own symlink() emulation that does not
- * use the Win32 CreateSymbolicLink() function. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
- value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
- && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
-#elif HAVE_SYMLINK
- value = (0 == symlink("canSymlink.0", "canSymlink.1"))
- && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
-#endif
- return (value);
-}
-
-/* Platform-dependent options for hiding the output of a subcommand. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
-#else
-static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
-#endif
-/*
- * Can this platform run the bzip2 program?
- */
-int
-canBzip2(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("bzip2 -d -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the grzip program?
- */
-int
-canGrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("grzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the gzip program?
- */
-int
-canGzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("gzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lrzip program?
- */
-int
-canRunCommand(const char *cmd)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("%s %s", cmd, redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-int
-canLrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lrzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lz4 program?
- */
-int
-canLz4(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lz4 -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzip program?
- */
-int
-canLzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzma program?
- */
-int
-canLzma(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzma -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzop program?
- */
-int
-canLzop(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzop -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the xz program?
- */
-int
-canXz(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("xz -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this filesystem handle nodump flags.
- */
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
-
-int
-canNodump(void)
-{
- const char *path = "cannodumptest";
- struct stat sb;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- if (chflags(path, UF_NODUMP) < 0)
- return (0);
- if (stat(path, &sb) < 0)
- 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)
-{
- const char *path = "cannodumptest";
- int fd, r, flags;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- fd = open(path, O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- return (0);
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0)
- return (0);
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &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);
- if (r < 0)
- return (0);
- close(fd);
- if (flags & EXT2_NODUMP_FL)
- return (1);
- return (0);
-}
-
-#else
-
-int
-canNodump()
-{
- return (0);
-}
-
-#endif
-
-/*
- * Sleep as needed; useful for verifying disk timestamp changes by
- * ensuring that the wall-clock time has actually changed before we
- * go back to re-read something from disk.
- */
-void
-sleepUntilAfter(time_t t)
-{
- while (t >= time(NULL))
-#if defined(_WIN32) && !defined(__CYGWIN__)
- Sleep(500);
-#else
- sleep(1);
-#endif
-}
-
-/*
- * Call standard system() call, but build up the command line using
- * sprintf() conventions.
- */
-int
-systemf(const char *fmt, ...)
-{
- char buff[8192];
- va_list ap;
- int r;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- if (verbosity > VERBOSITY_FULL)
- logprintf("Cmd: %s\n", buff);
- r = system(buff);
- va_end(ap);
- return (r);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-char *
-slurpfile(size_t * sizep, const char *fmt, ...)
-{
- char filename[8192];
- struct stat st;
- va_list ap;
- char *p;
- ssize_t bytes_read;
- FILE *f;
- int r;
-
- va_start(ap, fmt);
- vsprintf(filename, fmt, ap);
- va_end(ap);
-
- f = fopen(filename, "rb");
- if (f == NULL) {
- /* Note: No error; non-existent file is okay here. */
- return (NULL);
- }
- r = fstat(fileno(f), &st);
- if (r != 0) {
- logprintf("Can't stat file %s\n", filename);
- fclose(f);
- return (NULL);
- }
- p = malloc((size_t)st.st_size + 1);
- if (p == NULL) {
- logprintf("Can't allocate %ld bytes of memory to read file %s\n",
- (long int)st.st_size, filename);
- fclose(f);
- return (NULL);
- }
- bytes_read = fread(p, 1, (size_t)st.st_size, f);
- if (bytes_read < st.st_size) {
- logprintf("Can't read file %s\n", filename);
- fclose(f);
- free(p);
- return (NULL);
- }
- p[st.st_size] = '\0';
- if (sizep != NULL)
- *sizep = (size_t)st.st_size;
- fclose(f);
- return (p);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-void
-dumpfile(const char *filename, void *data, size_t len)
-{
- ssize_t bytes_written;
- FILE *f;
-
- f = fopen(filename, "wb");
- if (f == NULL) {
- logprintf("Can't open file %s for writing\n", filename);
- return;
- }
- bytes_written = fwrite(data, 1, len, f);
- if (bytes_written < (ssize_t)len)
- logprintf("Can't write file %s\n", filename);
- fclose(f);
-}
-
-/* Read a uuencoded file from the reference directory, decode, and
- * write the result into the current directory. */
-#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
-#define UUDECODE(c) (((c) - 0x20) & 0x3f)
-void
-extract_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
-
- sprintf(buff, "%s/%s.uu", refdir, name);
- in = fopen(buff, "r");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Read up to and including the 'begin' line. */
- for (;;) {
- if (fgets(buff, sizeof(buff), in) == NULL) {
- /* TODO: This is a failure. */
- return;
- }
- if (memcmp(buff, "begin ", 6) == 0)
- break;
- }
- /* Now, decode the rest and write it. */
- out = fopen(name, "wb");
- while (fgets(buff, sizeof(buff), in) != NULL) {
- char *p = buff;
- int bytes;
-
- if (memcmp(buff, "end", 3) == 0)
- break;
-
- bytes = UUDECODE(*p++);
- while (bytes > 0) {
- int n = 0;
- /* Write out 1-3 bytes from that. */
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- assert(VALID_UUDECODE(p[1]));
- n = UUDECODE(*p++) << 18;
- n |= UUDECODE(*p++) << 12;
- fputc(n >> 16, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++) << 6;
- fputc((n >> 8) & 0xFF, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++);
- fputc(n & 0xFF, out);
- --bytes;
- }
- }
- }
- fclose(out);
- fclose(in);
-}
-
-void
-copy_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
- size_t rbytes;
-
- sprintf(buff, "%s/%s", refdir, name);
- in = fopen(buff, "rb");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
- out = fopen(name, "wb");
- while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- if (fwrite(buff, 1, rbytes, out) != rbytes) {
- logprintf("Error: fwrite\n");
- break;
- }
- }
- fclose(out);
- fclose(in);
-}
-
-int
-is_LargeInode(const char *file)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- r = my_GetFileInformationByName(file, &bhfi);
- if (r != 0)
- return (0);
- return (bhfi.nFileIndexHigh & 0x0000FFFFUL);
-#else
- struct stat st;
- int64_t ino;
-
- if (stat(file, &st) < 0)
- return (0);
- ino = (int64_t)st.st_ino;
- return (ino > 0xffffffff);
-#endif
-}
-
-void
-extract_reference_files(const char **names)
-{
- while (names && *names)
- extract_reference_file(*names++);
-}
-
-/*
- *
- * TEST management
- *
- */
-
-/*
- * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has
- * a line like
- * DEFINE_TEST(test_function)
- * for each test.
- */
-
-/* Use "list.h" to declare all of the test functions. */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void);
-#include "list.h"
-
-/* Use "list.h" to create a list of all tests (functions and names). */
-#undef DEFINE_TEST
-#define DEFINE_TEST(n) { n, #n, 0 },
-struct test_list_t tests[] = {
- #include "list.h"
-};
-
-/*
- * Summarize repeated failures in the just-completed test.
- */
-static void
-test_summarize(int failed, int skips_num)
-{
- unsigned int i;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY:
- printf(failed ? "E" : ".");
- fflush(stdout);
- break;
- case VERBOSITY_PASSFAIL:
- printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n");
- break;
- }
-
- log_console = (verbosity == VERBOSITY_LIGHT_REPORT);
-
- for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
- if (failed_lines[i].count > 1 && !failed_lines[i].skip)
- logprintf("%s:%d: Summary: Failed %d times\n",
- failed_filename, i, failed_lines[i].count);
- }
- /* Clear the failure history for the next file. */
- failed_filename = NULL;
- memset(failed_lines, 0, sizeof(failed_lines));
-}
-
-/*
- * Actually run a single test, with appropriate setup and cleanup.
- */
-static int
-test_run(int i, const char *tmpdir)
-{
- char workdir[1024];
- char logfilename[64];
- int failures_before = failures;
- int skips_before = skips;
- int oldumask;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
- break;
- case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
- printf("%3d: %-64s", i, tests[i].name);
- fflush(stdout);
- break;
- default: /* Title of test, details will follow */
- printf("%3d: %s\n", i, tests[i].name);
- }
-
- /* Chdir to the top-level work directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to top work dir %s\n", tmpdir);
- exit(1);
- }
- /* Create a log file for this test. */
- sprintf(logfilename, "%s.log", tests[i].name);
- logfile = fopen(logfilename, "w");
- fprintf(logfile, "%s\n\n", tests[i].name);
- /* Chdir() to a work dir for this specific test. */
- snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name);
- testworkdir = workdir;
- if (!assertMakeDir(testworkdir, 0755)
- || !assertChdir(testworkdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to work dir %s\n", testworkdir);
- exit(1);
- }
- /* Explicitly reset the locale before each test. */
- setlocale(LC_ALL, "C");
- /* Record the umask before we run the test. */
- umask(oldumask = umask(0));
- /*
- * Run the actual test.
- */
- (*tests[i].func)();
- /*
- * Clean up and report afterwards.
- */
- testworkdir = NULL;
- /* Restore umask */
- umask(oldumask);
- /* Reset locale. */
- setlocale(LC_ALL, "C");
- /* Reset directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n",
- tmpdir);
- exit(1);
- }
- /* Report per-test summaries. */
- tests[i].failures = failures - failures_before;
- test_summarize(tests[i].failures, skips - skips_before);
- /* Close the per-test log file. */
- fclose(logfile);
- logfile = NULL;
- /* If there were no failures, we can remove the work dir and logfile. */
- if (tests[i].failures == 0) {
- if (!keep_temp_files && assertChdir(tmpdir)) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure not to leave empty directories.
- * Sometimes a processing of closing files used by tests
- * is not done, then rmdir will be failed and it will
- * leave a empty test directory. So we should wait a few
- * seconds and retry rmdir. */
- int r, t;
- for (t = 0; t < 10; t++) {
- if (t > 0)
- Sleep(1000);
- r = systemf("rmdir /S /Q %s", tests[i].name);
- if (r == 0)
- break;
- }
- systemf("del %s", logfilename);
-#else
- systemf("rm -rf %s", tests[i].name);
- systemf("rm %s", logfilename);
-#endif
- }
- }
- /* Return appropriate status. */
- return (tests[i].failures);
-}
-
-/*
- *
- *
- * MAIN and support routines.
- *
- *
- */
-
-static void
-usage(const char *program)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int i;
-
- printf("Usage: %s [options] <test> <test> ...\n", program);
- printf("Default is to run all tests.\n");
- printf("Otherwise, specify the numbers of the tests you wish to run.\n");
- printf("Options:\n");
- printf(" -d Dump core after any failure, for debugging.\n");
- printf(" -k Keep all temp files.\n");
- printf(" Default: temp files for successful tests deleted.\n");
-#ifdef PROGRAM
- printf(" -p <path> Path to executable to be tested.\n");
- printf(" Default: path taken from " ENVBASE " environment variable.\n");
-#endif
- printf(" -q Quiet.\n");
- printf(" -r <dir> Path to dir containing reference files.\n");
- printf(" Default: Current directory.\n");
- printf(" -u Keep running specifies tests until one fails.\n");
- printf(" -v Verbose.\n");
- printf("Available tests:\n");
- for (i = 0; i < limit; i++)
- printf(" %d: %s\n", i, tests[i].name);
- exit(1);
-}
-
-static char *
-get_refdir(const char *d)
-{
- size_t tried_size, buff_size;
- char *buff, *tried, *pwd = NULL, *p = NULL;
-
-#ifdef PATH_MAX
- buff_size = PATH_MAX;
-#else
- buff_size = 8192;
-#endif
- buff = calloc(buff_size, 1);
- if (buff == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* Allocate a buffer to hold the various directories we checked. */
- tried_size = buff_size * 2;
- tried = calloc(tried_size, 1);
- if (tried == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* If a dir was specified, try that */
- if (d != NULL) {
- pwd = NULL;
- snprintf(buff, buff_size, "%s", d);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- goto failure;
- }
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
- /* Look for a known file. */
- snprintf(buff, buff_size, "%s", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(LIBRARY)
- snprintf(buff, buff_size, "%s/%s/test", pwd, LIBRARY);
-#else
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM);
-#endif
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(PROGRAM_ALIAS)
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM_ALIAS);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-#endif
-
- if (memcmp(pwd, "/usr/obj", 8) == 0) {
- snprintf(buff, buff_size, "%s", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- }
-
-failure:
- printf("Unable to locate known reference file %s\n", KNOWNREF);
- printf(" Checked following directories:\n%s\n", tried);
- printf("Use -r option to specify full path to reference directory\n");
-#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
- DebugBreak();
-#endif
- exit(1);
-
-success:
- free(p);
- free(pwd);
- free(tried);
-
- /* Copy result into a fresh buffer to reduce memory usage. */
- p = strdup(buff);
- free(buff);
- return p;
-}
-
-int
-main(int argc, char **argv)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int test_set[sizeof(tests) / sizeof(tests[0])];
- int i = 0, j = 0, tests_run = 0, tests_failed = 0, option;
- time_t now;
- char *refdir_alloc = NULL;
- const char *progname;
- char **saved_argv;
- const char *tmp, *option_arg, *p;
- char tmpdir[256], *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL;
- char tmpdir_timestamp[256];
-
- (void)argc; /* UNUSED */
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
- /* To stop to run the default invalid parameter handler. */
- _set_invalid_parameter_handler(invalid_parameter_handler);
- /* Disable annoying assertion message box. */
- _CrtSetReportMode(_CRT_ASSERT, 0);
-#endif
-
- /*
- * Name of this program, used to build root of our temp directory
- * tree.
- */
- progname = p = argv[0];
- if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(testprogdir, progname);
- while (*p != '\0') {
- /* Support \ or / dir separators for Windows compat. */
- if (*p == '/' || *p == '\\')
- {
- progname = p + 1;
- i = j;
- }
- ++p;
- j++;
- }
- testprogdir[i] = '\0';
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (testprogdir[0] != '/' && testprogdir[0] != '\\' &&
- !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') ||
- (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) &&
- testprogdir[1] == ':' &&
- (testprogdir[2] == '/' || testprogdir[2] == '\\')))
-#else
- if (testprogdir[0] != '/')
-#endif
- {
- /* Fixup path for relative directories. */
- if ((testprogdir = (char *)realloc(testprogdir,
- strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir) + 1);
- memcpy(testprogdir, pwd, strlen(pwd));
- testprogdir[strlen(pwd)] = '/';
- }
-
-#ifdef PROGRAM
- /* Get the target program from environment, if available. */
- testprogfile = getenv(ENVBASE);
-#endif
-
- if (getenv("TMPDIR") != NULL)
- tmp = getenv("TMPDIR");
- else if (getenv("TMP") != NULL)
- tmp = getenv("TMP");
- else if (getenv("TEMP") != NULL)
- tmp = getenv("TEMP");
- else if (getenv("TEMPDIR") != NULL)
- tmp = getenv("TEMPDIR");
- else
- tmp = "/tmp";
-
- /* Allow -d to be controlled through the environment. */
- if (getenv(ENVBASE "_DEBUG") != NULL)
- dump_on_failure = 1;
-
- /* Allow -v to be controlled through the environment. */
- if (getenv("_VERBOSITY_LEVEL") != NULL)
- {
- vlevel = getenv("_VERBOSITY_LEVEL");
- verbosity = atoi(vlevel);
- if (verbosity < VERBOSITY_SUMMARY_ONLY || verbosity > VERBOSITY_FULL)
- {
- /* Unsupported verbosity levels are silently ignored */
- vlevel = NULL;
- verbosity = VERBOSITY_PASSFAIL;
- }
- }
-
- /* Get the directory holding test files from environment. */
- refdir = getenv(ENVBASE "_TEST_FILES");
-
- /*
- * Parse options, without using getopt(), which isn't available
- * on all platforms.
- */
- ++argv; /* Skip program name */
- while (*argv != NULL) {
- if (**argv != '-')
- break;
- p = *argv++;
- ++p; /* Skip '-' */
- while (*p != '\0') {
- option = *p++;
- option_arg = NULL;
- /* If 'opt' takes an argument, parse that. */
- if (option == 'p' || option == 'r') {
- if (*p != '\0')
- option_arg = p;
- else if (*argv == NULL) {
- fprintf(stderr,
- "Option -%c requires argument.\n",
- option);
- usage(progname);
- } else
- option_arg = *argv++;
- p = ""; /* End of this option word. */
- }
-
- /* Now, handle the option. */
- switch (option) {
- case 'd':
- dump_on_failure = 1;
- break;
- case 'k':
- keep_temp_files = 1;
- break;
- case 'p':
-#ifdef PROGRAM
- testprogfile = option_arg;
-#else
- fprintf(stderr, "-p option not permitted\n");
- usage(progname);
-#endif
- break;
- case 'q':
- if (!vlevel)
- verbosity--;
- break;
- case 'r':
- refdir = option_arg;
- break;
- case 'u':
- until_failure++;
- break;
- case 'v':
- if (!vlevel)
- verbosity++;
- break;
- default:
- fprintf(stderr, "Unrecognized option '%c'\n",
- option);
- usage(progname);
- }
- }
- }
-
- /*
- * Sanity-check that our options make sense.
- */
-#ifdef PROGRAM
- if (testprogfile == NULL)
- {
- if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 +
- strlen(PROGRAM) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(tmp2, testprogdir);
- strcat(tmp2, "/");
- strcat(tmp2, PROGRAM);
- testprogfile = tmp2;
- }
-
- {
- char *testprg;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Command.com sometimes rejects '/' separators. */
- testprg = strdup(testprogfile);
- for (i = 0; testprg[i] != '\0'; i++) {
- if (testprg[i] == '/')
- testprg[i] = '\\';
- }
- testprogfile = testprg;
-#endif
- /* Quote the name that gets put into shell command lines. */
- testprg = malloc(strlen(testprogfile) + 3);
- strcpy(testprg, "\"");
- strcat(testprg, testprogfile);
- strcat(testprg, "\"");
- testprog = testprg;
- }
-#endif
-
-#if !defined(_WIN32) && defined(SIGPIPE)
- { /* Ignore SIGPIPE signals */
- struct sigaction sa;
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(SIGPIPE, &sa, NULL);
- }
-#endif
-
- /*
- * Create a temp directory for the following tests.
- * Include the time the tests started as part of the name,
- * to make it easier to track the results of multiple tests.
- */
- now = time(NULL);
- for (i = 0; ; i++) {
- strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp),
- "%Y-%m-%dT%H.%M.%S",
- localtime(&now));
- sprintf(tmpdir, "%s/%s.%s-%03d", tmp, progname,
- tmpdir_timestamp, i);
- if (assertMakeDir(tmpdir,0755))
- break;
- if (i >= 999) {
- fprintf(stderr,
- "ERROR: Unable to create temp directory %s\n",
- tmpdir);
- exit(1);
- }
- }
-
- /*
- * If the user didn't specify a directory for locating
- * reference files, try to find the reference files in
- * the "usual places."
- */
- refdir = refdir_alloc = get_refdir(refdir);
-
- /*
- * Banner with basic information.
- */
- printf("\n");
- printf("If tests fail or crash, details will be in:\n");
- printf(" %s\n", tmpdir);
- printf("\n");
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("Reference files will be read from: %s\n", refdir);
-#ifdef PROGRAM
- printf("Running tests on: %s\n", testprog);
-#endif
- printf("Exercising: ");
- fflush(stdout);
- printf("%s\n", EXTRA_VERSION);
- } else {
- printf("Running ");
- fflush(stdout);
- }
-
- /*
- * Run some or all of the individual tests.
- */
- saved_argv = argv;
- do {
- argv = saved_argv;
- do {
- int test_num;
-
- test_num = get_test_set(test_set, limit, *argv, tests);
- if (test_num < 0) {
- printf("*** INVALID Test %s\n", *argv);
- free(refdir_alloc);
- free(testprogdir);
- usage(progname);
- return (1);
- }
- for (i = 0; i < test_num; i++) {
- tests_run++;
- if (test_run(test_set[i], tmpdir)) {
- tests_failed++;
- if (until_failure)
- goto finish;
- }
- }
- if (*argv != NULL)
- argv++;
- } while (*argv != NULL);
- } while (until_failure);
-
-finish:
- /* Must be freed after all tests run */
- free(tmp2);
- free(testprogdir);
- free(pwd);
-
- /*
- * Report summary statistics.
- */
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("\n");
- printf("Totals:\n");
- printf(" Tests run: %8d\n", tests_run);
- printf(" Tests failed: %8d\n", tests_failed);
- printf(" Assertions checked:%8d\n", assertions);
- printf(" Assertions failed: %8d\n", failures);
- printf(" Skips reported: %8d\n", skips);
- }
- if (failures) {
- printf("\n");
- printf("Failing tests:\n");
- for (i = 0; i < limit; ++i) {
- if (tests[i].failures)
- printf(" %d: %s (%d failures)\n", i,
- tests[i].name, tests[i].failures);
- }
- printf("\n");
- printf("Details for failing tests: %s\n", tmpdir);
- printf("\n");
- } else {
- if (verbosity == VERBOSITY_SUMMARY_ONLY)
- printf("\n");
- printf("%d tests passed, no failures\n", tests_run);
- }
-
- free(refdir_alloc);
-
- /* If the final tmpdir is empty, we can remove it. */
- /* This should be the usual case when all tests succeed. */
- assertChdir("..");
- rmdir(tmpdir);
-
- return (tests_failed ? 1 : 0);
-}
diff --git a/cat/test/test.h b/cat/test/test.h
index c002a2c27eee..350bcad63464 100644
--- a/cat/test/test.h
+++ b/cat/test/test.h
@@ -27,328 +27,14 @@
/* Every test program should #include "test.h" as the first thing. */
-/*
- * The goal of this file (and the matching test.c) is to
- * simplify the very repetitive test-*.c test programs.
- */
-#if defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "config.h"
-#elif defined(__FreeBSD__)
-/* Building as part of FreeBSD system requires a pre-built config.h. */
-#include "config_freebsd.h"
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-/* Win32 can't run the 'configure' script. */
-#include "config_windows.h"
-#else
-/* Warn if the library hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no pre-built configuration in test.h.
-#endif
-
-#include <sys/types.h> /* Windows requires this before sys/stat.h */
-#include <sys/stat.h>
-
-#if HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#define dirent direct
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <wchar.h>
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-/*
- * System-specific tweaks. We really want to minimize these
- * as much as possible, since they make it harder to understand
- * the mainline code.
- */
-
-/* Windows (including Visual Studio and MinGW but not Cygwin) */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(__BORLANDC__)
-#undef chdir
-#define chdir _chdir
-#define strdup _strdup
-#endif
-#endif
-
-/* Visual Studio */
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf sprintf_s
-#endif
-
-#if defined(__BORLANDC__)
-#pragma warn -8068 /* Constant out of range in comparison. */
-#endif
-
-/* Haiku OS and QNX */
-#if defined(__HAIKU__) || defined(__QNXNTO__)
-/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
-#include <stdint.h>
-#endif
-
-/* Get a real definition for __FBSDID if we can */
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-/* If not, define it so as to avoid dangling semicolons. */
-#ifndef __FBSDID
-#define __FBSDID(a) struct _undefined_hack
-#endif
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/*
- * Redefine DEFINE_TEST for use in defining the test functions.
- */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void); void name(void)
-
-/* An implementation of the standard assert() macro */
-#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
-/* chdir() and error if it fails */
-#define assertChdir(path) \
- assertion_chdir(__FILE__, __LINE__, path)
-/* 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)
-/* Assert two strings are the same. Reports value of each one if not. */
-#define assertEqualString(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
-#define assertEqualUTF8String(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
-/* As above, but v1 and v2 are wchar_t * */
-#define assertEqualWString(v1,v2) \
- assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-/* As above, but raw blocks of bytes. */
-#define assertEqualMem(v1, v2, l) \
- assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
-/* Assert that memory is full of a specified byte */
-#define assertMemoryFilledWith(v1, l, b) \
- assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
-/* Assert two files are the same. */
-#define assertEqualFile(f1, f2) \
- assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
-/* Assert that a file is empty. */
-#define assertEmptyFile(pathname) \
- assertion_empty_file(__FILE__, __LINE__, (pathname))
-/* Assert that a file is not empty. */
-#define assertNonEmptyFile(pathname) \
- assertion_non_empty_file(__FILE__, __LINE__, (pathname))
-#define assertFileAtime(pathname, sec, nsec) \
- assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileAtimeRecent(pathname) \
- assertion_file_atime_recent(__FILE__, __LINE__, pathname)
-#define assertFileBirthtime(pathname, sec, nsec) \
- assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileBirthtimeRecent(pathname) \
- assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
-/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileExists(pathname) \
- assertion_file_exists(__FILE__, __LINE__, pathname)
-/* Assert that a file exists. */
-#define assertFileNotExists(pathname) \
- assertion_file_not_exists(__FILE__, __LINE__, pathname)
-/* Assert that file contents match a string. */
-#define assertFileContents(data, data_size, pathname) \
- assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
-/* Verify that a file does not contain invalid strings */
-#define assertFileContainsNoInvalidStrings(pathname, strings) \
- assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
-#define assertFileMtime(pathname, sec, nsec) \
- assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileMtimeRecent(pathname) \
- assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
-#define assertFileNLinks(pathname, nlinks) \
- assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
-#define assertFileSize(pathname, size) \
- assertion_file_size(__FILE__, __LINE__, pathname, size)
-#define assertFileMode(pathname, mode) \
- assertion_file_mode(__FILE__, __LINE__, pathname, mode)
-#define assertTextFileContents(text, pathname) \
- assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
-#define assertFileContainsLinesAnyOrder(pathname, lines) \
- assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
-#define assertIsDir(pathname, mode) \
- assertion_is_dir(__FILE__, __LINE__, pathname, mode)
-#define assertIsHardlink(path1, path2) \
- assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsNotHardlink(path1, path2) \
- assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsReg(pathname, mode) \
- assertion_is_reg(__FILE__, __LINE__, pathname, mode)
-#define assertIsSymlink(pathname, contents) \
- assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
-/* Create a directory, report error if it fails. */
-#define assertMakeDir(dirname, mode) \
- assertion_make_dir(__FILE__, __LINE__, dirname, mode)
-#define assertMakeFile(path, mode, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents)
-#define assertMakeBinFile(path, mode, csize, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents)
-#define assertMakeHardlink(newfile, oldfile) \
- 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 assertUmask(mask) \
- assertion_umask(__FILE__, __LINE__, mask)
-#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
- assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
-
-/*
- * This would be simple with C99 variadic macros, but I don't want to
- * require that. Instead, I insert a function call before each
- * skipping() call to pass the file and line information down. Crude,
- * but effective.
- */
-#define skipping \
- skipping_setup(__FILE__, __LINE__);test_skipping
-
-/* Function declarations. These are defined in test_utility.c. */
-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_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 *);
-int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
-int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
-int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
-int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
-int assertion_file_atime(const char *, int, const char *, long, long);
-int assertion_file_atime_recent(const char *, int, const char *);
-int assertion_file_birthtime(const char *, int, const char *, long, long);
-int assertion_file_birthtime_recent(const char *, int, const char *);
-int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
-int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
-int assertion_file_contents(const char *, int, const void *, int, const char *);
-int assertion_file_exists(const char *, int, const char *);
-int assertion_file_mode(const char *, int, const char *, int);
-int assertion_file_mtime(const char *, int, const char *, long, long);
-int assertion_file_mtime_recent(const char *, int, const char *);
-int assertion_file_nlinks(const char *, int, const char *, int);
-int assertion_file_not_exists(const char *, int, const char *);
-int assertion_file_size(const char *, int, const char *, long);
-int assertion_is_dir(const char *, int, const char *, int);
-int assertion_is_hardlink(const char *, int, const char *, const char *);
-int assertion_is_not_hardlink(const char *, int, const char *, const char *);
-int assertion_is_reg(const char *, int, const char *, int);
-int assertion_is_symlink(const char *, int, const char *, const char *);
-int assertion_make_dir(const char *, int, const char *, int);
-int assertion_make_file(const char *, int, const char *, int, int, const void *);
-int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
-int assertion_make_symlink(const char *, int, const char *newpath, const char *);
-int assertion_nodump(const char *, int, const char *);
-int assertion_non_empty_file(const char *, int, const char *);
-int assertion_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 );
-
-void skipping_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
-
-/* Like sprintf, then system() */
-int systemf(const char * fmt, ...);
-
-/* Delay until time() returns a value after this. */
-void sleepUntilAfter(time_t);
-
-/* Return true if this platform can create symlinks. */
-int canSymlink(void);
-
-/* Return true if this platform can run the "bzip2" program. */
-int canBzip2(void);
-
-/* Return true if this platform can run the "grzip" program. */
-int canGrzip(void);
-
-/* Return true if this platform can run the "gzip" program. */
-int canGzip(void);
-
-/* Return true if this platform can run the specified command. */
-int canRunCommand(const char *);
-
-/* Return true if this platform can run the "lrzip" program. */
-int canLrzip(void);
-
-/* Return true if this platform can run the "lz4" program. */
-int canLz4(void);
-
-/* Return true if this platform can run the "lzip" program. */
-int canLzip(void);
-
-/* Return true if this platform can run the "lzma" program. */
-int canLzma(void);
-
-/* Return true if this platform can run the "lzop" program. */
-int canLzop(void);
-
-/* Return true if this platform can run the "xz" program. */
-int canXz(void);
-
-/* Return true if this filesystem can handle nodump flags. */
-int canNodump(void);
-
-/* Return true if the file has large i-node number(>0xffffffff). */
-int is_LargeInode(const char *);
-
-/* 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, ...);
-
-/* Dump block of bytes to a file. */
-void dumpfile(const char *filename, void *, size_t);
-
-/* Extracts named reference file to the current directory. */
-void extract_reference_file(const char *);
-/* Copies named reference file to the current directory. */
-void copy_reference_file(const char *);
-
-/* Extracts a list of files to the current directory.
- * List must be NULL terminated.
- */
-void extract_reference_files(const char **);
-
-/* Subtract umask from mode */
-mode_t umasked(mode_t expected_mode);
-
-/* Path to working directory for current test */
-extern const char *testworkdir;
-
-/*
- * Special interfaces for program test harness.
- */
-
-/* Pathname of exe to be tested. */
-extern const char *testprogfile;
-/* Name of exe to use in printf-formatted command strings. */
-/* On Windows, this includes leading/trailing quotes. */
-extern const char *testprog;
-
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
+#define KNOWNREF "test_expand.Z.uu"
+#define ENVBASE "BSDCAT" /* Prefix for environment variables. */
+#define PROGRAM "bsdcat" /* Name of program being tested. */
+#define PROGRAM_ALIAS "cat" /* Generic alias for program */
+#undef LIBRARY /* Not testing a library. */
+#undef EXTRA_DUMP /* How to dump extra data */
+#undef EXTRA_ERRNO /* How to dump errno */
+/* How to generate extra version info. */
+#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
+
+#include "test_common.h"
diff --git a/cat/test/test_version.c b/cat/test/test_version.c
index e587b3440c6d..51a4fd4d9a01 100644
--- a/cat/test/test_version.c
+++ b/cat/test/test_version.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2017 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,68 +30,5 @@
DEFINE_TEST(test_version)
{
- int r;
- char *p, *q;
- size_t s;
-
-
- r = systemf("%s --version >version.stdout 2>version.stderr", testprog);
- failure("Unable to run %s --version", testprog);
- if (!assert(r == 0))
- return;
-
- /* --version should generate nothing to stdout. */
- assertEmptyFile("version.stderr");
- /* Verify format of version message. */
- q = p = slurpfile(&s, "version.stdout");
- /* Version message should start with name of program, then space. */
- assert(s > 6);
- failure("Version must start with 'bsdcat': ``%s''", p);
- if (!assertEqualMem(q, "bsdcat ", 7))
- return;
- q += 7; s -= 7;
- /* Version number is a series of digits and periods. */
- while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
- ++q;
- --s;
- }
- /* Version number terminated by space. */
- failure("No space after bsdcat version: ``%s''", p);
- assert(s > 1);
- /* Skip a single trailing a,b,c, or d. */
- if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
- ++q;
- failure("No space after bsdcat version: ``%s''", p);
- assert(*q == ' ');
- ++q; --s;
- /* Separator. */
- failure("No `-' between bsdcat and libarchive versions: ``%s''", p);
- assertEqualMem(q, "- ", 2);
- q += 2; s -= 2;
- /* libarchive name and version number */
- failure("Not long enough for libarchive version: ``%s''", p);
- assert(s > 11);
- failure("Libarchive version must start with `libarchive': ``%s''", p);
- assertEqualMem(q, "libarchive ", 11);
- q += 11; s -= 11;
- /* Version number is a series of digits and periods. */
- while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
- ++q;
- --s;
- }
- /* Skip a single trailing a,b,c, or d. */
- if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
- ++q;
- /* Skip arbitrary third-party version numbers. */
- while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || isalnum(*q))) {
- ++q;
- --s;
- }
- /* All terminated by end-of-line. */
- assert(s >= 1);
- /* Skip an optional CR character (e.g., Windows) */
- failure("Version output must end with \\n or \\r\\n");
- if (*q == '\r') { ++q; --s; }
- assertEqualMem(q, "\n", 1);
- free(p);
+ assertVersion(testprog, "bsdcat");
}
diff --git a/configure.ac b/configure.ac
index f3b8fda40d4d..3a8ac6a853b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
dnl In particular, this allows the version macro to be used in AC_INIT
dnl These first two version numbers are updated automatically on each release.
-m4_define([LIBARCHIVE_VERSION_S],[3.2.2])
-m4_define([LIBARCHIVE_VERSION_N],[3002002])
+m4_define([LIBARCHIVE_VERSION_S],[3.3.1])
+m4_define([LIBARCHIVE_VERSION_N],[3003001])
dnl bsdtar and bsdcpio versioning tracks libarchive
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
@@ -270,6 +270,19 @@ AS_VAR_IF([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes],
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 @@ fi
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
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
index 8ffb54276967..ec9509be98fa 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -8,7 +8,7 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
../cmdline.c
../../libarchive_fe/err.c
../../test_utils/test_utils.c
- main.c
+ ../../test_utils/test_main.c
test.h
test_0.c
test_basic.c
@@ -87,6 +87,7 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
+ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cpio/test)
# Experimental new test handling
ADD_CUSTOM_TARGET(run_bsdcpio_test
diff --git a/cpio/test/main.c b/cpio/test/main.c
deleted file mode 100644
index 34282f3f8dc5..000000000000
--- a/cpio/test/main.c
+++ /dev/null
@@ -1,3073 +0,0 @@
-/*
- * Copyright (c) 2003-2009 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 "test.h"
-#include "test_utils.h"
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_ICONV_H
-#include <iconv.h>
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h> /* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
-#endif
-#include <limits.h>
-#include <locale.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <stdarg.h>
-#include <time.h>
-
-/*
- * This same file is used pretty much verbatim for all test harnesses.
- *
- * The next few lines are the only differences.
- * TODO: Move this into a separate configuration header, have all test
- * suites share one copy of this file.
- */
-__FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kientzle Exp $");
-#define KNOWNREF "test_option_f.cpio.uu"
-#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */
-#define PROGRAM "bsdcpio" /* Name of program being tested. */
-#define PROGRAM_ALIAS "cpio" /* Generic alias for program */
-#undef LIBRARY /* Not testing a library. */
-#undef EXTRA_DUMP /* How to dump extra data */
-#undef EXTRA_ERRNO /* How to dump errno */
-/* How to generate extra version info. */
-#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
-
-/*
- *
- * Windows support routines
- *
- * Note: Configuration is a tricky issue. Using HAVE_* feature macros
- * in the test harness is dangerous because they cover up
- * configuration errors. The classic example of this is omitting a
- * configure check. If libarchive and libarchive_test both look for
- * the same feature macro, such errors are hard to detect. Platform
- * macros (e.g., _WIN32 or __GNUC__) are a little better, but can
- * easily lead to very messy code. It's best to limit yourself
- * to only the most generic programming techniques in the test harness
- * and thus avoid conditionals altogether. Where that's not possible,
- * try to minimize conditionals by grouping platform-specific tests in
- * one place (e.g., test_acl_freebsd) or by adding new assert()
- * functions (e.g., assertMakeHardlink()) to cover up platform
- * differences. Platform-specific coding in libarchive_test is often
- * a symptom that some capability is missing from libarchive itself.
- */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
-#include <direct.h>
-#include <windows.h>
-#ifndef F_OK
-#define F_OK (0)
-#endif
-#ifndef S_ISDIR
-#define S_ISDIR(m) ((m) & _S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(m) ((m) & _S_IFREG)
-#endif
-#if !defined(__BORLANDC__)
-#define access _access
-#undef chdir
-#define chdir _chdir
-#endif
-#ifndef fileno
-#define fileno _fileno
-#endif
-/*#define fstat _fstat64*/
-#if !defined(__BORLANDC__)
-#define getcwd _getcwd
-#endif
-#define lstat stat
-/*#define lstat _stat64*/
-/*#define stat _stat64*/
-#define rmdir _rmdir
-#if !defined(__BORLANDC__)
-#define strdup _strdup
-#define umask _umask
-#endif
-#define int64_t __int64
-#endif
-
-#if defined(HAVE__CrtSetReportMode)
-# include <crtdbg.h>
-#endif
-
-mode_t umasked(mode_t expected_mode)
-{
- mode_t mode = umask(0);
- umask(mode);
- return expected_mode & ~mode;
-}
-
-/* Path to working directory for current test */
-const char *testworkdir;
-#ifdef PROGRAM
-/* Pathname of exe to be tested. */
-const char *testprogfile;
-/* Name of exe to use in printf-formatted command strings. */
-/* On Windows, this includes leading/trailing quotes. */
-const char *testprog;
-#endif
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static void *GetFunctionKernel32(const char *);
-static int my_CreateSymbolicLinkA(const char *, const char *, int);
-static int my_CreateHardLinkA(const char *, const char *);
-static int my_GetFileInformationByName(const char *,
- BY_HANDLE_FILE_INFORMATION *);
-
-static void *
-GetFunctionKernel32(const char *name)
-{
- static HINSTANCE lib;
- static int set;
- if (!set) {
- set = 1;
- lib = LoadLibrary("kernel32.dll");
- }
- if (lib == NULL) {
- fprintf(stderr, "Can't load kernel32.dll?!\n");
- exit(1);
- }
- return (void *)GetProcAddress(lib, name);
-}
-
-static int
-my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateSymbolicLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, flags);
-}
-
-static int
-my_CreateHardLinkA(const char *linkname, const char *target)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateHardLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, NULL);
-}
-
-static int
-my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
-{
- HANDLE h;
- int r;
-
- memset(bhfi, 0, sizeof(*bhfi));
- h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE)
- return (0);
- r = GetFileInformationByHandle(h, bhfi);
- CloseHandle(h);
- return (r);
-}
-#endif
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
-static void
-invalid_parameter_handler(const wchar_t * expression,
- const wchar_t * function, const wchar_t * file,
- unsigned int line, uintptr_t pReserved)
-{
- /* nop */
-}
-#endif
-
-/*
- *
- * OPTIONS FLAGS
- *
- */
-
-/* Enable core dump on failure. */
-static int dump_on_failure = 0;
-/* Default is to remove temp dirs and log data for successful tests. */
-static int keep_temp_files = 0;
-/* Default is to run the specified tests once and report errors. */
-static int until_failure = 0;
-/* Default is to just report pass/fail for each test. */
-static int verbosity = 0;
-#define VERBOSITY_SUMMARY_ONLY -1 /* -q */
-#define VERBOSITY_PASSFAIL 0 /* Default */
-#define VERBOSITY_LIGHT_REPORT 1 /* -v */
-#define VERBOSITY_FULL 2 /* -vv */
-/* A few places generate even more output for verbosity > VERBOSITY_FULL,
- * mostly for debugging the test harness itself. */
-/* Cumulative count of assertion failures. */
-static int failures = 0;
-/* Cumulative count of reported skips. */
-static int skips = 0;
-/* Cumulative count of assertions checked. */
-static int assertions = 0;
-
-/* Directory where uuencoded reference files can be found. */
-static const char *refdir;
-
-/*
- * Report log information selectively to console and/or disk log.
- */
-static int log_console = 0;
-static FILE *logfile;
-static void
-vlogprintf(const char *fmt, va_list ap)
-{
-#ifdef va_copy
- va_list lfap;
- va_copy(lfap, ap);
-#endif
- if (log_console)
- vfprintf(stdout, fmt, ap);
- if (logfile != NULL)
-#ifdef va_copy
- vfprintf(logfile, fmt, lfap);
- va_end(lfap);
-#else
- vfprintf(logfile, fmt, ap);
-#endif
-}
-
-static void
-logprintf(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogprintf(fmt, ap);
- va_end(ap);
-}
-
-/* Set up a message to display only if next assertion fails. */
-static char msgbuff[4096];
-static const char *msg, *nextmsg;
-void
-failure(const char *fmt, ...)
-{
- va_list ap;
- if (fmt == NULL) {
- nextmsg = NULL;
- } else {
- va_start(ap, fmt);
- vsprintf(msgbuff, fmt, ap);
- va_end(ap);
- nextmsg = msgbuff;
- }
-}
-
-/*
- * Copy arguments into file-local variables.
- * This was added to permit vararg assert() functions without needing
- * variadic wrapper macros. Turns out that the vararg capability is almost
- * never used, so almost all of the vararg assertions can be simplified
- * by removing the vararg capability and reworking the wrapper macro to
- * pass __FILE__, __LINE__ directly into the function instead of using
- * this hook. I suspect this machinery is used so rarely that we
- * would be better off just removing it entirely. That would simplify
- * the code here noticeably.
- */
-static const char *skipping_filename;
-static int skipping_line;
-void skipping_setup(const char *filename, int line)
-{
- skipping_filename = filename;
- skipping_line = line;
-}
-
-/* Called at the beginning of each assert() function. */
-static void
-assertion_count(const char *file, int line)
-{
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- ++assertions;
- /* Proper handling of "failure()" message. */
- msg = nextmsg;
- nextmsg = NULL;
- /* Uncomment to print file:line after every assertion.
- * Verbose, but occasionally useful in tracking down crashes. */
- /* printf("Checked %s:%d\n", file, line); */
-}
-
-/*
- * For each test source file, we remember how many times each
- * assertion was reported. Cleared before each new test,
- * used by test_summarize().
- */
-static struct line {
- int count;
- int skip;
-} failed_lines[10000];
-const char *failed_filename;
-
-/* Count this failure, setup up log destination and handle initial report. */
-static void
-failure_start(const char *filename, int line, const char *fmt, ...)
-{
- va_list ap;
-
- /* Record another failure for this line. */
- ++failures;
- failed_filename = filename;
- failed_lines[line].count++;
-
- /* Determine whether to log header to console. */
- switch (verbosity) {
- case VERBOSITY_LIGHT_REPORT:
- log_console = (failed_lines[line].count < 2);
- break;
- default:
- log_console = (verbosity >= VERBOSITY_FULL);
- }
-
- /* Log file:line header for this failure */
- va_start(ap, fmt);
-#if _MSC_VER
- logprintf("%s(%d): ", filename, line);
-#else
- logprintf("%s:%d: ", filename, line);
-#endif
- vlogprintf(fmt, ap);
- va_end(ap);
- logprintf("\n");
-
- if (msg != NULL && msg[0] != '\0') {
- logprintf(" Description: %s\n", msg);
- msg = NULL;
- }
-
- /* Determine whether to log details to console. */
- if (verbosity == VERBOSITY_LIGHT_REPORT)
- log_console = 0;
-}
-
-/* Complete reporting of failed tests. */
-/*
- * The 'extra' hook here is used by libarchive to include libarchive
- * error messages with assertion failures. It could also be used
- * to add strerror() output, for example. Just define the EXTRA_DUMP()
- * macro appropriately.
- */
-static void
-failure_finish(void *extra)
-{
- (void)extra; /* UNUSED (maybe) */
-#ifdef EXTRA_DUMP
- if (extra != NULL) {
- logprintf(" errno: %d\n", EXTRA_ERRNO(extra));
- logprintf(" detail: %s\n", EXTRA_DUMP(extra));
- }
-#endif
-
- if (dump_on_failure) {
- fprintf(stderr,
- " *** forcing core dump so failure can be debugged ***\n");
- abort();
- }
-}
-
-/* Inform user that we're skipping some checks. */
-void
-test_skipping(const char *fmt, ...)
-{
- char buff[1024];
- va_list ap;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- va_end(ap);
- /* Use failure() message if set. */
- msg = nextmsg;
- nextmsg = NULL;
- /* failure_start() isn't quite right, but is awfully convenient. */
- failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff);
- --failures; /* Undo failures++ in failure_start() */
- /* Don't failure_finish() here. */
- /* Mark as skip, so doesn't count as failed test. */
- failed_lines[skipping_line].skip = 1;
- ++skips;
-}
-
-/*
- *
- * ASSERTIONS
- *
- */
-
-/* Generic assert() just displays the failed condition. */
-int
-assertion_assert(const char *file, int line, int value,
- const char *condition, void *extra)
-{
- assertion_count(file, line);
- if (!value) {
- failure_start(file, line, "Assertion failed: %s", condition);
- failure_finish(extra);
- }
- return (value);
-}
-
-/* chdir() and report any errors */
-int
-assertion_chdir(const char *file, int line, const char *pathname)
-{
- assertion_count(file, line);
- if (chdir(pathname) == 0)
- return (1);
- failure_start(file, line, "chdir(\"%s\")", pathname);
- failure_finish(NULL);
- return (0);
-
-}
-
-/* Verify two integers are equal. */
-int
-assertion_equal_int(const char *file, int line,
- long long v1, const char *e1, long long v2, const char *e2, void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Utility to convert a single UTF-8 sequence.
- */
-static int
-_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
- static const char utf8_count[256] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */
- 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */
- 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
- };
- int ch;
- int cnt;
- uint32_t wc;
-
- *pwc = 0;
-
- /* Sanity check. */
- if (n == 0)
- return (0);
- /*
- * Decode 1-4 bytes depending on the value of the first byte.
- */
- ch = (unsigned char)*s;
- if (ch == 0)
- return (0); /* Standard: return 0 for end-of-string. */
- cnt = utf8_count[ch];
-
- /* Invalid sequence or there are not plenty bytes. */
- if (n < (size_t)cnt)
- return (-1);
-
- /* Make a Unicode code point from a single UTF-8 sequence. */
- switch (cnt) {
- case 1: /* 1 byte sequence. */
- *pwc = ch & 0x7f;
- return (cnt);
- case 2: /* 2 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
- return (cnt);
- case 3: /* 3 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x0f) << 12)
- | ((s[1] & 0x3f) << 6)
- | (s[2] & 0x3f);
- if (wc < 0x800)
- return (-1);/* Overlong sequence. */
- break;
- case 4: /* 4 bytes sequence. */
- if (n < 4)
- return (-1);
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- if ((s[3] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x07) << 18)
- | ((s[1] & 0x3f) << 12)
- | ((s[2] & 0x3f) << 6)
- | (s[3] & 0x3f);
- if (wc < 0x10000)
- return (-1);/* Overlong sequence. */
- break;
- default:
- return (-1);
- }
-
- /* The code point larger than 0x10FFFF is not legal
- * Unicode values. */
- if (wc > 0x10FFFF)
- return (-1);
- /* Correctly gets a Unicode, returns used bytes. */
- *pwc = wc;
- return (cnt);
-}
-
-static void strdump(const char *e, const char *p, int ewidth, int utf8)
-{
- const char *q = p;
-
- logprintf(" %*s = ", ewidth, e);
- if (p == NULL) {
- logprintf("NULL\n");
- return;
- }
- logprintf("\"");
- while (*p != '\0') {
- unsigned int c = 0xff & *p++;
- switch (c) {
- case '\a': logprintf("\\a"); break;
- case '\b': logprintf("\\b"); break;
- case '\n': logprintf("\\n"); break;
- case '\r': logprintf("\\r"); break;
- default:
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else
- logprintf("\\x%02X", c);
- }
- }
- logprintf("\"");
- logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q));
-
- /*
- * If the current string is UTF-8, dump its code points.
- */
- if (utf8) {
- size_t len;
- uint32_t uc;
- int n;
- int cnt = 0;
-
- p = q;
- len = strlen(p);
- logprintf(" [");
- while ((n = _utf8_to_unicode(&uc, p, len)) > 0) {
- if (p != q)
- logprintf(" ");
- logprintf("%04X", uc);
- p += n;
- len -= n;
- cnt++;
- }
- logprintf("]");
- logprintf(" (count %d", cnt);
- if (n < 0) {
- logprintf(",unknown %d bytes", len);
- }
- logprintf(")");
-
- }
- logprintf("\n");
-}
-
-/* Verify two strings are equal, dump them if not. */
-int
-assertion_equal_string(const char *file, int line,
- const char *v1, const char *e1,
- const char *v2, const char *e2,
- void *extra, int utf8)
-{
- int l1, l2;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- l1 = (int)strlen(e1);
- l2 = (int)strlen(e2);
- if (l1 < l2)
- l1 = l2;
- strdump(e1, v1, l1, utf8);
- strdump(e2, v2, l1, utf8);
- failure_finish(extra);
- return (0);
-}
-
-static void
-wcsdump(const char *e, const wchar_t *w)
-{
- logprintf(" %s = ", e);
- if (w == NULL) {
- logprintf("(null)");
- return;
- }
- logprintf("\"");
- while (*w != L'\0') {
- unsigned int c = *w++;
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else if (c < 256)
- logprintf("\\x%02X", c);
- else if (c < 0x10000)
- logprintf("\\u%04X", c);
- else
- logprintf("\\U%08X", c);
- }
- logprintf("\"\n");
-}
-
-#ifndef HAVE_WCSCMP
-static int
-wcscmp(const wchar_t *s1, const wchar_t *s2)
-{
-
- while (*s1 == *s2++) {
- if (*s1++ == L'\0')
- return 0;
- }
- if (*s1 > *--s2)
- return 1;
- else
- return -1;
-}
-#endif
-
-/* Verify that two wide strings are equal, dump them if not. */
-int
-assertion_equal_wstring(const char *file, int line,
- const wchar_t *v1, const char *e1,
- const wchar_t *v2, const char *e2,
- void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- wcsdump(e1, v1);
- wcsdump(e2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Pretty standard hexdump routine. As a bonus, if ref != NULL, then
- * any bytes in p that differ from ref will be highlighted with '_'
- * before and after the hex value.
- */
-static void
-hexdump(const char *p, const char *ref, size_t l, size_t offset)
-{
- size_t i, j;
- char sep;
-
- if (p == NULL) {
- logprintf("(null)\n");
- return;
- }
- for(i=0; i < l; i+=16) {
- logprintf("%04x", (unsigned)(i + offset));
- sep = ' ';
- for (j = 0; j < 16 && i + j < l; j++) {
- if (ref != NULL && p[i + j] != ref[i + j])
- sep = '_';
- logprintf("%c%02x", sep, 0xff & (int)p[i+j]);
- if (ref != NULL && p[i + j] == ref[i + j])
- sep = ' ';
- }
- for (; j < 16; j++) {
- logprintf("%c ", sep);
- sep = ' ';
- }
- logprintf("%c", sep);
- for (j=0; j < 16 && i + j < l; j++) {
- int c = p[i + j];
- if (c >= ' ' && c <= 126)
- logprintf("%c", c);
- else
- logprintf(".");
- }
- logprintf("\n");
- }
-}
-
-/* Verify that two blocks of memory are the same, display the first
- * block of differences if they're not. */
-int
-assertion_equal_mem(const char *file, int line,
- const void *_v1, const char *e1,
- const void *_v2, const char *e2,
- size_t l, const char *ld, void *extra)
-{
- const char *v1 = (const char *)_v1;
- const char *v2 = (const char *)_v2;
- size_t offset;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0))
- return (1);
- if (v1 == NULL || v2 == NULL)
- return (0);
-
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" size %s = %d\n", ld, (int)l);
- /* Dump 48 bytes (3 lines) so that the first difference is
- * in the second line. */
- offset = 0;
- while (l > 64 && memcmp(v1, v2, 32) == 0) {
- /* Two lines agree, so step forward one line. */
- v1 += 16;
- v2 += 16;
- l -= 16;
- offset += 16;
- }
- logprintf(" Dump of %s\n", e1);
- hexdump(v1, v2, l < 128 ? l : 128, offset);
- logprintf(" Dump of %s\n", e2);
- hexdump(v2, v1, l < 128 ? l : 128, offset);
- logprintf("\n");
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that a block of memory is filled with the specified byte. */
-int
-assertion_memory_filled_with(const char *file, int line,
- const void *_v1, const char *vd,
- size_t l, const char *ld,
- char b, const char *bd, void *extra)
-{
- const char *v1 = (const char *)_v1;
- size_t c = 0;
- size_t i;
- (void)ld; /* UNUSED */
-
- assertion_count(file, line);
-
- for (i = 0; i < l; ++i) {
- if (v1[i] == b) {
- ++c;
- }
- }
- if (c == l)
- return (1);
-
- failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
- logprintf(" Only %d bytes were correct\n", (int)c);
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that the named file exists and is empty. */
-int
-assertion_empty_file(const char *filename, int line, const char *f1)
-{
- char buff[1024];
- struct stat st;
- ssize_t s;
- FILE *f;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0)
- return (1);
-
- failure_start(filename, line, "File should be empty: %s", f1);
- logprintf(" File size: %d\n", (int)st.st_size);
- logprintf(" Contents:\n");
- f = fopen(f1, "rb");
- if (f == NULL) {
- logprintf(" Unable to open %s\n", f1);
- } else {
- s = ((off_t)sizeof(buff) < st.st_size) ?
- (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
- s = fread(buff, 1, s, f);
- hexdump(buff, NULL, s, 0);
- fclose(f);
- }
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file exists and is not empty. */
-int
-assertion_non_empty_file(const char *filename, int line, const char *f1)
-{
- struct stat st;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0) {
- failure_start(filename, line, "File empty: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify that two files have the same contents. */
-/* TODO: hexdump the first bytes that actually differ. */
-int
-assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2)
-{
- char buff1[1024];
- char buff2[1024];
- FILE *f1, *f2;
- int n1, n2;
-
- assertion_count(filename, line);
-
- f1 = fopen(fn1, "rb");
- f2 = fopen(fn2, "rb");
- if (f1 == NULL || f2 == NULL) {
- if (f1) fclose(f1);
- if (f2) fclose(f2);
- return (0);
- }
- for (;;) {
- n1 = (int)fread(buff1, 1, sizeof(buff1), f1);
- n2 = (int)fread(buff2, 1, sizeof(buff2), f2);
- if (n1 != n2)
- break;
- if (n1 == 0 && n2 == 0) {
- fclose(f1);
- fclose(f2);
- return (1);
- }
- if (memcmp(buff1, buff2, n1) != 0)
- break;
- }
- fclose(f1);
- fclose(f2);
- failure_start(filename, line, "Files not identical");
- logprintf(" file1=\"%s\"\n", fn1);
- logprintf(" file2=\"%s\"\n", fn2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file does exist. */
-int
-assertion_file_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (!_access(f, 0))
- return (1);
-#else
- if (!access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file doesn't exist. */
-int
-assertion_file_not_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (_access(f, 0))
- return (1);
-#else
- if (access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should not exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Compare the contents of a file to a block of memory. */
-int
-assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn)
-{
- char *contents;
- FILE *f;
- int n;
-
- assertion_count(filename, line);
-
- f = fopen(fn, "rb");
- if (f == NULL) {
- failure_start(filename, line,
- "File should exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- contents = malloc(s * 2);
- n = (int)fread(contents, 1, s * 2, f);
- fclose(f);
- if (n == s && memcmp(buff, contents, s) == 0) {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "File contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0)
- hexdump(contents, buff, n > 512 ? 512 : n, 0);
- else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s > 512 ? 512 : s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Check the contents of a text file, being tolerant of line endings. */
-int
-assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn)
-{
- char *contents;
- const char *btxt, *ftxt;
- FILE *f;
- int n, s;
-
- assertion_count(filename, line);
- f = fopen(fn, "r");
- if (f == NULL) {
- failure_start(filename, line,
- "File doesn't exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- s = (int)strlen(buff);
- contents = malloc(s * 2 + 128);
- n = (int)fread(contents, 1, s * 2 + 128 - 1, f);
- if (n >= 0)
- contents[n] = '\0';
- fclose(f);
- /* Compare texts. */
- btxt = buff;
- ftxt = (const char *)contents;
- while (*btxt != '\0' && *ftxt != '\0') {
- if (*btxt == *ftxt) {
- ++btxt;
- ++ftxt;
- continue;
- }
- if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') {
- /* Pass over different new line characters. */
- ++btxt;
- ftxt += 2;
- continue;
- }
- break;
- }
- if (*btxt == '\0' && *ftxt == '\0') {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "Contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0) {
- hexdump(contents, buff, n, 0);
- logprintf(" expected\n", fn);
- hexdump(buff, contents, s, 0);
- } else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Verify that a text file contains the specified lines, regardless of order */
-/* This could be more efficient if we sorted both sets of lines, etc, but
- * since this is used only for testing and only ever deals with a dozen or so
- * lines at a time, this relatively crude approach is just fine. */
-int
-assertion_file_contains_lines_any_order(const char *file, int line,
- const char *pathname, const char *lines[])
-{
- char *buff;
- size_t buff_size;
- size_t expected_count, actual_count, i, j;
- char **expected = NULL;
- char *p, **actual = NULL;
- char c;
- int expected_failure = 0, actual_failure = 0;
-
- assertion_count(file, line);
-
- buff = slurpfile(&buff_size, "%s", pathname);
- if (buff == NULL) {
- failure_start(pathname, line, "Can't read file: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- /* Make a copy of the provided lines and count up the expected
- * file size. */
- for (i = 0; lines[i] != NULL; ++i) {
- }
- expected_count = i;
- if (expected_count) {
- expected = malloc(sizeof(char *) * expected_count);
- if (expected == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- free(expected);
- return (0);
- }
- for (i = 0; lines[i] != NULL; ++i) {
- expected[i] = strdup(lines[i]);
- }
- }
-
- /* Break the file into lines */
- actual_count = 0;
- for (c = '\0', p = buff; p < buff + buff_size; ++p) {
- if (*p == '\x0d' || *p == '\x0a')
- *p = '\0';
- if (c == '\0' && *p != '\0')
- ++actual_count;
- c = *p;
- }
- if (actual_count) {
- actual = calloc(sizeof(char *), actual_count);
- if (actual == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- free(expected);
- return (0);
- }
- for (j = 0, p = buff; p < buff + buff_size;
- p += 1 + strlen(p)) {
- if (*p != '\0') {
- actual[j] = p;
- ++j;
- }
- }
- }
-
- /* Erase matching lines from both lists */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] == NULL)
- continue;
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] == NULL)
- continue;
- if (strcmp(expected[i], actual[j]) == 0) {
- free(expected[i]);
- expected[i] = NULL;
- actual[j] = NULL;
- break;
- }
- }
- }
-
- /* If there's anything left, it's a failure */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL)
- ++expected_failure;
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- ++actual_failure;
- }
- if (expected_failure == 0 && actual_failure == 0) {
- free(buff);
- free(expected);
- free(actual);
- return (1);
- }
- failure_start(file, line, "File doesn't match: %s", pathname);
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL) {
- logprintf(" Expected but not present: %s\n", expected[i]);
- free(expected[i]);
- }
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- logprintf(" Present but not expected: %s\n", actual[j]);
- }
- failure_finish(NULL);
- free(buff);
- free(expected);
- free(actual);
- return (0);
-}
-
-/* Verify that a text file does not contains the specified strings */
-int
-assertion_file_contains_no_invalid_strings(const char *file, int line,
- const char *pathname, const char *strings[])
-{
- char *buff;
- int i;
-
- buff = slurpfile(NULL, "%s", pathname);
- if (buff == NULL) {
- failure_start(file, line, "Can't read file: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- for (i = 0; strings[i] != NULL; ++i) {
- if (strstr(buff, strings[i]) != NULL) {
- failure_start(file, line, "Invalid string in %s: %s", pathname,
- strings[i]);
- failure_finish(NULL);
- free(buff);
- return(0);
- }
- }
-
- free(buff);
- return (0);
-}
-
-/* Test that two paths point to the same file. */
-/* As a side-effect, asserts that both files exist. */
-static int
-is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(path1, &bhfi1);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path1);
- failure_finish(NULL);
- return (0);
- }
- r = my_GetFileInformationByName(path2, &bhfi2);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path2);
- failure_finish(NULL);
- return (0);
- }
- return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber
- && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
- && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
-#else
- struct stat st1, st2;
- int r;
-
- assertion_count(file, line);
- r = lstat(path1, &st1);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path1);
- failure_finish(NULL);
- return (0);
- }
- r = lstat(path2, &st2);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path2);
- failure_finish(NULL);
- return (0);
- }
- return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
-#endif
-}
-
-int
-assertion_is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s are not hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-int
-assertion_is_not_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (!is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s should not be hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify a/b/mtime of 'pathname'. */
-/* If 'recent', verify that it's within last 10 seconds. */
-static int
-assertion_file_time(const char *file, int line,
- const char *pathname, long t, long nsec, char type, int recent)
-{
- long long filet, filet_nsec;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME (116444736000000000ULL)
- FILETIME fxtime, fbirthtime, fatime, fmtime;
- ULARGE_INTEGER wintm;
- HANDLE h;
- fxtime.dwLowDateTime = 0;
- fxtime.dwHighDateTime = 0;
-
- assertion_count(file, line);
- /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
- * a directory file. If not, CreateFile() will fail when
- * the pathname is a directory. */
- h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = GetFileTime(h, &fbirthtime, &fatime, &fmtime);
- switch (type) {
- case 'a': fxtime = fatime; break;
- case 'b': fxtime = fbirthtime; break;
- case 'm': fxtime = fmtime; break;
- }
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't GetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- wintm.LowPart = fxtime.dwLowDateTime;
- wintm.HighPart = fxtime.dwHighDateTime;
- filet = (wintm.QuadPart - EPOC_TIME) / 10000000;
- filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100;
- nsec = (nsec / 100) * 100; /* Round the request */
-#else
- struct stat st;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- switch (type) {
- case 'a': filet = st.st_atime; break;
- case 'm': filet = st.st_mtime; break;
- case 'b': filet = 0; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
-#if defined(__FreeBSD__)
- switch (type) {
- case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
- case 'b': filet = st.st_birthtime;
- /* FreeBSD filesystems that don't support birthtime
- * (e.g., UFS1) always return -1 here. */
- if (filet == -1) {
- return (1);
- }
- filet_nsec = st.st_birthtimespec.tv_nsec; break;
- case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
- /* FreeBSD generally only stores to microsecond res, so round. */
- filet_nsec = (filet_nsec / 1000) * 1000;
- nsec = (nsec / 1000) * 1000;
-#else
- filet_nsec = nsec = 0; /* Generic POSIX only has whole seconds. */
- if (type == 'b') return (1); /* Generic POSIX doesn't have birthtime */
-#if defined(__HAIKU__)
- if (type == 'a') return (1); /* Haiku doesn't have atime. */
-#endif
-#endif
-#endif
- if (recent) {
- /* Check that requested time is up-to-date. */
- time_t now = time(NULL);
- if (filet < now - 10 || filet > now + 1) {
- failure_start(file, line,
- "File %s has %ctime %lld, %lld seconds ago\n",
- pathname, type, filet, now - filet);
- failure_finish(NULL);
- return (0);
- }
- } else if (filet != t || filet_nsec != nsec) {
- failure_start(file, line,
- "File %s has %ctime %lld.%09lld, expected %lld.%09lld",
- pathname, type, filet, filet_nsec, t, nsec);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify atime of 'pathname'. */
-int
-assertion_file_atime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'a', 0);
-}
-
-/* Verify atime of 'pathname' is up-to-date. */
-int
-assertion_file_atime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'a', 1);
-}
-
-/* Verify birthtime of 'pathname'. */
-int
-assertion_file_birthtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'b', 0);
-}
-
-/* Verify birthtime of 'pathname' is up-to-date. */
-int
-assertion_file_birthtime_recent(const char *file, int line,
- const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'b', 1);
-}
-
-/* Verify mode of 'pathname'. */
-int
-assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode)
-{
- int mode;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- failure_start(file, line, "assertFileMode not yet implemented for Windows");
- (void)mode; /* UNUSED */
- (void)r; /* UNUSED */
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- mode = (int)(st.st_mode & 0777);
- }
- if (r == 0 && mode == expected_mode)
- return (1);
- failure_start(file, line, "File %s has mode %o, expected %o",
- pathname, mode, expected_mode);
-#endif
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify mtime of 'pathname'. */
-int
-assertion_file_mtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'm', 0);
-}
-
-/* Verify mtime of 'pathname' is up-to-date. */
-int
-assertion_file_mtime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'm', 1);
-}
-
-/* Verify number of links to 'pathname'. */
-int
-assertion_file_nlinks(const char *file, int line,
- const char *pathname, int nlinks)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(pathname, &bhfi);
- if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, bhfi.nNumberOfLinks, nlinks);
- failure_finish(NULL);
- return (0);
-#else
- struct stat st;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, st.st_nlink, nlinks);
- failure_finish(NULL);
- return (0);
-#endif
-}
-
-/* Verify size of 'pathname'. */
-int
-assertion_file_size(const char *file, int line, const char *pathname, long size)
-{
- int64_t filesize;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- {
- BY_HANDLE_FILE_INFORMATION bhfi;
- r = !my_GetFileInformationByName(pathname, &bhfi);
- filesize = ((int64_t)bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow;
- }
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- filesize = st.st_size;
- }
-#endif
- if (r == 0 && filesize == size)
- return (1);
- failure_start(file, line, "File %s has size %ld, expected %ld",
- pathname, (long)filesize, (long)size);
- failure_finish(NULL);
- return (0);
-}
-
-/* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */
-int
-assertion_is_dir(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Dir should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISDIR(st.st_mode)) {
- failure_start(file, line, "%s is not a dir", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "Dir %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Verify that 'pathname' is a regular file. If 'mode' is >= 0,
- * verify that too. */
-int
-assertion_is_reg(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0 || !S_ISREG(st.st_mode)) {
- failure_start(file, line, "File should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "File %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Check whether 'pathname' is a symbolic link. If 'contents' is
- * non-NULL, verify that the symlink has those contents. */
-static int
-is_symlink(const char *file, int line,
- const char *pathname, const char *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)pathname; /* UNUSED */
- (void)contents; /* UNUSED */
- assertion_count(file, line);
- /* Windows sort-of has real symlinks, but they're only usable
- * by privileged users and are crippled even then, so there's
- * really not much point in bothering with this. */
- return (0);
-#else
- char buff[300];
- struct stat st;
- ssize_t linklen;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line,
- "Symlink should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISLNK(st.st_mode))
- return (0);
- if (contents == NULL)
- return (1);
- linklen = readlink(pathname, buff, sizeof(buff));
- if (linklen < 0) {
- failure_start(file, line, "Can't read symlink %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- buff[linklen] = '\0';
- if (strcmp(buff, contents) != 0)
- return (0);
- return (1);
-#endif
-}
-
-/* Assert that path is a symlink that (optionally) contains contents. */
-int
-assertion_is_symlink(const char *file, int line,
- const char *path, const char *contents)
-{
- if (is_symlink(file, line, path, contents))
- return (1);
- if (contents)
- failure_start(file, line, "File %s is not a symlink to %s",
- path, contents);
- else
- failure_start(file, line, "File %s is not a symlink", path);
- failure_finish(NULL);
- return (0);
-}
-
-
-/* Create a directory and report any errors. */
-int
-assertion_make_dir(const char *file, int line, const char *dirname, int mode)
-{
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
- if (0 == _mkdir(dirname))
- return (1);
-#else
- if (0 == mkdir(dirname, mode)) {
- if (0 == chmod(dirname, mode)) {
- assertion_file_mode(file, line, dirname, mode);
- return (1);
- }
- }
-#endif
- failure_start(file, line, "Could not create directory %s", dirname);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a file with the specified contents and report any failures. */
-int
-assertion_make_file(const char *file, int line,
- const char *path, int mode, int csize, const void *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* TODO: Rework this to set file mode as well. */
- FILE *f;
- (void)mode; /* UNUSED */
- assertion_count(file, line);
- f = fopen(path, "wb");
- if (f == NULL) {
- failure_start(file, line, "Could not create file %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (contents != NULL) {
- size_t wsize;
-
- if (csize < 0)
- wsize = strlen(contents);
- else
- wsize = (size_t)csize;
- if (wsize != fwrite(contents, 1, wsize, f)) {
- fclose(f);
- failure_start(file, line,
- "Could not write file %s", path);
- failure_finish(NULL);
- return (0);
- }
- }
- fclose(f);
- return (1);
-#else
- int fd;
- assertion_count(file, line);
- fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
- if (fd < 0) {
- failure_start(file, line, "Could not create %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (0 != chmod(path, mode)) {
- failure_start(file, line, "Could not chmod %s", path);
- failure_finish(NULL);
- close(fd);
- return (0);
- }
- if (contents != NULL) {
- ssize_t wsize;
-
- if (csize < 0)
- wsize = (ssize_t)strlen(contents);
- else
- wsize = (ssize_t)csize;
- if (wsize != write(fd, contents, wsize)) {
- close(fd);
- failure_start(file, line,
- "Could not write to %s", path);
- failure_finish(NULL);
- close(fd);
- return (0);
- }
- }
- close(fd);
- assertion_file_mode(file, line, path, mode);
- return (1);
-#endif
-}
-
-/* Create a hardlink and report any failures. */
-int
-assertion_make_hardlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
- int succeeded;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- succeeded = my_CreateHardLinkA(newpath, linkto);
-#elif HAVE_LINK
- succeeded = !link(linkto, newpath);
-#else
- succeeded = 0;
-#endif
- if (succeeded)
- return (1);
- failure_start(file, line, "Could not create hardlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a symlink and report any failures. */
-int
-assertion_make_symlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- int targetIsDir = 0; /* TODO: Fix this */
- assertion_count(file, line);
- if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
- return (1);
-#elif HAVE_SYMLINK
- assertion_count(file, line);
- if (0 == symlink(linkto, newpath))
- return (1);
-#endif
- failure_start(file, line, "Could not create symlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Set umask, report failures. */
-int
-assertion_umask(const char *file, int line, int mask)
-{
- assertion_count(file, line);
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- umask(mask);
- return (1);
-}
-
-/* Set times, report failures. */
-int
-assertion_utimes(const char *file, int line,
- const char *pathname, long at, long at_nsec, long mt, long mt_nsec)
-{
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
- + (((nsec)/1000)*10))
- HANDLE h;
- ULARGE_INTEGER wintm;
- FILETIME fatime, fmtime;
- FILETIME *pat, *pmt;
-
- assertion_count(file, line);
- h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (at > 0 || at_nsec > 0) {
- wintm.QuadPart = WINTIME(at, at_nsec);
- fatime.dwLowDateTime = wintm.LowPart;
- fatime.dwHighDateTime = wintm.HighPart;
- pat = &fatime;
- } else
- pat = NULL;
- if (mt > 0 || mt_nsec > 0) {
- wintm.QuadPart = WINTIME(mt, mt_nsec);
- fmtime.dwLowDateTime = wintm.LowPart;
- fmtime.dwHighDateTime = wintm.HighPart;
- pmt = &fmtime;
- } else
- pmt = NULL;
- if (pat != NULL || pmt != NULL)
- r = SetFileTime(h, NULL, pat, pmt);
- else
- r = 1;
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't SetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#else /* defined(_WIN32) && !defined(__CYGWIN__) */
- struct stat st;
- struct timeval times[2];
-
-#if !defined(__FreeBSD__)
- mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */
-#endif
- if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0)
- return (1);
-
- r = lstat(pathname, &st);
- if (r < 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (mt == 0 && mt_nsec == 0) {
- mt = st.st_mtime;
-#if defined(__FreeBSD__)
- mt_nsec = st.st_mtimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- mt_nsec = (mt_nsec / 1000) * 1000;
-#endif
- }
- if (at == 0 && at_nsec == 0) {
- at = st.st_atime;
-#if defined(__FreeBSD__)
- at_nsec = st.st_atimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- at_nsec = (at_nsec / 1000) * 1000;
-#endif
- }
-
- times[1].tv_sec = mt;
- times[1].tv_usec = mt_nsec / 1000;
-
- times[0].tv_sec = at;
- times[0].tv_usec = at_nsec / 1000;
-
-#ifdef HAVE_LUTIMES
- r = lutimes(pathname, times);
-#else
- r = utimes(pathname, times);
-#endif
- if (r < 0) {
- failure_start(file, line, "Can't utimes %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
-}
-
-/* Set nodump, report failures. */
-int
-assertion_nodump(const char *file, int line, const char *pathname)
-{
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
- int r;
-
- assertion_count(file, line);
- r = chflags(pathname, UF_NODUMP);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-#elif defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)\
- && defined(EXT2_NODUMP_FL)
- int fd, r, flags;
-
- assertion_count(file, line);
- fd = open(pathname, O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
- failure_start(file, line, "Can't open %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't get flags %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- close(fd);
-#else
- (void)pathname; /* UNUSED */
- assertion_count(file, line);
-#endif
- return (1);
-}
-
-/*
- *
- * UTILITIES for use by tests.
- *
- */
-
-/*
- * Check whether platform supports symlinks. This is intended
- * for tests to use in deciding whether to bother testing symlink
- * support; if the platform doesn't support symlinks, there's no point
- * in checking whether the program being tested can create them.
- *
- * Note that the first time this test is called, we actually go out to
- * disk to create and verify a symlink. This is necessary because
- * symlink support is actually a property of a particular filesystem
- * and can thus vary between directories on a single system. After
- * the first call, this returns the cached result from memory, so it's
- * safe to call it as often as you wish.
- */
-int
-canSymlink(void)
-{
- /* Remember the test result */
- static int value = 0, tested = 0;
- if (tested)
- return (value);
-
- ++tested;
- assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a");
- /* Note: Cygwin has its own symlink() emulation that does not
- * use the Win32 CreateSymbolicLink() function. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
- value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
- && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
-#elif HAVE_SYMLINK
- value = (0 == symlink("canSymlink.0", "canSymlink.1"))
- && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
-#endif
- return (value);
-}
-
-/* Platform-dependent options for hiding the output of a subcommand. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
-#else
-static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
-#endif
-/*
- * Can this platform run the bzip2 program?
- */
-int
-canBzip2(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("bzip2 -d -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the grzip program?
- */
-int
-canGrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("grzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the gzip program?
- */
-int
-canGzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("gzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lrzip program?
- */
-int
-canRunCommand(const char *cmd)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("%s %s", cmd, redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-int
-canLrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lrzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lz4 program?
- */
-int
-canLz4(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lz4 -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzip program?
- */
-int
-canLzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzma program?
- */
-int
-canLzma(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzma -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzop program?
- */
-int
-canLzop(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzop -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the xz program?
- */
-int
-canXz(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("xz -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this filesystem handle nodump flags.
- */
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
-
-int
-canNodump(void)
-{
- const char *path = "cannodumptest";
- struct stat sb;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- if (chflags(path, UF_NODUMP) < 0)
- return (0);
- if (stat(path, &sb) < 0)
- 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)
-{
- const char *path = "cannodumptest";
- int fd, r, flags;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- fd = open(path, O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- return (0);
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0)
- return (0);
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &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);
- if (r < 0)
- return (0);
- close(fd);
- if (flags & EXT2_NODUMP_FL)
- return (1);
- return (0);
-}
-
-#else
-
-int
-canNodump()
-{
- return (0);
-}
-
-#endif
-
-/*
- * Sleep as needed; useful for verifying disk timestamp changes by
- * ensuring that the wall-clock time has actually changed before we
- * go back to re-read something from disk.
- */
-void
-sleepUntilAfter(time_t t)
-{
- while (t >= time(NULL))
-#if defined(_WIN32) && !defined(__CYGWIN__)
- Sleep(500);
-#else
- sleep(1);
-#endif
-}
-
-/*
- * Call standard system() call, but build up the command line using
- * sprintf() conventions.
- */
-int
-systemf(const char *fmt, ...)
-{
- char buff[8192];
- va_list ap;
- int r;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- if (verbosity > VERBOSITY_FULL)
- logprintf("Cmd: %s\n", buff);
- r = system(buff);
- va_end(ap);
- return (r);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-char *
-slurpfile(size_t * sizep, const char *fmt, ...)
-{
- char filename[8192];
- struct stat st;
- va_list ap;
- char *p;
- ssize_t bytes_read;
- FILE *f;
- int r;
-
- va_start(ap, fmt);
- vsprintf(filename, fmt, ap);
- va_end(ap);
-
- f = fopen(filename, "rb");
- if (f == NULL) {
- /* Note: No error; non-existent file is okay here. */
- return (NULL);
- }
- r = fstat(fileno(f), &st);
- if (r != 0) {
- logprintf("Can't stat file %s\n", filename);
- fclose(f);
- return (NULL);
- }
- p = malloc((size_t)st.st_size + 1);
- if (p == NULL) {
- logprintf("Can't allocate %ld bytes of memory to read file %s\n",
- (long int)st.st_size, filename);
- fclose(f);
- return (NULL);
- }
- bytes_read = fread(p, 1, (size_t)st.st_size, f);
- if (bytes_read < st.st_size) {
- logprintf("Can't read file %s\n", filename);
- fclose(f);
- free(p);
- return (NULL);
- }
- p[st.st_size] = '\0';
- if (sizep != NULL)
- *sizep = (size_t)st.st_size;
- fclose(f);
- return (p);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-void
-dumpfile(const char *filename, void *data, size_t len)
-{
- ssize_t bytes_written;
- FILE *f;
-
- f = fopen(filename, "wb");
- if (f == NULL) {
- logprintf("Can't open file %s for writing\n", filename);
- return;
- }
- bytes_written = fwrite(data, 1, len, f);
- if (bytes_written < (ssize_t)len)
- logprintf("Can't write file %s\n", filename);
- fclose(f);
-}
-
-/* Read a uuencoded file from the reference directory, decode, and
- * write the result into the current directory. */
-#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
-#define UUDECODE(c) (((c) - 0x20) & 0x3f)
-void
-extract_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
-
- sprintf(buff, "%s/%s.uu", refdir, name);
- in = fopen(buff, "r");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Read up to and including the 'begin' line. */
- for (;;) {
- if (fgets(buff, sizeof(buff), in) == NULL) {
- /* TODO: This is a failure. */
- return;
- }
- if (memcmp(buff, "begin ", 6) == 0)
- break;
- }
- /* Now, decode the rest and write it. */
- out = fopen(name, "wb");
- while (fgets(buff, sizeof(buff), in) != NULL) {
- char *p = buff;
- int bytes;
-
- if (memcmp(buff, "end", 3) == 0)
- break;
-
- bytes = UUDECODE(*p++);
- while (bytes > 0) {
- int n = 0;
- /* Write out 1-3 bytes from that. */
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- assert(VALID_UUDECODE(p[1]));
- n = UUDECODE(*p++) << 18;
- n |= UUDECODE(*p++) << 12;
- fputc(n >> 16, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++) << 6;
- fputc((n >> 8) & 0xFF, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++);
- fputc(n & 0xFF, out);
- --bytes;
- }
- }
- }
- fclose(out);
- fclose(in);
-}
-
-void
-copy_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
- size_t rbytes;
-
- sprintf(buff, "%s/%s", refdir, name);
- in = fopen(buff, "rb");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
- out = fopen(name, "wb");
- while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- if (fwrite(buff, 1, rbytes, out) != rbytes) {
- logprintf("Error: fwrite\n");
- break;
- }
- }
- fclose(out);
- fclose(in);
-}
-
-int
-is_LargeInode(const char *file)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- r = my_GetFileInformationByName(file, &bhfi);
- if (r != 0)
- return (0);
- return (bhfi.nFileIndexHigh & 0x0000FFFFUL);
-#else
- struct stat st;
- int64_t ino;
-
- if (stat(file, &st) < 0)
- return (0);
- ino = (int64_t)st.st_ino;
- return (ino > 0xffffffff);
-#endif
-}
-
-void
-extract_reference_files(const char **names)
-{
- while (names && *names)
- extract_reference_file(*names++);
-}
-
-/*
- *
- * TEST management
- *
- */
-
-/*
- * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has
- * a line like
- * DEFINE_TEST(test_function)
- * for each test.
- */
-
-/* Use "list.h" to declare all of the test functions. */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void);
-#include "list.h"
-
-/* Use "list.h" to create a list of all tests (functions and names). */
-#undef DEFINE_TEST
-#define DEFINE_TEST(n) { n, #n, 0 },
-struct test_list_t tests[] = {
- #include "list.h"
-};
-
-/*
- * Summarize repeated failures in the just-completed test.
- */
-static void
-test_summarize(int failed, int skips_num)
-{
- unsigned int i;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY:
- printf(failed ? "E" : ".");
- fflush(stdout);
- break;
- case VERBOSITY_PASSFAIL:
- printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n");
- break;
- }
-
- log_console = (verbosity == VERBOSITY_LIGHT_REPORT);
-
- for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
- if (failed_lines[i].count > 1 && !failed_lines[i].skip)
- logprintf("%s:%d: Summary: Failed %d times\n",
- failed_filename, i, failed_lines[i].count);
- }
- /* Clear the failure history for the next file. */
- failed_filename = NULL;
- memset(failed_lines, 0, sizeof(failed_lines));
-}
-
-/*
- * Actually run a single test, with appropriate setup and cleanup.
- */
-static int
-test_run(int i, const char *tmpdir)
-{
- char workdir[1024];
- char logfilename[64];
- int failures_before = failures;
- int skips_before = skips;
- int oldumask;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
- break;
- case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
- printf("%3d: %-64s", i, tests[i].name);
- fflush(stdout);
- break;
- default: /* Title of test, details will follow */
- printf("%3d: %s\n", i, tests[i].name);
- }
-
- /* Chdir to the top-level work directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to top work dir %s\n", tmpdir);
- exit(1);
- }
- /* Create a log file for this test. */
- sprintf(logfilename, "%s.log", tests[i].name);
- logfile = fopen(logfilename, "w");
- fprintf(logfile, "%s\n\n", tests[i].name);
- /* Chdir() to a work dir for this specific test. */
- snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name);
- testworkdir = workdir;
- if (!assertMakeDir(testworkdir, 0755)
- || !assertChdir(testworkdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to work dir %s\n", testworkdir);
- exit(1);
- }
- /* Explicitly reset the locale before each test. */
- setlocale(LC_ALL, "C");
- /* Record the umask before we run the test. */
- umask(oldumask = umask(0));
- /*
- * Run the actual test.
- */
- (*tests[i].func)();
- /*
- * Clean up and report afterwards.
- */
- testworkdir = NULL;
- /* Restore umask */
- umask(oldumask);
- /* Reset locale. */
- setlocale(LC_ALL, "C");
- /* Reset directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n",
- tmpdir);
- exit(1);
- }
- /* Report per-test summaries. */
- tests[i].failures = failures - failures_before;
- test_summarize(tests[i].failures, skips - skips_before);
- /* Close the per-test log file. */
- fclose(logfile);
- logfile = NULL;
- /* If there were no failures, we can remove the work dir and logfile. */
- if (tests[i].failures == 0) {
- if (!keep_temp_files && assertChdir(tmpdir)) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure not to leave empty directories.
- * Sometimes a processing of closing files used by tests
- * is not done, then rmdir will be failed and it will
- * leave a empty test directory. So we should wait a few
- * seconds and retry rmdir. */
- int r, t;
- for (t = 0; t < 10; t++) {
- if (t > 0)
- Sleep(1000);
- r = systemf("rmdir /S /Q %s", tests[i].name);
- if (r == 0)
- break;
- }
- systemf("del %s", logfilename);
-#else
- systemf("rm -rf %s", tests[i].name);
- systemf("rm %s", logfilename);
-#endif
- }
- }
- /* Return appropriate status. */
- return (tests[i].failures);
-}
-
-/*
- *
- *
- * MAIN and support routines.
- *
- *
- */
-
-static void
-usage(const char *program)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int i;
-
- printf("Usage: %s [options] <test> <test> ...\n", program);
- printf("Default is to run all tests.\n");
- printf("Otherwise, specify the numbers of the tests you wish to run.\n");
- printf("Options:\n");
- printf(" -d Dump core after any failure, for debugging.\n");
- printf(" -k Keep all temp files.\n");
- printf(" Default: temp files for successful tests deleted.\n");
-#ifdef PROGRAM
- printf(" -p <path> Path to executable to be tested.\n");
- printf(" Default: path taken from " ENVBASE " environment variable.\n");
-#endif
- printf(" -q Quiet.\n");
- printf(" -r <dir> Path to dir containing reference files.\n");
- printf(" Default: Current directory.\n");
- printf(" -u Keep running specifies tests until one fails.\n");
- printf(" -v Verbose.\n");
- printf("Available tests:\n");
- for (i = 0; i < limit; i++)
- printf(" %d: %s\n", i, tests[i].name);
- exit(1);
-}
-
-static char *
-get_refdir(const char *d)
-{
- size_t tried_size, buff_size;
- char *buff, *tried, *pwd = NULL, *p = NULL;
-
-#ifdef PATH_MAX
- buff_size = PATH_MAX;
-#else
- buff_size = 8192;
-#endif
- buff = calloc(buff_size, 1);
- if (buff == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* Allocate a buffer to hold the various directories we checked. */
- tried_size = buff_size * 2;
- tried = calloc(tried_size, 1);
- if (tried == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* If a dir was specified, try that */
- if (d != NULL) {
- pwd = NULL;
- snprintf(buff, buff_size, "%s", d);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- goto failure;
- }
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
- /* Look for a known file. */
- snprintf(buff, buff_size, "%s", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(LIBRARY)
- snprintf(buff, buff_size, "%s/%s/test", pwd, LIBRARY);
-#else
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM);
-#endif
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(PROGRAM_ALIAS)
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM_ALIAS);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-#endif
-
- if (memcmp(pwd, "/usr/obj", 8) == 0) {
- snprintf(buff, buff_size, "%s", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- }
-
-failure:
- printf("Unable to locate known reference file %s\n", KNOWNREF);
- printf(" Checked following directories:\n%s\n", tried);
- printf("Use -r option to specify full path to reference directory\n");
-#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
- DebugBreak();
-#endif
- exit(1);
-
-success:
- free(p);
- free(pwd);
- free(tried);
-
- /* Copy result into a fresh buffer to reduce memory usage. */
- p = strdup(buff);
- free(buff);
- return p;
-}
-
-int
-main(int argc, char **argv)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int test_set[sizeof(tests) / sizeof(tests[0])];
- int i = 0, j = 0, tests_run = 0, tests_failed = 0, option;
- time_t now;
- char *refdir_alloc = NULL;
- const char *progname;
- char **saved_argv;
- const char *tmp, *option_arg, *p;
- char tmpdir[256], *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL;
- char tmpdir_timestamp[256];
-
- (void)argc; /* UNUSED */
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
- /* To stop to run the default invalid parameter handler. */
- _set_invalid_parameter_handler(invalid_parameter_handler);
- /* Disable annoying assertion message box. */
- _CrtSetReportMode(_CRT_ASSERT, 0);
-#endif
-
- /*
- * Name of this program, used to build root of our temp directory
- * tree.
- */
- progname = p = argv[0];
- if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(testprogdir, progname);
- while (*p != '\0') {
- /* Support \ or / dir separators for Windows compat. */
- if (*p == '/' || *p == '\\')
- {
- progname = p + 1;
- i = j;
- }
- ++p;
- j++;
- }
- testprogdir[i] = '\0';
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (testprogdir[0] != '/' && testprogdir[0] != '\\' &&
- !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') ||
- (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) &&
- testprogdir[1] == ':' &&
- (testprogdir[2] == '/' || testprogdir[2] == '\\')))
-#else
- if (testprogdir[0] != '/')
-#endif
- {
- /* Fixup path for relative directories. */
- if ((testprogdir = (char *)realloc(testprogdir,
- strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir) + 1);
- memcpy(testprogdir, pwd, strlen(pwd));
- testprogdir[strlen(pwd)] = '/';
- }
-
-#ifdef PROGRAM
- /* Get the target program from environment, if available. */
- testprogfile = getenv(ENVBASE);
-#endif
-
- if (getenv("TMPDIR") != NULL)
- tmp = getenv("TMPDIR");
- else if (getenv("TMP") != NULL)
- tmp = getenv("TMP");
- else if (getenv("TEMP") != NULL)
- tmp = getenv("TEMP");
- else if (getenv("TEMPDIR") != NULL)
- tmp = getenv("TEMPDIR");
- else
- tmp = "/tmp";
-
- /* Allow -d to be controlled through the environment. */
- if (getenv(ENVBASE "_DEBUG") != NULL)
- dump_on_failure = 1;
-
- /* Allow -v to be controlled through the environment. */
- if (getenv("_VERBOSITY_LEVEL") != NULL)
- {
- vlevel = getenv("_VERBOSITY_LEVEL");
- verbosity = atoi(vlevel);
- if (verbosity < VERBOSITY_SUMMARY_ONLY || verbosity > VERBOSITY_FULL)
- {
- /* Unsupported verbosity levels are silently ignored */
- vlevel = NULL;
- verbosity = VERBOSITY_PASSFAIL;
- }
- }
-
- /* Get the directory holding test files from environment. */
- refdir = getenv(ENVBASE "_TEST_FILES");
-
- /*
- * Parse options, without using getopt(), which isn't available
- * on all platforms.
- */
- ++argv; /* Skip program name */
- while (*argv != NULL) {
- if (**argv != '-')
- break;
- p = *argv++;
- ++p; /* Skip '-' */
- while (*p != '\0') {
- option = *p++;
- option_arg = NULL;
- /* If 'opt' takes an argument, parse that. */
- if (option == 'p' || option == 'r') {
- if (*p != '\0')
- option_arg = p;
- else if (*argv == NULL) {
- fprintf(stderr,
- "Option -%c requires argument.\n",
- option);
- usage(progname);
- } else
- option_arg = *argv++;
- p = ""; /* End of this option word. */
- }
-
- /* Now, handle the option. */
- switch (option) {
- case 'd':
- dump_on_failure = 1;
- break;
- case 'k':
- keep_temp_files = 1;
- break;
- case 'p':
-#ifdef PROGRAM
- testprogfile = option_arg;
-#else
- fprintf(stderr, "-p option not permitted\n");
- usage(progname);
-#endif
- break;
- case 'q':
- if (!vlevel)
- verbosity--;
- break;
- case 'r':
- refdir = option_arg;
- break;
- case 'u':
- until_failure++;
- break;
- case 'v':
- if (!vlevel)
- verbosity++;
- break;
- default:
- fprintf(stderr, "Unrecognized option '%c'\n",
- option);
- usage(progname);
- }
- }
- }
-
- /*
- * Sanity-check that our options make sense.
- */
-#ifdef PROGRAM
- if (testprogfile == NULL)
- {
- if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 +
- strlen(PROGRAM) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(tmp2, testprogdir);
- strcat(tmp2, "/");
- strcat(tmp2, PROGRAM);
- testprogfile = tmp2;
- }
-
- {
- char *testprg;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Command.com sometimes rejects '/' separators. */
- testprg = strdup(testprogfile);
- for (i = 0; testprg[i] != '\0'; i++) {
- if (testprg[i] == '/')
- testprg[i] = '\\';
- }
- testprogfile = testprg;
-#endif
- /* Quote the name that gets put into shell command lines. */
- testprg = malloc(strlen(testprogfile) + 3);
- strcpy(testprg, "\"");
- strcat(testprg, testprogfile);
- strcat(testprg, "\"");
- testprog = testprg;
- }
-#endif
-
-#if !defined(_WIN32) && defined(SIGPIPE)
- { /* Ignore SIGPIPE signals */
- struct sigaction sa;
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(SIGPIPE, &sa, NULL);
- }
-#endif
-
- /*
- * Create a temp directory for the following tests.
- * Include the time the tests started as part of the name,
- * to make it easier to track the results of multiple tests.
- */
- now = time(NULL);
- for (i = 0; ; i++) {
- strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp),
- "%Y-%m-%dT%H.%M.%S",
- localtime(&now));
- sprintf(tmpdir, "%s/%s.%s-%03d", tmp, progname,
- tmpdir_timestamp, i);
- if (assertMakeDir(tmpdir,0755))
- break;
- if (i >= 999) {
- fprintf(stderr,
- "ERROR: Unable to create temp directory %s\n",
- tmpdir);
- exit(1);
- }
- }
-
- /*
- * If the user didn't specify a directory for locating
- * reference files, try to find the reference files in
- * the "usual places."
- */
- refdir = refdir_alloc = get_refdir(refdir);
-
- /*
- * Banner with basic information.
- */
- printf("\n");
- printf("If tests fail or crash, details will be in:\n");
- printf(" %s\n", tmpdir);
- printf("\n");
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("Reference files will be read from: %s\n", refdir);
-#ifdef PROGRAM
- printf("Running tests on: %s\n", testprog);
-#endif
- printf("Exercising: ");
- fflush(stdout);
- printf("%s\n", EXTRA_VERSION);
- } else {
- printf("Running ");
- fflush(stdout);
- }
-
- /*
- * Run some or all of the individual tests.
- */
- saved_argv = argv;
- do {
- argv = saved_argv;
- do {
- int test_num;
-
- test_num = get_test_set(test_set, limit, *argv, tests);
- if (test_num < 0) {
- printf("*** INVALID Test %s\n", *argv);
- free(refdir_alloc);
- free(testprogdir);
- usage(progname);
- return (1);
- }
- for (i = 0; i < test_num; i++) {
- tests_run++;
- if (test_run(test_set[i], tmpdir)) {
- tests_failed++;
- if (until_failure)
- goto finish;
- }
- }
- if (*argv != NULL)
- argv++;
- } while (*argv != NULL);
- } while (until_failure);
-
-finish:
- /* Must be freed after all tests run */
- free(tmp2);
- free(testprogdir);
- free(pwd);
-
- /*
- * Report summary statistics.
- */
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("\n");
- printf("Totals:\n");
- printf(" Tests run: %8d\n", tests_run);
- printf(" Tests failed: %8d\n", tests_failed);
- printf(" Assertions checked:%8d\n", assertions);
- printf(" Assertions failed: %8d\n", failures);
- printf(" Skips reported: %8d\n", skips);
- }
- if (failures) {
- printf("\n");
- printf("Failing tests:\n");
- for (i = 0; i < limit; ++i) {
- if (tests[i].failures)
- printf(" %d: %s (%d failures)\n", i,
- tests[i].name, tests[i].failures);
- }
- printf("\n");
- printf("Details for failing tests: %s\n", tmpdir);
- printf("\n");
- } else {
- if (verbosity == VERBOSITY_SUMMARY_ONLY)
- printf("\n");
- printf("%d tests passed, no failures\n", tests_run);
- }
-
- free(refdir_alloc);
-
- /* If the final tmpdir is empty, we can remove it. */
- /* This should be the usual case when all tests succeed. */
- assertChdir("..");
- rmdir(tmpdir);
-
- return (tests_failed ? 1 : 0);
-}
diff --git a/cpio/test/test.h b/cpio/test/test.h
index 49fa32c99e25..1dadf68890bf 100644
--- a/cpio/test/test.h
+++ b/cpio/test/test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2006 Tim Kientzle
+ * Copyright (c) 2003-2017 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,333 +22,19 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/usr.bin/cpio/test/test.h,v 1.2 2008/06/21 02:17:18 kientzle Exp $
+ * $FreeBSD$
*/
/* Every test program should #include "test.h" as the first thing. */
-/*
- * The goal of this file (and the matching test.c) is to
- * simplify the very repetitive test-*.c test programs.
- */
-#if defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "config.h"
-#elif defined(__FreeBSD__)
-/* Building as part of FreeBSD system requires a pre-built config.h. */
-#include "config_freebsd.h"
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-/* Win32 can't run the 'configure' script. */
-#include "config_windows.h"
-#else
-/* Warn if the library hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no pre-built configuration in test.h.
-#endif
-
-#include <sys/types.h> /* Windows requires this before sys/stat.h */
-#include <sys/stat.h>
-
-#if HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#define dirent direct
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <wchar.h>
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-/*
- * System-specific tweaks. We really want to minimize these
- * as much as possible, since they make it harder to understand
- * the mainline code.
- */
-
-/* Windows (including Visual Studio and MinGW but not Cygwin) */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(__BORLANDC__)
-#undef chdir
-#define chdir _chdir
-#define strdup _strdup
-#endif
-#endif
-
-/* Visual Studio */
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf sprintf_s
-#endif
-
-#if defined(__BORLANDC__)
-#pragma warn -8068 /* Constant out of range in comparison. */
-#endif
-
-/* Haiku OS and QNX */
-#if defined(__HAIKU__) || defined(__QNXNTO__)
-/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
-#include <stdint.h>
-#endif
-
-/* Get a real definition for __FBSDID if we can */
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-/* If not, define it so as to avoid dangling semicolons. */
-#ifndef __FBSDID
-#define __FBSDID(a) struct _undefined_hack
-#endif
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/*
- * Redefine DEFINE_TEST for use in defining the test functions.
- */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void); void name(void)
-
-/* An implementation of the standard assert() macro */
-#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
-/* chdir() and error if it fails */
-#define assertChdir(path) \
- assertion_chdir(__FILE__, __LINE__, path)
-/* 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)
-/* Assert two strings are the same. Reports value of each one if not. */
-#define assertEqualString(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
-#define assertEqualUTF8String(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
-/* As above, but v1 and v2 are wchar_t * */
-#define assertEqualWString(v1,v2) \
- assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-/* As above, but raw blocks of bytes. */
-#define assertEqualMem(v1, v2, l) \
- assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
-/* Assert that memory is full of a specified byte */
-#define assertMemoryFilledWith(v1, l, b) \
- assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
-/* Assert two files are the same. */
-#define assertEqualFile(f1, f2) \
- assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
-/* Assert that a file is empty. */
-#define assertEmptyFile(pathname) \
- assertion_empty_file(__FILE__, __LINE__, (pathname))
-/* Assert that a file is not empty. */
-#define assertNonEmptyFile(pathname) \
- assertion_non_empty_file(__FILE__, __LINE__, (pathname))
-#define assertFileAtime(pathname, sec, nsec) \
- assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileAtimeRecent(pathname) \
- assertion_file_atime_recent(__FILE__, __LINE__, pathname)
-#define assertFileBirthtime(pathname, sec, nsec) \
- assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileBirthtimeRecent(pathname) \
- assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
-/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileExists(pathname) \
- assertion_file_exists(__FILE__, __LINE__, pathname)
-/* Assert that a file exists. */
-#define assertFileNotExists(pathname) \
- assertion_file_not_exists(__FILE__, __LINE__, pathname)
-/* Assert that file contents match a string. */
-#define assertFileContents(data, data_size, pathname) \
- assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
-/* Verify that a file does not contain invalid strings */
-#define assertFileContainsNoInvalidStrings(pathname, strings) \
- assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
-#define assertFileMtime(pathname, sec, nsec) \
- assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileMtimeRecent(pathname) \
- assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
-#define assertFileNLinks(pathname, nlinks) \
- assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
-#define assertFileSize(pathname, size) \
- assertion_file_size(__FILE__, __LINE__, pathname, size)
-#define assertFileMode(pathname, mode) \
- assertion_file_mode(__FILE__, __LINE__, pathname, mode)
-#define assertTextFileContents(text, pathname) \
- assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
-#define assertFileContainsLinesAnyOrder(pathname, lines) \
- assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
-#define assertIsDir(pathname, mode) \
- assertion_is_dir(__FILE__, __LINE__, pathname, mode)
-#define assertIsHardlink(path1, path2) \
- assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsNotHardlink(path1, path2) \
- assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsReg(pathname, mode) \
- assertion_is_reg(__FILE__, __LINE__, pathname, mode)
-#define assertIsSymlink(pathname, contents) \
- assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
-/* Create a directory, report error if it fails. */
-#define assertMakeDir(dirname, mode) \
- assertion_make_dir(__FILE__, __LINE__, dirname, mode)
-#define assertMakeFile(path, mode, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents)
-#define assertMakeBinFile(path, mode, csize, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents)
-#define assertMakeHardlink(newfile, oldfile) \
- 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 assertUmask(mask) \
- assertion_umask(__FILE__, __LINE__, mask)
-#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
- assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
-
-/*
- * This would be simple with C99 variadic macros, but I don't want to
- * require that. Instead, I insert a function call before each
- * skipping() call to pass the file and line information down. Crude,
- * but effective.
- */
-#define skipping \
- skipping_setup(__FILE__, __LINE__);test_skipping
-
-/* Function declarations. These are defined in test_utility.c. */
-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_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 *);
-int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
-int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
-int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
-int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
-int assertion_file_atime(const char *, int, const char *, long, long);
-int assertion_file_atime_recent(const char *, int, const char *);
-int assertion_file_birthtime(const char *, int, const char *, long, long);
-int assertion_file_birthtime_recent(const char *, int, const char *);
-int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
-int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
-int assertion_file_contents(const char *, int, const void *, int, const char *);
-int assertion_file_exists(const char *, int, const char *);
-int assertion_file_mode(const char *, int, const char *, int);
-int assertion_file_mtime(const char *, int, const char *, long, long);
-int assertion_file_mtime_recent(const char *, int, const char *);
-int assertion_file_nlinks(const char *, int, const char *, int);
-int assertion_file_not_exists(const char *, int, const char *);
-int assertion_file_size(const char *, int, const char *, long);
-int assertion_is_dir(const char *, int, const char *, int);
-int assertion_is_hardlink(const char *, int, const char *, const char *);
-int assertion_is_not_hardlink(const char *, int, const char *, const char *);
-int assertion_is_reg(const char *, int, const char *, int);
-int assertion_is_symlink(const char *, int, const char *, const char *);
-int assertion_make_dir(const char *, int, const char *, int);
-int assertion_make_file(const char *, int, const char *, int, int, const void *);
-int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
-int assertion_make_symlink(const char *, int, const char *newpath, const char *);
-int assertion_nodump(const char *, int, const char *);
-int assertion_non_empty_file(const char *, int, const char *);
-int assertion_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 );
-
-void skipping_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
-
-/* Like sprintf, then system() */
-int systemf(const char * fmt, ...);
-
-/* Delay until time() returns a value after this. */
-void sleepUntilAfter(time_t);
-
-/* Return true if this platform can create symlinks. */
-int canSymlink(void);
-
-/* Return true if this platform can run the "bzip2" program. */
-int canBzip2(void);
-
-/* Return true if this platform can run the "grzip" program. */
-int canGrzip(void);
-
-/* Return true if this platform can run the "gzip" program. */
-int canGzip(void);
-
-/* Return true if this platform can run the specified command. */
-int canRunCommand(const char *);
-
-/* Return true if this platform can run the "lrzip" program. */
-int canLrzip(void);
-
-/* Return true if this platform can run the "lz4" program. */
-int canLz4(void);
-
-/* Return true if this platform can run the "lzip" program. */
-int canLzip(void);
-
-/* Return true if this platform can run the "lzma" program. */
-int canLzma(void);
-
-/* Return true if this platform can run the "lzop" program. */
-int canLzop(void);
-
-/* Return true if this platform can run the "xz" program. */
-int canXz(void);
-
-/* Return true if this filesystem can handle nodump flags. */
-int canNodump(void);
-
-/* Return true if the file has large i-node number(>0xffffffff). */
-int is_LargeInode(const char *);
-
-/* 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, ...);
-
-/* Dump block of bytes to a file. */
-void dumpfile(const char *filename, void *, size_t);
-
-/* Extracts named reference file to the current directory. */
-void extract_reference_file(const char *);
-/* Copies named reference file to the current directory. */
-void copy_reference_file(const char *);
-
-/* Extracts a list of files to the current directory.
- * List must be NULL terminated.
- */
-void extract_reference_files(const char **);
-
-/* Subtract umask from mode */
-mode_t umasked(mode_t expected_mode);
-
-/* Path to working directory for current test */
-extern const char *testworkdir;
-
-/*
- * Special interfaces for program test harness.
- */
-
-/* Pathname of exe to be tested. */
-extern const char *testprogfile;
-/* Name of exe to use in printf-formatted command strings. */
-/* On Windows, this includes leading/trailing quotes. */
-extern const char *testprog;
-
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
+#define KNOWNREF "test_option_f.cpio.uu"
+#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */
+#define PROGRAM "bsdcpio" /* Name of program being tested. */
+#define PROGRAM_ALIAS "cpio" /* Generic alias for program */
+#undef LIBRARY /* Not testing a library. */
+#undef EXTRA_DUMP /* How to dump extra data */
+#undef EXTRA_ERRNO /* How to dump errno */
+/* How to generate extra version info. */
+#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
+
+#include "test_common.h"
diff --git a/cpio/test/test_option_version.c b/cpio/test/test_option_version.c
index ac58cefda11f..505db27128fe 100644
--- a/cpio/test/test_option_version.c
+++ b/cpio/test/test_option_version.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2017 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,92 +23,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
-__FBSDID("$FreeBSD$");
-
-/*
- * Test that --version option works and generates reasonable output.
- */
-
-static void
-verify(const char *p, size_t s)
-{
- const char *q = p;
-
- /* Version message should start with name of program, then space. */
- failure("version message too short:", p);
- if (!assert(s > 6))
- return;
- failure("Version message should begin with 'bsdcpio': %s", p);
- if (!assertEqualMem(q, "bsdcpio ", 8))
- /* If we're not testing bsdcpio, don't keep going. */
- return;
- q += 8; s -= 8;
- /* Version number is a series of digits and periods. */
- while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
- ++q;
- --s;
- }
- /* Version number terminated by space. */
- failure("Version: %s", p);
- assert(s > 1);
- /* Skip a single trailing a,b,c, or d. */
- if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
- ++q;
- failure("Version: %s", p);
- assert(*q == ' ');
- ++q; --s;
- /* Separator. */
- failure("Version: %s", p);
- assertEqualMem(q, "- ", 2);
- q += 2; s -= 2;
- /* libarchive name and version number */
- assert(s > 11);
- failure("Version: %s", p);
- assertEqualMem(q, "libarchive ", 11);
- q += 11; s -= 11;
- /* Version number is a series of digits and periods. */
- while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
- ++q;
- --s;
- }
- /* Skip a single trailing a,b,c, or d. */
- if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
- ++q;
- /* Skip arbitrary third-party version numbers. */
- while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || isalnum(*q))) {
- ++q;
- --s;
- }
- /* All terminated by end-of-line: \r, \r\n, or \n */
- assert(s >= 1);
- failure("Version: %s", p);
- if (*q == '\x0d') {
- if (q[1] != '\0')
- assertEqualMem(q, "\x0d\x0a", 2);
- } else
- assertEqualMem(q, "\x0a", 1);
-}
-
DEFINE_TEST(test_option_version)
{
- int r;
- char *p;
- size_t s;
-
- r = systemf("%s --version >version.stdout 2>version.stderr", testprog);
- if (r != 0)
- r = systemf("%s -W version >version.stdout 2>version.stderr",
- testprog);
- failure("Unable to run either %s --version or %s -W version",
- testprog, testprog);
- if (!assert(r == 0))
- return;
-
- /* --version should generate nothing to stderr. */
- assertEmptyFile("version.stderr");
- /* Verify format of version message. */
- p = slurpfile(&s, "version.stdout");
- verify(p, s);
- free(p);
+ assertVersion(testprog, "bsdcpio");
}
diff --git a/libarchive/archive.h b/libarchive/archive.h
index c67685802193..d400735a272a 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 3002002
+#define ARCHIVE_VERSION_NUMBER 3003001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.2.2"
+#define ARCHIVE_VERSION_ONLY_STRING "3.3.1"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -1001,6 +1001,10 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
#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_digest_private.h b/libarchive/archive_digest_private.h
index b58ffb348f60..b4fd6ca22527 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.c b/libarchive/archive_entry.c
index d4f061b5b9d0..10eff11b287f 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -1649,7 +1649,10 @@ static struct flag {
{ "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 @@ static struct flag {
{ "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 @@ static struct flag {
#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 @@ static struct flag {
#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 ca77b37810f2..7645f0cf6011 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 3002002
+#define ARCHIVE_VERSION_NUMBER 3003001
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -66,6 +66,27 @@ typedef int64_t la_int64_t;
# endif
#endif
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+# elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+# else
+typedef long la_ssize_t;
+# endif
+# else
+# include <unistd.h> /* ssize_t */
+typedef ssize_t la_ssize_t;
+# endif
+#endif
+
/* Get a suitable definition for mode_t */
#if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
@@ -526,9 +547,9 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type
#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010
__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
- ssize_t * /* len */, int /* flags */);
+ la_ssize_t * /* len */, int /* flags */);
__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
- ssize_t * /* len */, int /* flags */);
+ la_ssize_t * /* len */, int /* flags */);
__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
const wchar_t * /* wtext */, int /* type */);
__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c
index 1e0ae283bc94..f29965577f01 100644
--- a/libarchive/archive_hmac.c
+++ b/libarchive/archive_hmac.c
@@ -76,6 +76,10 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
#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_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c
index b9cd8da9017f..b2f1d17d9718 100644
--- a/libarchive/archive_read_disk_entry_from_file.c
+++ b/libarchive/archive_read_disk_entry_from_file.c
@@ -203,15 +203,17 @@ archive_read_disk_entry_from_file(struct archive *_a,
#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 +225,13 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
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 +277,15 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
#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;
@@ -321,20 +331,17 @@ setup_mac_metadata(struct archive_read_disk *a,
name = archive_entry_sourcepath(entry);
if (name == NULL)
name = archive_entry_pathname(entry);
+ else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't change dir to read extended attributes");
+ return (ARCHIVE_FAILED);
+ }
if (name == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't open file to read extended attributes: No name");
return (ARCHIVE_WARN);
}
- if (a->tree != NULL) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't change dir");
- return (ARCHIVE_FAILED);
- }
- }
-
/* Short-circuit if there's nothing to do. */
have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
if (have_attrs == -1) {
@@ -453,21 +460,32 @@ setup_acls(struct archive_read_disk *a,
#endif
int r;
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
+ accpath = NULL;
- if (*fd < 0 && a->tree != NULL) {
- if (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)
+#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
+ if (*fd < 0)
+#else
+ /* For default ACLs on Linux we need reachable accpath */
+ if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
+#endif
+ {
+ accpath = archive_entry_sourcepath(entry);
+ if (accpath == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ accpath = archive_entry_pathname(entry);
+ if (accpath == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read ACLs");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL &&
+#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
+ *fd < 0 &&
+#endif
+ (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
*fd = a->open_on_current_dir(a->tree,
accpath, O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", accpath);
- return (ARCHIVE_FAILED);
- }
}
}
@@ -530,11 +548,11 @@ setup_acls(struct archive_read_disk *a,
acl_free(acl);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
-#if HAVE_SUN_ACL
- "Couldn't translate ACLs: %s", accpath);
-#else
- "Couldn't translate NFSv4 ACLs: %s", accpath);
+ "Couldn't translate "
+#if !HAVE_SUN_ACL
+ "NFSv4 "
#endif
+ "ACLs");
}
#if HAVE_DARWIN_ACL
/*
@@ -543,8 +561,8 @@ setup_acls(struct archive_read_disk *a,
* the archive entry. Otherwise extraction on non-Mac platforms
* would lead to an invalid file mode.
*/
- if (archive_entry_acl_count(entry,
- ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0)
+ if ((archive_entry_acl_types(entry) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
add_trivial_nfs4_acl(entry);
#endif
return (r);
@@ -586,7 +604,7 @@ setup_acls(struct archive_read_disk *a,
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
- "Couldn't translate access ACLs: %s", accpath);
+ "Couldn't translate access ACLs");
return (r);
}
}
@@ -605,8 +623,7 @@ setup_acls(struct archive_read_disk *a,
acl_free(acl);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
- "Couldn't translate default ACLs: %s",
- accpath);
+ "Couldn't translate default ACLs");
return (r);
}
}
@@ -1411,15 +1428,10 @@ setup_acls(struct archive_read_disk *a,
static int
setup_xattr(struct archive_read_disk *a,
- struct archive_entry *entry, const char *name, int fd)
+ struct archive_entry *entry, const char *name, int fd, const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
#if HAVE_FGETXATTR
if (fd >= 0)
@@ -1484,21 +1496,23 @@ setup_xattrs(struct archive_read_disk *a,
const char *path;
ssize_t list_size;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
+ path = NULL;
- if (*fd < 0 && a->tree != NULL) {
- if (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", path);
- return (ARCHIVE_FAILED);
- }
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
}
}
@@ -1561,7 +1575,7 @@ setup_xattrs(struct archive_read_disk *a,
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
continue;
- setup_xattr(a, entry, p, *fd);
+ setup_xattr(a, entry, p, *fd, path);
}
free(list);
@@ -1582,19 +1596,16 @@ setup_xattrs(struct archive_read_disk *a,
*/
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd);
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *path);
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd)
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
if (fd >= 0)
size = extattr_get_fd(fd, namespace, name, NULL, 0);
@@ -1644,21 +1655,23 @@ setup_xattrs(struct archive_read_disk *a,
const char *path;
int namespace = EXTATTR_NAMESPACE_USER;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
+ path = NULL;
- if (*fd < 0 && a->tree != NULL) {
- if (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", path);
- return (ARCHIVE_FAILED);
- }
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
}
}
@@ -1708,7 +1721,7 @@ setup_xattrs(struct archive_read_disk *a,
name = buff + strlen(buff);
memcpy(name, p + 1, len);
name[len] = '\0';
- setup_xattr(a, entry, namespace, name, buff, *fd);
+ setup_xattr(a, entry, namespace, name, buff, *fd, path);
p += 1 + len;
}
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
index b89370421c07..6961ae6a42fe 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -465,8 +465,7 @@ archive_read_disk_new(void)
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 @@ archive_read_disk_set_symlink_hybrid(struct archive *_a)
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_read_disk_set_behavior(struct archive *_a, int flags)
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 @@ next_entry(struct archive_read_disk *a, struct tree *t,
} 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 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
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 @@ next_entry(struct archive_read_disk *a, struct tree *t,
* 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 @@ next_entry(struct archive_read_disk *a, struct tree *t,
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 @@ _archive_read_disk_open(struct archive *_a, const char *pathname)
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 @@ tree_open(const char *path, int symlink_mode, int restore_time)
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 2569321da544..b5a8328b7bfe 100644
--- a/libarchive/archive_read_disk_private.h
+++ b/libarchive/archive_read_disk_private.h
@@ -63,16 +63,8 @@ struct archive_read_disk {
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 27b75e3b10ce..3b903304f08b 100644
--- a/libarchive/archive_read_disk_windows.c
+++ b/libarchive/archive_read_disk_windows.c
@@ -398,8 +398,7 @@ archive_read_disk_new(void)
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 @@ archive_read_disk_set_atime_restored(struct archive *_a)
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_read_disk_set_behavior(struct archive *_a, int flags)
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 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
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 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
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 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
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_support_format_tar.c b/libarchive/archive_read_support_format_tar.c
index bc4ba3db2871..bd7f13d52eeb 100644
--- a/libarchive/archive_read_support_format_tar.c
+++ b/libarchive/archive_read_support_format_tar.c
@@ -847,9 +847,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
tar->sparse_gnu_pending = 0;
/* Read initial sparse map. */
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
- tar->entry_bytes_remaining -= bytes_read;
if (bytes_read < 0)
return ((int)bytes_read);
+ tar->entry_bytes_remaining -= bytes_read;
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -2487,6 +2487,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
tar_flush_unconsumed(a, unconsumed);
bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
to_skip = 0x1ff & -bytes_read;
+ /* Fail if tar->entry_bytes_remaing would get negative */
+ if (to_skip > remaining)
+ return (ARCHIVE_FATAL);
if (to_skip != __archive_read_consume(a, to_skip))
return (ARCHIVE_FATAL);
return ((ssize_t)(bytes_read + to_skip));
diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c
index 5e22438d268b..b1624651426c 100644
--- a/libarchive/archive_read_support_format_warc.c
+++ b/libarchive/archive_read_support_format_warc.c
@@ -543,7 +543,7 @@ xstrpisotime(const char *s, char **endptr)
/* 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 @@ static unsigned int
_warc_rdver(const char *buf, size_t bsz)
{
static const char magic[] = "WARC/";
+ const char *c;
unsigned int ver = 0U;
unsigned int end = 0U;
@@ -615,11 +616,12 @@ _warc_rdver(const char *buf, size_t bsz)
* 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 +645,7 @@ _warc_rdtyp(const char *buf, size_t bsz)
}
/* overread whitespace */
- while (val < eol && isblank((unsigned char)*val))
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
if (val + 8U == eol) {
@@ -673,7 +675,7 @@ _warc_rduri(const char *buf, size_t bsz)
return res;
}
- while (val < eol && isblank((unsigned char)*val))
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
/* overread URL designators */
@@ -731,7 +733,7 @@ _warc_rdlen(const char *buf, size_t bsz)
}
/* 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))
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 49e79dc23e9d..5a01e8450cef 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -1712,7 +1712,8 @@ _archive_write_disk_finish_entry(struct archive *_a)
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),
@@ -2067,6 +2068,7 @@ create_filesystem_object(struct archive_write_disk *a)
int r;
/* these for check_symlinks_fsobj */
char *linkname_copy; /* non-const copy of linkname */
+ struct stat st;
struct archive_string error_string;
int error_number;
@@ -2131,11 +2133,20 @@ create_filesystem_object(struct archive_write_disk *a)
a->todo = 0;
a->deferred = 0;
} else if (r == 0 && a->filesize > 0) {
- a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY
- | O_CLOEXEC | O_NOFOLLOW);
- __archive_ensure_cloexec_flag(a->fd);
- if (a->fd < 0)
+#ifdef HAVE_LSTAT
+ r = lstat(a->name, &st);
+#else
+ r = stat(a->name, &st);
+#endif
+ if (r != 0)
r = errno;
+ else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
+ a->fd = open(a->name, O_WRONLY | O_TRUNC |
+ O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+ __archive_ensure_cloexec_flag(a->fd);
+ if (a->fd < 0)
+ r = errno;
+ }
}
return (r);
#endif
@@ -2283,7 +2294,8 @@ _archive_write_disk_close(struct archive *_a)
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,
@@ -3455,12 +3467,19 @@ set_fflags(struct archive_write_disk *a)
#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);
@@ -3572,7 +3591,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
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.
*/
@@ -3585,7 +3607,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
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))
@@ -3606,12 +3628,19 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
* 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
@@ -3619,12 +3648,24 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
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;
@@ -3633,7 +3674,13 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
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_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c
index 4e910979e096..c0ca435d15c7 100644
--- a/libarchive/archive_write_set_format_iso9660.c
+++ b/libarchive/archive_write_set_format_iso9660.c
@@ -4074,8 +4074,10 @@ write_information_block(struct archive_write *a)
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/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt
index 6c4ac23baa24..5016eed369ec 100644
--- a/libarchive/test/CMakeLists.txt
+++ b/libarchive/test/CMakeLists.txt
@@ -6,7 +6,7 @@
IF(ENABLE_TEST)
SET(libarchive_test_SOURCES
../../test_utils/test_utils.c
- main.c
+ ../../test_utils/test_main.c
read_open_memory.c
test.h
test_acl_nfs4.c
@@ -303,6 +303,7 @@ IF(ENABLE_TEST)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
+ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/libarchive/test)
# Experimental new test handling
ADD_CUSTOM_TARGET(run_libarchive_test
diff --git a/libarchive/test/test.h b/libarchive/test/test.h
index 58df1cbfb893..fd679f5f2ffe 100644
--- a/libarchive/test/test.h
+++ b/libarchive/test/test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2006 Tim Kientzle
+ * Copyright (c) 2003-2017 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -21,388 +21,16 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: head/lib/libarchive/test/test.h 201247 2009-12-30 05:59:21Z kientzle $
*/
/* Every test program should #include "test.h" as the first thing. */
-/*
- * The goal of this file (and the matching test.c) is to
- * simplify the very repetitive test-*.c test programs.
- */
-#if defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "config.h"
-#elif defined(__FreeBSD__)
-/* Building as part of FreeBSD system requires a pre-built config.h. */
-#include "config_freebsd.h"
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-/* Win32 can't run the 'configure' script. */
-#include "config_windows.h"
-#else
-/* Warn if the library hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no pre-built configuration in test.h.
-#endif
-
-#include <sys/types.h> /* Windows requires this before sys/stat.h */
-#include <sys/stat.h>
-
-#if HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#define dirent direct
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <wchar.h>
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-/*
- * System-specific tweaks. We really want to minimize these
- * as much as possible, since they make it harder to understand
- * the mainline code.
- */
-
-/* Windows (including Visual Studio and MinGW but not Cygwin) */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(__BORLANDC__)
-#undef chdir
-#define chdir _chdir
-#define strdup _strdup
-#endif
-#endif
-
-/* Visual Studio */
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf sprintf_s
-#endif
-
-#if defined(__BORLANDC__)
-#pragma warn -8068 /* Constant out of range in comparison. */
-#endif
-
-/* Haiku OS and QNX */
-#if defined(__HAIKU__) || defined(__QNXNTO__)
-/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
-#include <stdint.h>
-#endif
-
-/* Get a real definition for __FBSDID if we can */
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-/* If not, define it so as to avoid dangling semicolons. */
-#ifndef __FBSDID
-#define __FBSDID(a) struct _undefined_hack
-#endif
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/*
- * If this platform has <sys/acl.h>, acl_create(), acl_init(),
- * acl_set_file(), and ACL_USER, we assume it has the rest of the
- * POSIX.1e draft functions used in archive_read_extract.c.
- */
-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
-#if HAVE_ACL_USER
-#define HAVE_POSIX_ACL 1
-#elif HAVE_ACL_TYPE_EXTENDED
-#define HAVE_DARWIN_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
-#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
-#endif
-
-/*
- * Redefine DEFINE_TEST for use in defining the test functions.
- */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void); void name(void)
-
-/* An implementation of the standard assert() macro */
-#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
-/* chdir() and error if it fails */
-#define assertChdir(path) \
- assertion_chdir(__FILE__, __LINE__, path)
-/* 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)
-/* Assert two strings are the same. Reports value of each one if not. */
-#define assertEqualString(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
-#define assertEqualUTF8String(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
-/* As above, but v1 and v2 are wchar_t * */
-#define assertEqualWString(v1,v2) \
- assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-/* As above, but raw blocks of bytes. */
-#define assertEqualMem(v1, v2, l) \
- assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
-/* Assert that memory is full of a specified byte */
-#define assertMemoryFilledWith(v1, l, b) \
- assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
-/* Assert two files are the same. */
-#define assertEqualFile(f1, f2) \
- assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
-/* Assert that a file is empty. */
-#define assertEmptyFile(pathname) \
- assertion_empty_file(__FILE__, __LINE__, (pathname))
-/* Assert that a file is not empty. */
-#define assertNonEmptyFile(pathname) \
- assertion_non_empty_file(__FILE__, __LINE__, (pathname))
-#define assertFileAtime(pathname, sec, nsec) \
- assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileAtimeRecent(pathname) \
- assertion_file_atime_recent(__FILE__, __LINE__, pathname)
-#define assertFileBirthtime(pathname, sec, nsec) \
- assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileBirthtimeRecent(pathname) \
- assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
-/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileExists(pathname) \
- assertion_file_exists(__FILE__, __LINE__, pathname)
-/* Assert that a file exists. */
-#define assertFileNotExists(pathname) \
- assertion_file_not_exists(__FILE__, __LINE__, pathname)
-/* Assert that file contents match a string. */
-#define assertFileContents(data, data_size, pathname) \
- assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
-/* Verify that a file does not contain invalid strings */
-#define assertFileContainsNoInvalidStrings(pathname, strings) \
- assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
-#define assertFileMtime(pathname, sec, nsec) \
- assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileMtimeRecent(pathname) \
- assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
-#define assertFileNLinks(pathname, nlinks) \
- assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
-#define assertFileSize(pathname, size) \
- assertion_file_size(__FILE__, __LINE__, pathname, size)
-#define assertFileMode(pathname, mode) \
- assertion_file_mode(__FILE__, __LINE__, pathname, mode)
-#define assertTextFileContents(text, pathname) \
- assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
-#define assertFileContainsLinesAnyOrder(pathname, lines) \
- assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
-#define assertIsDir(pathname, mode) \
- assertion_is_dir(__FILE__, __LINE__, pathname, mode)
-#define assertIsHardlink(path1, path2) \
- assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsNotHardlink(path1, path2) \
- assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsReg(pathname, mode) \
- assertion_is_reg(__FILE__, __LINE__, pathname, mode)
-#define assertIsSymlink(pathname, contents) \
- assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
-/* Create a directory, report error if it fails. */
-#define assertMakeDir(dirname, mode) \
- assertion_make_dir(__FILE__, __LINE__, dirname, mode)
-#define assertMakeFile(path, mode, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents)
-#define assertMakeBinFile(path, mode, csize, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents)
-#define assertMakeHardlink(newfile, oldfile) \
- 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 assertUmask(mask) \
- assertion_umask(__FILE__, __LINE__, mask)
-#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
- assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
-
-/*
- * This would be simple with C99 variadic macros, but I don't want to
- * require that. Instead, I insert a function call before each
- * skipping() call to pass the file and line information down. Crude,
- * but effective.
- */
-#define skipping \
- skipping_setup(__FILE__, __LINE__);test_skipping
-
-/* Function declarations. These are defined in test_utility.c. */
-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_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 *);
-int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
-int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
-int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
-int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
-int assertion_file_atime(const char *, int, const char *, long, long);
-int assertion_file_atime_recent(const char *, int, const char *);
-int assertion_file_birthtime(const char *, int, const char *, long, long);
-int assertion_file_birthtime_recent(const char *, int, const char *);
-int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
-int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
-int assertion_file_contents(const char *, int, const void *, int, const char *);
-int assertion_file_exists(const char *, int, const char *);
-int assertion_file_mode(const char *, int, const char *, int);
-int assertion_file_mtime(const char *, int, const char *, long, long);
-int assertion_file_mtime_recent(const char *, int, const char *);
-int assertion_file_nlinks(const char *, int, const char *, int);
-int assertion_file_not_exists(const char *, int, const char *);
-int assertion_file_size(const char *, int, const char *, long);
-int assertion_is_dir(const char *, int, const char *, int);
-int assertion_is_hardlink(const char *, int, const char *, const char *);
-int assertion_is_not_hardlink(const char *, int, const char *, const char *);
-int assertion_is_reg(const char *, int, const char *, int);
-int assertion_is_symlink(const char *, int, const char *, const char *);
-int assertion_make_dir(const char *, int, const char *, int);
-int assertion_make_file(const char *, int, const char *, int, int, const void *);
-int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
-int assertion_make_symlink(const char *, int, const char *newpath, const char *);
-int assertion_nodump(const char *, int, const char *);
-int assertion_non_empty_file(const char *, int, const char *);
-int assertion_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 );
-
-void skipping_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
-
-/* Like sprintf, then system() */
-int systemf(const char * fmt, ...);
-
-/* Delay until time() returns a value after this. */
-void sleepUntilAfter(time_t);
-
-/* Return true if this platform can create symlinks. */
-int canSymlink(void);
-
-/* Return true if this platform can run the "bzip2" program. */
-int canBzip2(void);
-
-/* Return true if this platform can run the "grzip" program. */
-int canGrzip(void);
-
-/* Return true if this platform can run the "gzip" program. */
-int canGzip(void);
-
-/* Return true if this platform can run the specified command. */
-int canRunCommand(const char *);
-
-/* Return true if this platform can run the "lrzip" program. */
-int canLrzip(void);
-
-/* Return true if this platform can run the "lz4" program. */
-int canLz4(void);
-
-/* Return true if this platform can run the "lzip" program. */
-int canLzip(void);
-
-/* Return true if this platform can run the "lzma" program. */
-int canLzma(void);
-
-/* Return true if this platform can run the "lzop" program. */
-int canLzop(void);
-
-/* Return true if this platform can run the "xz" program. */
-int canXz(void);
-
-/* Return true if this filesystem can handle nodump flags. */
-int canNodump(void);
-
-/* Return true if the file has large i-node number(>0xffffffff). */
-int is_LargeInode(const char *);
-
-/* 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, ...);
-
-/* Dump block of bytes to a file. */
-void dumpfile(const char *filename, void *, size_t);
-
-/* Extracts named reference file to the current directory. */
-void extract_reference_file(const char *);
-/* Copies named reference file to the current directory. */
-void copy_reference_file(const char *);
-
-/* Extracts a list of files to the current directory.
- * List must be NULL terminated.
- */
-void extract_reference_files(const char **);
-
-/* Subtract umask from mode */
-mode_t umasked(mode_t expected_mode);
-
-/* Path to working directory for current test */
-extern const char *testworkdir;
-
-/*
- * Special interfaces for libarchive test harness.
- */
-
-#include "archive.h"
-#include "archive_entry.h"
-
-/* ACL structure */
-struct archive_test_acl_t {
- int type; /* Type of ACL */
- int permset; /* Permissions for this class of users. */
- int tag; /* Owner, User, Owning group, group, other, etc. */
- int qual; /* GID or UID of user/group, depending on tag. */
- const char *name; /* Name of user/group, depending on tag. */
-};
-
-/* Set ACLs */
-void archive_test_set_acls(struct archive_entry *, struct archive_test_acl_t *,
- int);
-
-/* Compare ACLs */
-void archive_test_compare_acls(struct archive_entry *,
- struct archive_test_acl_t *, int, int, int);
-
-/* Special customized read-from-memory interface. */
-int read_open_memory(struct archive *, const void *, size_t, size_t);
-/* _minimal version exercises a slightly different set of libarchive APIs. */
-int read_open_memory_minimal(struct archive *, const void *, size_t, size_t);
-/* _seek version produces a seekable file. */
-int read_open_memory_seek(struct archive *, const void *, size_t, size_t);
-
-/* Versions of above that accept an archive argument for additional info. */
-#define assertA(e) assertion_assert(__FILE__, __LINE__, (e), #e, (a))
-#define assertEqualIntA(a,v1,v2) \
- assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
-#define assertEqualStringA(a,v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a), 0)
+#define KNOWNREF "test_compat_gtar_1.tar.uu"
+#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */
+#undef PROGRAM /* Testing a library, not a program. */
+#define LIBRARY "libarchive"
+#define EXTRA_DUMP(x) archive_error_string((struct archive *)(x))
+#define EXTRA_ERRNO(x) archive_errno((struct archive *)(x))
+#define EXTRA_VERSION archive_version_details()
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
+#include "test_common.h"
diff --git a/libarchive/test/test_acl_nfs4.c b/libarchive/test/test_acl_nfs4.c
index f4e66f52294e..fdc0191516e1 100644
--- a/libarchive/test/test_acl_nfs4.c
+++ b/libarchive/test/test_acl_nfs4.c
@@ -159,7 +159,7 @@ DEFINE_TEST(test_acl_nfs4)
archive_entry_set_mode(ae, S_IFREG | 0777);
/* Store and read back some basic ACL entries. */
- archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
+ assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
/* Check that entry contains only NFSv4 types */
assert((archive_entry_acl_types(ae) &
@@ -169,21 +169,21 @@ DEFINE_TEST(test_acl_nfs4)
assertEqualInt(4,
archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* A more extensive set of ACLs. */
- archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
+ assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertEqualInt(32,
archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
+ assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/*
* Check that clearing ACLs gets rid of them all by repeating
* the first test.
*/
- archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
+ assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
failure("Basic ACLs shouldn't be stored as extended ACLs");
assertEqualInt(4,
archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
@@ -192,7 +192,7 @@ DEFINE_TEST(test_acl_nfs4)
* Different types of malformed ACL entries that should
* fail when added to existing NFS4 ACLs.
*/
- archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
+ assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
for (i = 0; i < (int)(sizeof(acls_bad)/sizeof(acls_bad[0])); ++i) {
struct archive_test_acl_t *p = &acls_bad[i];
failure("Malformed ACL test #%d", i);
diff --git a/libarchive/test/test_acl_pax.c b/libarchive/test/test_acl_pax.c
index 8dfa0e031312..8566f55a51a4 100644
--- a/libarchive/test/test_acl_pax.c
+++ b/libarchive/test/test_acl_pax.c
@@ -238,23 +238,22 @@ DEFINE_TEST(test_acl_pax_posix1e)
archive_entry_set_mode(ae, S_IFREG | 0777);
/* Basic owner/owning group should just update mode bits. */
- archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
+ assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
assertA(0 == archive_write_header(a, ae));
/* With any extended ACL entry, we should read back a full set. */
- archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
+ assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
assertA(0 == archive_write_header(a, ae));
-
/* A more extensive set of ACLs. */
- archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
+ assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertA(0 == archive_write_header(a, ae));
/*
* Check that clearing ACLs gets rid of them all by repeating
* the first test.
*/
- archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
+ assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
assertA(0 == archive_write_header(a, ae));
archive_entry_free(ae);
@@ -296,7 +295,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
assertA(0 == archive_read_next_header(a, &ae));
failure("One extended ACL should flag all ACLs to be returned.");
assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
@@ -306,7 +305,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
+ assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
@@ -350,15 +349,15 @@ DEFINE_TEST(test_acl_pax_nfs4)
archive_entry_set_mode(ae, S_IFREG | 0777);
/* NFS4 ACLs mirroring 0754 file mode */
- archive_test_set_acls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]));
+ assertEntrySetAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]));
assertA(0 == archive_write_header(a, ae));
/* A more extensive set of NFS4 ACLs. */
- archive_test_set_acls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]));
+ assertEntrySetAcls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]));
assertA(0 == archive_write_header(a, ae));
/* Set with special (audit, alarm) NFS4 ACLs. */
- archive_test_set_acls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]));
+ assertEntrySetAcls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]));
assertA(0 == archive_write_header(a, ae));
archive_entry_free(ae);
@@ -393,21 +392,21 @@ DEFINE_TEST(test_acl_pax_nfs4)
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(3, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ALLOW));
- archive_test_compare_acls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
+ assertEntryCompareAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0);
/* Second item has has more fine-grained NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]),
+ assertEntryCompareAcls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Third item has has audit and alarm NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]),
+ assertEntryCompareAcls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Close the archive. */
diff --git a/libarchive/test/test_acl_platform_posix1e.c b/libarchive/test/test_acl_platform_posix1e.c
index 1d55a33eb951..b46f65815307 100644
--- a/libarchive/test/test_acl_platform_posix1e.c
+++ b/libarchive/test/test_acl_platform_posix1e.c
@@ -393,7 +393,7 @@ DEFINE_TEST(test_acl_platform_posix1e_restore)
archive_entry_set_pathname(ae, "test0");
archive_entry_set_mtime(ae, 123456, 7890);
archive_entry_set_size(ae, 0);
- archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
+ assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
archive_entry_free(ae);
@@ -571,8 +571,8 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
assertEqualInt(0, n);
close(fd);
- /* Create directory d2 with default ACLs */
- assertMakeDir("d2", 0755);
+ /* Create nested directory d2 with default ACLs */
+ assertMakeDir("d/d2", 0755);
#if HAVE_SUN_ACL
acl3_text = "user::rwx,"
@@ -604,10 +604,10 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
#if HAVE_SUN_ACL
func = "acl_set()";
- n = acl_set("d2", acl3);
+ n = acl_set("d/d2", acl3);
#else
func = "acl_set_file()";
- n = acl_set_file("d2", ACL_TYPE_DEFAULT, acl3);
+ n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3);
#endif
acl_free(acl3);
@@ -640,7 +640,7 @@ DEFINE_TEST(test_acl_platform_posix1e_read)
acl_text = archive_entry_acl_to_text(ae, NULL, flags);
assertEqualString(acl_text, acl2_text);
free(acl_text);
- } else if (strcmp(archive_entry_pathname(ae), "./d2") == 0) {
+ } else if (strcmp(archive_entry_pathname(ae), "./d/d2") == 0) {
acl_text = archive_entry_acl_to_text(ae, NULL, dflags);
assertEqualString(acl_text, acl3_text);
free(acl_text);
diff --git a/libarchive/test/test_acl_posix1e.c b/libarchive/test/test_acl_posix1e.c
index 01167dae20b0..fa2628dbe794 100644
--- a/libarchive/test/test_acl_posix1e.c
+++ b/libarchive/test/test_acl_posix1e.c
@@ -116,16 +116,15 @@ DEFINE_TEST(test_acl_posix1e)
* triggering unnecessary extensions. It's better to identify
* trivial ACLs at the point they are being read from disk.
*/
- archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
+ assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
-
/* With any extended ACL entry, we should read back a full set. */
- archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
+ assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
failure("One extended ACL should flag all ACLs to be returned.");
/* Check that entry contains only POSIX.1e types */
@@ -135,7 +134,7 @@ DEFINE_TEST(test_acl_posix1e)
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0);
assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
@@ -143,9 +142,9 @@ DEFINE_TEST(test_acl_posix1e)
/* A more extensive set of ACLs. */
- archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
+ assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
+ assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
@@ -155,7 +154,7 @@ DEFINE_TEST(test_acl_posix1e)
* Check that clearing ACLs gets rid of them all by repeating
* the first test.
*/
- archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
+ assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
@@ -166,7 +165,7 @@ DEFINE_TEST(test_acl_posix1e)
* Different types of malformed ACL entries that should
* fail when added to existing POSIX.1e ACLs.
*/
- archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
+ assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
for (i = 0; i < (int)(sizeof(acls_nfs4)/sizeof(acls_nfs4[0])); ++i) {
struct archive_test_acl_t *p = &acls_nfs4[i];
failure("Malformed ACL test #%d", i);
diff --git a/libarchive/test/test_acl_text.c b/libarchive/test/test_acl_text.c
index f3d2b10edcfe..80728932cb54 100644
--- a/libarchive/test/test_acl_text.c
+++ b/libarchive/test/test_acl_text.c
@@ -282,7 +282,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[5],
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
@@ -291,7 +291,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[7],
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
@@ -303,7 +303,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
@@ -314,7 +314,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
@@ -324,7 +324,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[7],
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0);
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
@@ -334,7 +334,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0);
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
@@ -344,7 +344,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[1],
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
@@ -355,7 +355,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
@@ -365,7 +365,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[2],
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
@@ -376,7 +376,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
@@ -386,7 +386,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[10],
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
@@ -398,7 +398,7 @@ DEFINE_TEST(test_acl_from_text)
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
@@ -416,7 +416,7 @@ DEFINE_TEST(test_acl_to_text)
assert((ae = archive_entry_new()) != NULL);
/* Write POSIX.1e ACLs */
- archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
+ assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
/* No flags should give output like getfacl(1) on linux */
compare_acl_text(ae, 0, acltext[0]);
@@ -457,7 +457,7 @@ DEFINE_TEST(test_acl_to_text)
ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT, acltext[8]);
/* Write NFSv4 ACLs */
- archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
+ assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
/* NFSv4 ACLs like getfacl(1) on FreeBSD */
compare_acl_text(ae, 0, acltext[9]);
diff --git a/libarchive/test/test_archive_api_feature.c b/libarchive/test/test_archive_api_feature.c
index d551e6a01ebc..60773ad04e54 100644
--- a/libarchive/test/test_archive_api_feature.c
+++ b/libarchive/test/test_archive_api_feature.c
@@ -42,8 +42,12 @@ DEFINE_TEST(test_archive_api_feature)
if (strlen(buff) < strlen(archive_version_string())) {
p = archive_version_string() + strlen(buff);
failure("Version string is: %s", archive_version_string());
- assert(*p == 'a' || *p == 'b' || *p == 'c' || *p == 'd');
- ++p;
+ if (p[0] == 'd'&& p[1] == 'e' && p[2] == 'v')
+ p += 3;
+ else {
+ assert(*p == 'a' || *p == 'b' || *p == 'c' || *p == 'd');
+ ++p;
+ }
failure("Version string is: %s", archive_version_string());
assert(*p == '\0');
}
diff --git a/libarchive/test/test_compat_solaris_tar_acl.c b/libarchive/test/test_compat_solaris_tar_acl.c
index 3d063c1db9e6..815977290670 100644
--- a/libarchive/test/test_compat_solaris_tar_acl.c
+++ b/libarchive/test/test_compat_solaris_tar_acl.c
@@ -227,7 +227,7 @@ DEFINE_TEST(test_compat_solaris_tar_acl)
failure("One extended ACL should flag all ACLs to be returned.");
assertEqualInt(7, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0644);
failure("Basic ACLs should set mode to 0644, not %04o",
archive_entry_mode(ae)&0777);
@@ -237,28 +237,28 @@ DEFINE_TEST(test_compat_solaris_tar_acl)
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0750);
failure("Basic ACLs should set mode to 0750, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0750);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
- archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
+ assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0750);
/* Third item has NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
+ assertEntryCompareAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Fourth item has NFS4 ACLs and inheritance flags */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls4, sizeof(acls4)/sizeof(acls0[4]),
+ assertEntryCompareAcls(ae, acls4, sizeof(acls4)/sizeof(acls0[4]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Close the archive. */
diff --git a/libarchive/test/test_compat_star_acl.c b/libarchive/test/test_compat_star_acl.c
index f2a78b2d2ce4..824710194c18 100644
--- a/libarchive/test/test_compat_star_acl.c
+++ b/libarchive/test/test_compat_star_acl.c
@@ -249,7 +249,7 @@ DEFINE_TEST(test_compat_star_acl_posix1e)
failure("One extended ACL should flag all ACLs to be returned.");
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
+ assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
@@ -259,7 +259,7 @@ DEFINE_TEST(test_compat_star_acl_posix1e)
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(7, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
- archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
+ assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
@@ -269,7 +269,7 @@ DEFINE_TEST(test_compat_star_acl_posix1e)
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
- archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
+ assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
@@ -298,21 +298,21 @@ DEFINE_TEST(test_compat_star_acl_nfs4)
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(3, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ALLOW));
- archive_test_compare_acls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
+ assertEntryCompareAcls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0);
/* Second item has has fine-grained NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls4, sizeof(acls4)/sizeof(acls0[4]),
+ assertEntryCompareAcls(ae, acls4, sizeof(acls4)/sizeof(acls0[4]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Third item has file and directory inheritance NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
- archive_test_compare_acls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]),
+ assertEntryCompareAcls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Close the archive. */
diff --git a/libarchive/test/test_fuzz.c b/libarchive/test/test_fuzz.c
index 71bf3ffb9b4b..ce7b8663faea 100644
--- a/libarchive/test/test_fuzz.c
+++ b/libarchive/test/test_fuzz.c
@@ -110,8 +110,9 @@ test_fuzz(const struct files *filesets)
} 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 bd36c396a1af..43d7d86bab24 100644
--- a/libarchive/test/test_read_disk.c
+++ b/libarchive/test/test_read_disk.c
@@ -61,6 +61,7 @@ uname_lookup(void *d, int64_t u)
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 @@ static const char *zero_groups[] = {
"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 @@ DEFINE_TEST(test_read_disk)
/* 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 c9aca8fa985d..fdbfbec91e93 100644
--- a/libarchive/test/test_read_disk_directory_traversals.c
+++ b/libarchive/test/test_read_disk_directory_traversals.c
@@ -1228,8 +1228,8 @@ test_restore_atime(void)
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");
@@ -1460,7 +1460,7 @@ test_nodump(void)
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 @@ test_nodump(void)
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 9eadaaf885b1..b60f09c5fb27 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 24, 2017
.Dt TAR 1
.Os
.Sh NAME
@@ -124,7 +125,7 @@ Unless specifically stated otherwise, options are applicable in
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 @@ and gzip compression,
.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 @@ options and before extracting any files.
(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 @@ On create, this sets the group name that will be stored
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 @@ Synonym for
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 @@ later copies will not overwrite earlier copies.
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 @@ In extract or list modes, this option is ignored.
(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 @@ This is often used to read filenames output by the
.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.
@@ -401,7 +450,21 @@ This is the reverse of
.Fl p
and the default behavior if
.Nm
-is run as non-root.
+is run as non-root and can be overridden by also specifying
+.Fl Fl acls ,
+.Fl Fl fflags ,
+.Fl Fl mac-metadata,
+.Fl Fl same-owner ,
+.Fl Fl same-permissions
+and
+.Fl Fl xattrs .
+.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 +646,18 @@ This option suppresses these behaviors.
.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 atributes and extended file flags, if available, for each item
+extracted from the archive. This is the default, if
.Nm
is being run by root and can be overridden by also specifying
-.Fl Fl no-same-owner
+.Fl Fl no-acls ,
+.Fl Fl no-fflags ,
+.Fl Fl no-mac-metadata,
+.Fl Fl no-same-owner ,
+.Fl Fl no-same-permissions
and
-.Fl Fl no-same-permissions .
+.Fl Fl no-xattrs .
.It Fl Fl passphrase Ar passphrase
The
.Pa passphrase
@@ -692,7 +759,7 @@ you probably want to use
.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 +821,13 @@ Read a list of exclusion patterns from the specified file.
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 93bf60a94da8..a9252a5c7c26 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -137,7 +137,6 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
#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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
"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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 4b84ba18ab46..ee9c6485fccc 100644
--- a/tar/bsdtar.h
+++ b/tar/bsdtar.h
@@ -50,6 +50,7 @@ struct bsdtar {
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 @@ struct bsdtar {
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 @@ struct bsdtar {
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 @@ enum {
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 @@ enum {
OPTION_UNAME,
OPTION_USE_COMPRESS_PROGRAM,
OPTION_UUENCODE,
- OPTION_VERSION
+ OPTION_VERSION,
+ OPTION_XATTRS
};
int bsdtar_getopt(struct bsdtar *);
diff --git a/tar/cmdline.c b/tar/cmdline.c
index c87741cc565e..e36c545b3336 100644
--- a/tar/cmdline.c
+++ b/tar/cmdline.c
@@ -65,6 +65,7 @@ static const struct bsdtar_option {
} 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 @@ static const struct bsdtar_option {
{ "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 @@ static const struct bsdtar_option {
{ "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 @@ static const struct bsdtar_option {
{ "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 @@ static const struct bsdtar_option {
{ "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 3c6cb0c13c39..658c810f9c59 100644
--- a/tar/read.c
+++ b/tar/read.c
@@ -105,7 +105,7 @@ tar_mode_x(struct bsdtar *bsdtar)
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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
}
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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
&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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
}
#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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
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 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
/* 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 0d2da365087d..3dd36019eed4 100644
--- a/tar/test/CMakeLists.txt
+++ b/tar/test/CMakeLists.txt
@@ -6,7 +6,7 @@
IF(ENABLE_TAR AND ENABLE_TEST)
SET(bsdtar_test_SOURCES
../../test_utils/test_utils.c
- main.c
+ ../../test_utils/test_main.c
test.h
test_0.c
test_basic.c
@@ -96,6 +96,7 @@ IF(ENABLE_TAR AND ENABLE_TEST)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
+ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/tar/test)
# Experimental new test handling
ADD_CUSTOM_TARGET(run_bsdtar_test
diff --git a/tar/test/main.c b/tar/test/main.c
deleted file mode 100644
index 8d31706f0d63..000000000000
--- a/tar/test/main.c
+++ /dev/null
@@ -1,3072 +0,0 @@
-/*
- * Copyright (c) 2003-2009 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 "test.h"
-#include "test_utils.h"
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_ICONV_H
-#include <iconv.h>
-#endif
-/*
- * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
- * As the include guards don't agree, the order of include is important.
- */
-#ifdef HAVE_LINUX_EXT2_FS_H
-#include <linux/ext2_fs.h> /* for Linux file flags */
-#endif
-#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
-#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
-#endif
-#include <limits.h>
-#include <locale.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <stdarg.h>
-#include <time.h>
-
-/*
- * This same file is used pretty much verbatim for all test harnesses.
- *
- * The next few lines are the only differences.
- * TODO: Move this into a separate configuration header, have all test
- * suites share one copy of this file.
- */
-__FBSDID("$FreeBSD: src/usr.bin/tar/test/main.c,v 1.6 2008/11/05 06:40:53 kientzle Exp $");
-#define KNOWNREF "test_patterns_2.tar.uu"
-#define ENVBASE "BSDTAR" /* Prefix for environment variables. */
-#define PROGRAM "bsdtar" /* Name of program being tested. */
-#define PROGRAM_ALIAS "tar" /* Generic alias for program */
-#undef LIBRARY /* Not testing a library. */
-#undef EXTRA_DUMP /* How to dump extra data */
-#undef EXTRA_ERRNO /* How to dump errno */
-/* How to generate extra version info. */
-#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
-
-/*
- *
- * Windows support routines
- *
- * Note: Configuration is a tricky issue. Using HAVE_* feature macros
- * in the test harness is dangerous because they cover up
- * configuration errors. The classic example of this is omitting a
- * configure check. If libarchive and libarchive_test both look for
- * the same feature macro, such errors are hard to detect. Platform
- * macros (e.g., _WIN32 or __GNUC__) are a little better, but can
- * easily lead to very messy code. It's best to limit yourself
- * to only the most generic programming techniques in the test harness
- * and thus avoid conditionals altogether. Where that's not possible,
- * try to minimize conditionals by grouping platform-specific tests in
- * one place (e.g., test_acl_freebsd) or by adding new assert()
- * functions (e.g., assertMakeHardlink()) to cover up platform
- * differences. Platform-specific coding in libarchive_test is often
- * a symptom that some capability is missing from libarchive itself.
- */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
-#include <direct.h>
-#include <windows.h>
-#ifndef F_OK
-#define F_OK (0)
-#endif
-#ifndef S_ISDIR
-#define S_ISDIR(m) ((m) & _S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(m) ((m) & _S_IFREG)
-#endif
-#if !defined(__BORLANDC__)
-#define access _access
-#undef chdir
-#define chdir _chdir
-#endif
-#ifndef fileno
-#define fileno _fileno
-#endif
-/*#define fstat _fstat64*/
-#if !defined(__BORLANDC__)
-#define getcwd _getcwd
-#endif
-#define lstat stat
-/*#define lstat _stat64*/
-/*#define stat _stat64*/
-#define rmdir _rmdir
-#if !defined(__BORLANDC__)
-#define strdup _strdup
-#define umask _umask
-#endif
-#define int64_t __int64
-#endif
-
-#if defined(HAVE__CrtSetReportMode)
-# include <crtdbg.h>
-#endif
-
-mode_t umasked(mode_t expected_mode)
-{
- mode_t mode = umask(0);
- umask(mode);
- return expected_mode & ~mode;
-}
-
-/* Path to working directory for current test */
-const char *testworkdir;
-#ifdef PROGRAM
-/* Pathname of exe to be tested. */
-const char *testprogfile;
-/* Name of exe to use in printf-formatted command strings. */
-/* On Windows, this includes leading/trailing quotes. */
-const char *testprog;
-#endif
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static void *GetFunctionKernel32(const char *);
-static int my_CreateSymbolicLinkA(const char *, const char *, int);
-static int my_CreateHardLinkA(const char *, const char *);
-static int my_GetFileInformationByName(const char *,
- BY_HANDLE_FILE_INFORMATION *);
-
-static void *
-GetFunctionKernel32(const char *name)
-{
- static HINSTANCE lib;
- static int set;
- if (!set) {
- set = 1;
- lib = LoadLibrary("kernel32.dll");
- }
- if (lib == NULL) {
- fprintf(stderr, "Can't load kernel32.dll?!\n");
- exit(1);
- }
- return (void *)GetProcAddress(lib, name);
-}
-
-static int
-my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateSymbolicLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, flags);
-}
-
-static int
-my_CreateHardLinkA(const char *linkname, const char *target)
-{
- static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
- static int set;
- if (!set) {
- set = 1;
- f = GetFunctionKernel32("CreateHardLinkA");
- }
- return f == NULL ? 0 : (*f)(linkname, target, NULL);
-}
-
-static int
-my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
-{
- HANDLE h;
- int r;
-
- memset(bhfi, 0, sizeof(*bhfi));
- h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE)
- return (0);
- r = GetFileInformationByHandle(h, bhfi);
- CloseHandle(h);
- return (r);
-}
-#endif
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
-static void
-invalid_parameter_handler(const wchar_t * expression,
- const wchar_t * function, const wchar_t * file,
- unsigned int line, uintptr_t pReserved)
-{
- /* nop */
-}
-#endif
-
-/*
- *
- * OPTIONS FLAGS
- *
- */
-
-/* Enable core dump on failure. */
-static int dump_on_failure = 0;
-/* Default is to remove temp dirs and log data for successful tests. */
-static int keep_temp_files = 0;
-/* Default is to run the specified tests once and report errors. */
-static int until_failure = 0;
-/* Default is to just report pass/fail for each test. */
-static int verbosity = 0;
-#define VERBOSITY_SUMMARY_ONLY -1 /* -q */
-#define VERBOSITY_PASSFAIL 0 /* Default */
-#define VERBOSITY_LIGHT_REPORT 1 /* -v */
-#define VERBOSITY_FULL 2 /* -vv */
-/* A few places generate even more output for verbosity > VERBOSITY_FULL,
- * mostly for debugging the test harness itself. */
-/* Cumulative count of assertion failures. */
-static int failures = 0;
-/* Cumulative count of reported skips. */
-static int skips = 0;
-/* Cumulative count of assertions checked. */
-static int assertions = 0;
-
-/* Directory where uuencoded reference files can be found. */
-static const char *refdir;
-
-/*
- * Report log information selectively to console and/or disk log.
- */
-static int log_console = 0;
-static FILE *logfile;
-static void
-vlogprintf(const char *fmt, va_list ap)
-{
-#ifdef va_copy
- va_list lfap;
- va_copy(lfap, ap);
-#endif
- if (log_console)
- vfprintf(stdout, fmt, ap);
- if (logfile != NULL)
-#ifdef va_copy
- vfprintf(logfile, fmt, lfap);
- va_end(lfap);
-#else
- vfprintf(logfile, fmt, ap);
-#endif
-}
-
-static void
-logprintf(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogprintf(fmt, ap);
- va_end(ap);
-}
-
-/* Set up a message to display only if next assertion fails. */
-static char msgbuff[4096];
-static const char *msg, *nextmsg;
-void
-failure(const char *fmt, ...)
-{
- va_list ap;
- if (fmt == NULL) {
- nextmsg = NULL;
- } else {
- va_start(ap, fmt);
- vsprintf(msgbuff, fmt, ap);
- va_end(ap);
- nextmsg = msgbuff;
- }
-}
-
-/*
- * Copy arguments into file-local variables.
- * This was added to permit vararg assert() functions without needing
- * variadic wrapper macros. Turns out that the vararg capability is almost
- * never used, so almost all of the vararg assertions can be simplified
- * by removing the vararg capability and reworking the wrapper macro to
- * pass __FILE__, __LINE__ directly into the function instead of using
- * this hook. I suspect this machinery is used so rarely that we
- * would be better off just removing it entirely. That would simplify
- * the code here noticeably.
- */
-static const char *skipping_filename;
-static int skipping_line;
-void skipping_setup(const char *filename, int line)
-{
- skipping_filename = filename;
- skipping_line = line;
-}
-
-/* Called at the beginning of each assert() function. */
-static void
-assertion_count(const char *file, int line)
-{
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- ++assertions;
- /* Proper handling of "failure()" message. */
- msg = nextmsg;
- nextmsg = NULL;
- /* Uncomment to print file:line after every assertion.
- * Verbose, but occasionally useful in tracking down crashes. */
- /* printf("Checked %s:%d\n", file, line); */
-}
-
-/*
- * For each test source file, we remember how many times each
- * assertion was reported. Cleared before each new test,
- * used by test_summarize().
- */
-static struct line {
- int count;
- int skip;
-} failed_lines[10000];
-const char *failed_filename;
-
-/* Count this failure, setup up log destination and handle initial report. */
-static void
-failure_start(const char *filename, int line, const char *fmt, ...)
-{
- va_list ap;
-
- /* Record another failure for this line. */
- ++failures;
- failed_filename = filename;
- failed_lines[line].count++;
-
- /* Determine whether to log header to console. */
- switch (verbosity) {
- case VERBOSITY_LIGHT_REPORT:
- log_console = (failed_lines[line].count < 2);
- break;
- default:
- log_console = (verbosity >= VERBOSITY_FULL);
- }
-
- /* Log file:line header for this failure */
- va_start(ap, fmt);
-#if _MSC_VER
- logprintf("%s(%d): ", filename, line);
-#else
- logprintf("%s:%d: ", filename, line);
-#endif
- vlogprintf(fmt, ap);
- va_end(ap);
- logprintf("\n");
-
- if (msg != NULL && msg[0] != '\0') {
- logprintf(" Description: %s\n", msg);
- msg = NULL;
- }
-
- /* Determine whether to log details to console. */
- if (verbosity == VERBOSITY_LIGHT_REPORT)
- log_console = 0;
-}
-
-/* Complete reporting of failed tests. */
-/*
- * The 'extra' hook here is used by libarchive to include libarchive
- * error messages with assertion failures. It could also be used
- * to add strerror() output, for example. Just define the EXTRA_DUMP()
- * macro appropriately.
- */
-static void
-failure_finish(void *extra)
-{
- (void)extra; /* UNUSED (maybe) */
-#ifdef EXTRA_DUMP
- if (extra != NULL) {
- logprintf(" errno: %d\n", EXTRA_ERRNO(extra));
- logprintf(" detail: %s\n", EXTRA_DUMP(extra));
- }
-#endif
-
- if (dump_on_failure) {
- fprintf(stderr,
- " *** forcing core dump so failure can be debugged ***\n");
- abort();
- }
-}
-
-/* Inform user that we're skipping some checks. */
-void
-test_skipping(const char *fmt, ...)
-{
- char buff[1024];
- va_list ap;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- va_end(ap);
- /* Use failure() message if set. */
- msg = nextmsg;
- nextmsg = NULL;
- /* failure_start() isn't quite right, but is awfully convenient. */
- failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff);
- --failures; /* Undo failures++ in failure_start() */
- /* Don't failure_finish() here. */
- /* Mark as skip, so doesn't count as failed test. */
- failed_lines[skipping_line].skip = 1;
- ++skips;
-}
-
-/*
- *
- * ASSERTIONS
- *
- */
-
-/* Generic assert() just displays the failed condition. */
-int
-assertion_assert(const char *file, int line, int value,
- const char *condition, void *extra)
-{
- assertion_count(file, line);
- if (!value) {
- failure_start(file, line, "Assertion failed: %s", condition);
- failure_finish(extra);
- }
- return (value);
-}
-
-/* chdir() and report any errors */
-int
-assertion_chdir(const char *file, int line, const char *pathname)
-{
- assertion_count(file, line);
- if (chdir(pathname) == 0)
- return (1);
- failure_start(file, line, "chdir(\"%s\")", pathname);
- failure_finish(NULL);
- return (0);
-
-}
-
-/* Verify two integers are equal. */
-int
-assertion_equal_int(const char *file, int line,
- long long v1, const char *e1, long long v2, const char *e2, void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1);
- logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Utility to convert a single UTF-8 sequence.
- */
-static int
-_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
-{
- static const char utf8_count[256] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */
- 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */
- 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
- };
- int ch;
- int cnt;
- uint32_t wc;
-
- *pwc = 0;
-
- /* Sanity check. */
- if (n == 0)
- return (0);
- /*
- * Decode 1-4 bytes depending on the value of the first byte.
- */
- ch = (unsigned char)*s;
- if (ch == 0)
- return (0); /* Standard: return 0 for end-of-string. */
- cnt = utf8_count[ch];
-
- /* Invalid sequence or there are not plenty bytes. */
- if (n < (size_t)cnt)
- return (-1);
-
- /* Make a Unicode code point from a single UTF-8 sequence. */
- switch (cnt) {
- case 1: /* 1 byte sequence. */
- *pwc = ch & 0x7f;
- return (cnt);
- case 2: /* 2 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
- return (cnt);
- case 3: /* 3 bytes sequence. */
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x0f) << 12)
- | ((s[1] & 0x3f) << 6)
- | (s[2] & 0x3f);
- if (wc < 0x800)
- return (-1);/* Overlong sequence. */
- break;
- case 4: /* 4 bytes sequence. */
- if (n < 4)
- return (-1);
- if ((s[1] & 0xc0) != 0x80) return (-1);
- if ((s[2] & 0xc0) != 0x80) return (-1);
- if ((s[3] & 0xc0) != 0x80) return (-1);
- wc = ((ch & 0x07) << 18)
- | ((s[1] & 0x3f) << 12)
- | ((s[2] & 0x3f) << 6)
- | (s[3] & 0x3f);
- if (wc < 0x10000)
- return (-1);/* Overlong sequence. */
- break;
- default:
- return (-1);
- }
-
- /* The code point larger than 0x10FFFF is not legal
- * Unicode values. */
- if (wc > 0x10FFFF)
- return (-1);
- /* Correctly gets a Unicode, returns used bytes. */
- *pwc = wc;
- return (cnt);
-}
-
-static void strdump(const char *e, const char *p, int ewidth, int utf8)
-{
- const char *q = p;
-
- logprintf(" %*s = ", ewidth, e);
- if (p == NULL) {
- logprintf("NULL\n");
- return;
- }
- logprintf("\"");
- while (*p != '\0') {
- unsigned int c = 0xff & *p++;
- switch (c) {
- case '\a': logprintf("\\a"); break;
- case '\b': logprintf("\\b"); break;
- case '\n': logprintf("\\n"); break;
- case '\r': logprintf("\\r"); break;
- default:
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else
- logprintf("\\x%02X", c);
- }
- }
- logprintf("\"");
- logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q));
-
- /*
- * If the current string is UTF-8, dump its code points.
- */
- if (utf8) {
- size_t len;
- uint32_t uc;
- int n;
- int cnt = 0;
-
- p = q;
- len = strlen(p);
- logprintf(" [");
- while ((n = _utf8_to_unicode(&uc, p, len)) > 0) {
- if (p != q)
- logprintf(" ");
- logprintf("%04X", uc);
- p += n;
- len -= n;
- cnt++;
- }
- logprintf("]");
- logprintf(" (count %d", cnt);
- if (n < 0) {
- logprintf(",unknown %d bytes", len);
- }
- logprintf(")");
-
- }
- logprintf("\n");
-}
-
-/* Verify two strings are equal, dump them if not. */
-int
-assertion_equal_string(const char *file, int line,
- const char *v1, const char *e1,
- const char *v2, const char *e2,
- void *extra, int utf8)
-{
- int l1, l2;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- l1 = (int)strlen(e1);
- l2 = (int)strlen(e2);
- if (l1 < l2)
- l1 = l2;
- strdump(e1, v1, l1, utf8);
- strdump(e2, v2, l1, utf8);
- failure_finish(extra);
- return (0);
-}
-
-static void
-wcsdump(const char *e, const wchar_t *w)
-{
- logprintf(" %s = ", e);
- if (w == NULL) {
- logprintf("(null)");
- return;
- }
- logprintf("\"");
- while (*w != L'\0') {
- unsigned int c = *w++;
- if (c >= 32 && c < 127)
- logprintf("%c", c);
- else if (c < 256)
- logprintf("\\x%02X", c);
- else if (c < 0x10000)
- logprintf("\\u%04X", c);
- else
- logprintf("\\U%08X", c);
- }
- logprintf("\"\n");
-}
-
-#ifndef HAVE_WCSCMP
-static int
-wcscmp(const wchar_t *s1, const wchar_t *s2)
-{
-
- while (*s1 == *s2++) {
- if (*s1++ == L'\0')
- return 0;
- }
- if (*s1 > *--s2)
- return 1;
- else
- return -1;
-}
-#endif
-
-/* Verify that two wide strings are equal, dump them if not. */
-int
-assertion_equal_wstring(const char *file, int line,
- const wchar_t *v1, const char *e1,
- const wchar_t *v2, const char *e2,
- void *extra)
-{
- assertion_count(file, line);
- if (v1 == v2)
- return (1);
- if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0)
- return (1);
- failure_start(file, line, "%s != %s", e1, e2);
- wcsdump(e1, v1);
- wcsdump(e2, v2);
- failure_finish(extra);
- return (0);
-}
-
-/*
- * Pretty standard hexdump routine. As a bonus, if ref != NULL, then
- * any bytes in p that differ from ref will be highlighted with '_'
- * before and after the hex value.
- */
-static void
-hexdump(const char *p, const char *ref, size_t l, size_t offset)
-{
- size_t i, j;
- char sep;
-
- if (p == NULL) {
- logprintf("(null)\n");
- return;
- }
- for(i=0; i < l; i+=16) {
- logprintf("%04x", (unsigned)(i + offset));
- sep = ' ';
- for (j = 0; j < 16 && i + j < l; j++) {
- if (ref != NULL && p[i + j] != ref[i + j])
- sep = '_';
- logprintf("%c%02x", sep, 0xff & (int)p[i+j]);
- if (ref != NULL && p[i + j] == ref[i + j])
- sep = ' ';
- }
- for (; j < 16; j++) {
- logprintf("%c ", sep);
- sep = ' ';
- }
- logprintf("%c", sep);
- for (j=0; j < 16 && i + j < l; j++) {
- int c = p[i + j];
- if (c >= ' ' && c <= 126)
- logprintf("%c", c);
- else
- logprintf(".");
- }
- logprintf("\n");
- }
-}
-
-/* Verify that two blocks of memory are the same, display the first
- * block of differences if they're not. */
-int
-assertion_equal_mem(const char *file, int line,
- const void *_v1, const char *e1,
- const void *_v2, const char *e2,
- size_t l, const char *ld, void *extra)
-{
- const char *v1 = (const char *)_v1;
- const char *v2 = (const char *)_v2;
- size_t offset;
-
- assertion_count(file, line);
- if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0))
- return (1);
- if (v1 == NULL || v2 == NULL)
- return (0);
-
- failure_start(file, line, "%s != %s", e1, e2);
- logprintf(" size %s = %d\n", ld, (int)l);
- /* Dump 48 bytes (3 lines) so that the first difference is
- * in the second line. */
- offset = 0;
- while (l > 64 && memcmp(v1, v2, 32) == 0) {
- /* Two lines agree, so step forward one line. */
- v1 += 16;
- v2 += 16;
- l -= 16;
- offset += 16;
- }
- logprintf(" Dump of %s\n", e1);
- hexdump(v1, v2, l < 128 ? l : 128, offset);
- logprintf(" Dump of %s\n", e2);
- hexdump(v2, v1, l < 128 ? l : 128, offset);
- logprintf("\n");
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that a block of memory is filled with the specified byte. */
-int
-assertion_memory_filled_with(const char *file, int line,
- const void *_v1, const char *vd,
- size_t l, const char *ld,
- char b, const char *bd, void *extra)
-{
- const char *v1 = (const char *)_v1;
- size_t c = 0;
- size_t i;
- (void)ld; /* UNUSED */
-
- assertion_count(file, line);
-
- for (i = 0; i < l; ++i) {
- if (v1[i] == b) {
- ++c;
- }
- }
- if (c == l)
- return (1);
-
- failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
- logprintf(" Only %d bytes were correct\n", (int)c);
- failure_finish(extra);
- return (0);
-}
-
-/* Verify that the named file exists and is empty. */
-int
-assertion_empty_file(const char *filename, int line, const char *f1)
-{
- char buff[1024];
- struct stat st;
- ssize_t s;
- FILE *f;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0)
- return (1);
-
- failure_start(filename, line, "File should be empty: %s", f1);
- logprintf(" File size: %d\n", (int)st.st_size);
- logprintf(" Contents:\n");
- f = fopen(f1, "rb");
- if (f == NULL) {
- logprintf(" Unable to open %s\n", f1);
- } else {
- s = ((off_t)sizeof(buff) < st.st_size) ?
- (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
- s = fread(buff, 1, s, f);
- hexdump(buff, NULL, s, 0);
- fclose(f);
- }
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file exists and is not empty. */
-int
-assertion_non_empty_file(const char *filename, int line, const char *f1)
-{
- struct stat st;
-
- assertion_count(filename, line);
-
- if (stat(f1, &st) != 0) {
- failure_start(filename, line, "Stat failed: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- if (st.st_size == 0) {
- failure_start(filename, line, "File empty: %s", f1);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify that two files have the same contents. */
-/* TODO: hexdump the first bytes that actually differ. */
-int
-assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2)
-{
- char buff1[1024];
- char buff2[1024];
- FILE *f1, *f2;
- int n1, n2;
-
- assertion_count(filename, line);
-
- f1 = fopen(fn1, "rb");
- f2 = fopen(fn2, "rb");
- if (f1 == NULL || f2 == NULL) {
- if (f1) fclose(f1);
- if (f2) fclose(f2);
- return (0);
- }
- for (;;) {
- n1 = (int)fread(buff1, 1, sizeof(buff1), f1);
- n2 = (int)fread(buff2, 1, sizeof(buff2), f2);
- if (n1 != n2)
- break;
- if (n1 == 0 && n2 == 0) {
- fclose(f1);
- fclose(f2);
- return (1);
- }
- if (memcmp(buff1, buff2, n1) != 0)
- break;
- }
- fclose(f1);
- fclose(f2);
- failure_start(filename, line, "Files not identical");
- logprintf(" file1=\"%s\"\n", fn1);
- logprintf(" file2=\"%s\"\n", fn2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file does exist. */
-int
-assertion_file_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (!_access(f, 0))
- return (1);
-#else
- if (!access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify that the named file doesn't exist. */
-int
-assertion_file_not_exists(const char *filename, int line, const char *f)
-{
- assertion_count(filename, line);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (_access(f, 0))
- return (1);
-#else
- if (access(f, F_OK))
- return (1);
-#endif
- failure_start(filename, line, "File should not exist: %s", f);
- failure_finish(NULL);
- return (0);
-}
-
-/* Compare the contents of a file to a block of memory. */
-int
-assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn)
-{
- char *contents;
- FILE *f;
- int n;
-
- assertion_count(filename, line);
-
- f = fopen(fn, "rb");
- if (f == NULL) {
- failure_start(filename, line,
- "File should exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- contents = malloc(s * 2);
- n = (int)fread(contents, 1, s * 2, f);
- fclose(f);
- if (n == s && memcmp(buff, contents, s) == 0) {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "File contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0)
- hexdump(contents, buff, n > 512 ? 512 : n, 0);
- else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s > 512 ? 512 : s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Check the contents of a text file, being tolerant of line endings. */
-int
-assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn)
-{
- char *contents;
- const char *btxt, *ftxt;
- FILE *f;
- int n, s;
-
- assertion_count(filename, line);
- f = fopen(fn, "r");
- if (f == NULL) {
- failure_start(filename, line,
- "File doesn't exist: %s", fn);
- failure_finish(NULL);
- return (0);
- }
- s = (int)strlen(buff);
- contents = malloc(s * 2 + 128);
- n = (int)fread(contents, 1, s * 2 + 128 - 1, f);
- if (n >= 0)
- contents[n] = '\0';
- fclose(f);
- /* Compare texts. */
- btxt = buff;
- ftxt = (const char *)contents;
- while (*btxt != '\0' && *ftxt != '\0') {
- if (*btxt == *ftxt) {
- ++btxt;
- ++ftxt;
- continue;
- }
- if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') {
- /* Pass over different new line characters. */
- ++btxt;
- ftxt += 2;
- continue;
- }
- break;
- }
- if (*btxt == '\0' && *ftxt == '\0') {
- free(contents);
- return (1);
- }
- failure_start(filename, line, "Contents don't match");
- logprintf(" file=\"%s\"\n", fn);
- if (n > 0) {
- hexdump(contents, buff, n, 0);
- logprintf(" expected\n", fn);
- hexdump(buff, contents, s, 0);
- } else {
- logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s, 0);
- }
- failure_finish(NULL);
- free(contents);
- return (0);
-}
-
-/* Verify that a text file contains the specified lines, regardless of order */
-/* This could be more efficient if we sorted both sets of lines, etc, but
- * since this is used only for testing and only ever deals with a dozen or so
- * lines at a time, this relatively crude approach is just fine. */
-int
-assertion_file_contains_lines_any_order(const char *file, int line,
- const char *pathname, const char *lines[])
-{
- char *buff;
- size_t buff_size;
- size_t expected_count, actual_count, i, j;
- char **expected = NULL;
- char *p, **actual = NULL;
- char c;
- int expected_failure = 0, actual_failure = 0, retval = 0;
-
- assertion_count(file, line);
-
- buff = slurpfile(&buff_size, "%s", pathname);
- if (buff == NULL) {
- failure_start(pathname, line, "Can't read file: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- /* Make a copy of the provided lines and count up the expected
- * file size. */
- for (i = 0; lines[i] != NULL; ++i) {
- }
- expected_count = i;
- if (expected_count) {
- expected = malloc(sizeof(char *) * expected_count);
- if (expected == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- goto done;
- }
- for (i = 0; lines[i] != NULL; ++i) {
- expected[i] = strdup(lines[i]);
- }
- }
-
- /* Break the file into lines */
- actual_count = 0;
- for (c = '\0', p = buff; p < buff + buff_size; ++p) {
- if (*p == '\x0d' || *p == '\x0a')
- *p = '\0';
- if (c == '\0' && *p != '\0')
- ++actual_count;
- c = *p;
- }
- if (actual_count) {
- actual = calloc(sizeof(char *), actual_count);
- if (actual == NULL) {
- failure_start(pathname, line, "Can't allocate memory");
- failure_finish(NULL);
- goto done;
- }
- for (j = 0, p = buff; p < buff + buff_size;
- p += 1 + strlen(p)) {
- if (*p != '\0') {
- actual[j] = p;
- ++j;
- }
- }
- }
-
- /* Erase matching lines from both lists */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] == NULL)
- continue;
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] == NULL)
- continue;
- if (strcmp(expected[i], actual[j]) == 0) {
- free(expected[i]);
- expected[i] = NULL;
- actual[j] = NULL;
- break;
- }
- }
- }
-
- /* If there's anything left, it's a failure */
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL)
- ++expected_failure;
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- ++actual_failure;
- }
- if (expected_failure == 0 && actual_failure == 0) {
- retval = 1;
- goto done;
- }
- failure_start(file, line, "File doesn't match: %s", pathname);
- for (i = 0; i < expected_count; ++i) {
- if (expected[i] != NULL)
- logprintf(" Expected but not present: %s\n", expected[i]);
- }
- for (j = 0; j < actual_count; ++j) {
- if (actual[j] != NULL)
- logprintf(" Present but not expected: %s\n", actual[j]);
- }
- failure_finish(NULL);
-done:
- free(actual);
- free(buff);
- for (i = 0; i < expected_count; ++i)
- free(expected[i]);
- free(expected);
-
- return (retval);
-}
-
-/* Verify that a text file does not contains the specified strings */
-int
-assertion_file_contains_no_invalid_strings(const char *file, int line,
- const char *pathname, const char *strings[])
-{
- char *buff;
- int i;
-
- buff = slurpfile(NULL, "%s", pathname);
- if (buff == NULL) {
- failure_start(file, line, "Can't read file: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- for (i = 0; strings[i] != NULL; ++i) {
- if (strstr(buff, strings[i]) != NULL) {
- failure_start(file, line, "Invalid string in %s: %s", pathname,
- strings[i]);
- failure_finish(NULL);
- free(buff);
- return(0);
- }
- }
-
- free(buff);
- return (0);
-}
-
-/* Test that two paths point to the same file. */
-/* As a side-effect, asserts that both files exist. */
-static int
-is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(path1, &bhfi1);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path1);
- failure_finish(NULL);
- return (0);
- }
- r = my_GetFileInformationByName(path2, &bhfi2);
- if (r == 0) {
- failure_start(file, line, "File %s can't be inspected?", path2);
- failure_finish(NULL);
- return (0);
- }
- return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber
- && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
- && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
-#else
- struct stat st1, st2;
- int r;
-
- assertion_count(file, line);
- r = lstat(path1, &st1);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path1);
- failure_finish(NULL);
- return (0);
- }
- r = lstat(path2, &st2);
- if (r != 0) {
- failure_start(file, line, "File should exist: %s", path2);
- failure_finish(NULL);
- return (0);
- }
- return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
-#endif
-}
-
-int
-assertion_is_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s are not hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-int
-assertion_is_not_hardlink(const char *file, int line,
- const char *path1, const char *path2)
-{
- if (!is_hardlink(file, line, path1, path2))
- return (1);
- failure_start(file, line,
- "Files %s and %s should not be hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify a/b/mtime of 'pathname'. */
-/* If 'recent', verify that it's within last 10 seconds. */
-static int
-assertion_file_time(const char *file, int line,
- const char *pathname, long t, long nsec, char type, int recent)
-{
- long long filet, filet_nsec;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME (116444736000000000ULL)
- FILETIME fxtime, fbirthtime, fatime, fmtime;
- ULARGE_INTEGER wintm;
- HANDLE h;
- fxtime.dwLowDateTime = 0;
- fxtime.dwHighDateTime = 0;
-
- assertion_count(file, line);
- /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
- * a directory file. If not, CreateFile() will fail when
- * the pathname is a directory. */
- h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = GetFileTime(h, &fbirthtime, &fatime, &fmtime);
- switch (type) {
- case 'a': fxtime = fatime; break;
- case 'b': fxtime = fbirthtime; break;
- case 'm': fxtime = fmtime; break;
- }
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't GetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- wintm.LowPart = fxtime.dwLowDateTime;
- wintm.HighPart = fxtime.dwHighDateTime;
- filet = (wintm.QuadPart - EPOC_TIME) / 10000000;
- filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100;
- nsec = (nsec / 100) * 100; /* Round the request */
-#else
- struct stat st;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- switch (type) {
- case 'a': filet = st.st_atime; break;
- case 'm': filet = st.st_mtime; break;
- case 'b': filet = 0; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
-#if defined(__FreeBSD__)
- switch (type) {
- case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
- case 'b': filet = st.st_birthtime;
- /* FreeBSD filesystems that don't support birthtime
- * (e.g., UFS1) always return -1 here. */
- if (filet == -1) {
- return (1);
- }
- filet_nsec = st.st_birthtimespec.tv_nsec; break;
- case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
- default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
- exit(1);
- }
- /* FreeBSD generally only stores to microsecond res, so round. */
- filet_nsec = (filet_nsec / 1000) * 1000;
- nsec = (nsec / 1000) * 1000;
-#else
- filet_nsec = nsec = 0; /* Generic POSIX only has whole seconds. */
- if (type == 'b') return (1); /* Generic POSIX doesn't have birthtime */
-#if defined(__HAIKU__)
- if (type == 'a') return (1); /* Haiku doesn't have atime. */
-#endif
-#endif
-#endif
- if (recent) {
- /* Check that requested time is up-to-date. */
- time_t now = time(NULL);
- if (filet < now - 10 || filet > now + 1) {
- failure_start(file, line,
- "File %s has %ctime %lld, %lld seconds ago\n",
- pathname, type, filet, now - filet);
- failure_finish(NULL);
- return (0);
- }
- } else if (filet != t || filet_nsec != nsec) {
- failure_start(file, line,
- "File %s has %ctime %lld.%09lld, expected %lld.%09lld",
- pathname, type, filet, filet_nsec, t, nsec);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-}
-
-/* Verify atime of 'pathname'. */
-int
-assertion_file_atime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'a', 0);
-}
-
-/* Verify atime of 'pathname' is up-to-date. */
-int
-assertion_file_atime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'a', 1);
-}
-
-/* Verify birthtime of 'pathname'. */
-int
-assertion_file_birthtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'b', 0);
-}
-
-/* Verify birthtime of 'pathname' is up-to-date. */
-int
-assertion_file_birthtime_recent(const char *file, int line,
- const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'b', 1);
-}
-
-/* Verify mode of 'pathname'. */
-int
-assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode)
-{
- int mode;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- failure_start(file, line, "assertFileMode not yet implemented for Windows");
- (void)mode; /* UNUSED */
- (void)r; /* UNUSED */
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- mode = (int)(st.st_mode & 0777);
- }
- if (r == 0 && mode == expected_mode)
- return (1);
- failure_start(file, line, "File %s has mode %o, expected %o",
- pathname, mode, expected_mode);
-#endif
- failure_finish(NULL);
- return (0);
-}
-
-/* Verify mtime of 'pathname'. */
-int
-assertion_file_mtime(const char *file, int line,
- const char *pathname, long t, long nsec)
-{
- return assertion_file_time(file, line, pathname, t, nsec, 'm', 0);
-}
-
-/* Verify mtime of 'pathname' is up-to-date. */
-int
-assertion_file_mtime_recent(const char *file, int line, const char *pathname)
-{
- return assertion_file_time(file, line, pathname, 0, 0, 'm', 1);
-}
-
-/* Verify number of links to 'pathname'. */
-int
-assertion_file_nlinks(const char *file, int line,
- const char *pathname, int nlinks)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- assertion_count(file, line);
- r = my_GetFileInformationByName(pathname, &bhfi);
- if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, bhfi.nNumberOfLinks, nlinks);
- failure_finish(NULL);
- return (0);
-#else
- struct stat st;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r == 0 && (int)st.st_nlink == nlinks)
- return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, st.st_nlink, nlinks);
- failure_finish(NULL);
- return (0);
-#endif
-}
-
-/* Verify size of 'pathname'. */
-int
-assertion_file_size(const char *file, int line, const char *pathname, long size)
-{
- int64_t filesize;
- int r;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- {
- BY_HANDLE_FILE_INFORMATION bhfi;
- r = !my_GetFileInformationByName(pathname, &bhfi);
- filesize = ((int64_t)bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow;
- }
-#else
- {
- struct stat st;
- r = lstat(pathname, &st);
- filesize = st.st_size;
- }
-#endif
- if (r == 0 && filesize == size)
- return (1);
- failure_start(file, line, "File %s has size %ld, expected %ld",
- pathname, (long)filesize, (long)size);
- failure_finish(NULL);
- return (0);
-}
-
-/* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */
-int
-assertion_is_dir(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line, "Dir should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISDIR(st.st_mode)) {
- failure_start(file, line, "%s is not a dir", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "Dir %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Verify that 'pathname' is a regular file. If 'mode' is >= 0,
- * verify that too. */
-int
-assertion_is_reg(const char *file, int line, const char *pathname, int mode)
-{
- struct stat st;
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
-#endif
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0 || !S_ISREG(st.st_mode)) {
- failure_start(file, line, "File should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Windows doesn't handle permissions the same way as POSIX,
- * so just ignore the mode tests. */
- /* TODO: Can we do better here? */
- if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
- failure_start(file, line, "File %s has wrong mode", pathname);
- logprintf(" Expected: 0%3o\n", mode);
- logprintf(" Found: 0%3o\n", st.st_mode & 07777);
- failure_finish(NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-/* Check whether 'pathname' is a symbolic link. If 'contents' is
- * non-NULL, verify that the symlink has those contents. */
-static int
-is_symlink(const char *file, int line,
- const char *pathname, const char *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)pathname; /* UNUSED */
- (void)contents; /* UNUSED */
- assertion_count(file, line);
- /* Windows sort-of has real symlinks, but they're only usable
- * by privileged users and are crippled even then, so there's
- * really not much point in bothering with this. */
- return (0);
-#else
- char buff[301];
- struct stat st;
- ssize_t linklen;
- int r;
-
- assertion_count(file, line);
- r = lstat(pathname, &st);
- if (r != 0) {
- failure_start(file, line,
- "Symlink should exist: %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- if (!S_ISLNK(st.st_mode))
- return (0);
- if (contents == NULL)
- return (1);
- linklen = readlink(pathname, buff, sizeof(buff) - 1);
- if (linklen < 0) {
- failure_start(file, line, "Can't read symlink %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- buff[linklen] = '\0';
- if (strcmp(buff, contents) != 0)
- return (0);
- return (1);
-#endif
-}
-
-/* Assert that path is a symlink that (optionally) contains contents. */
-int
-assertion_is_symlink(const char *file, int line,
- const char *path, const char *contents)
-{
- if (is_symlink(file, line, path, contents))
- return (1);
- if (contents)
- failure_start(file, line, "File %s is not a symlink to %s",
- path, contents);
- else
- failure_start(file, line, "File %s is not a symlink", path);
- failure_finish(NULL);
- return (0);
-}
-
-
-/* Create a directory and report any errors. */
-int
-assertion_make_dir(const char *file, int line, const char *dirname, int mode)
-{
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)mode; /* UNUSED */
- if (0 == _mkdir(dirname))
- return (1);
-#else
- if (0 == mkdir(dirname, mode)) {
- if (0 == chmod(dirname, mode)) {
- assertion_file_mode(file, line, dirname, mode);
- return (1);
- }
- }
-#endif
- failure_start(file, line, "Could not create directory %s", dirname);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a file with the specified contents and report any failures. */
-int
-assertion_make_file(const char *file, int line,
- const char *path, int mode, int csize, const void *contents)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* TODO: Rework this to set file mode as well. */
- FILE *f;
- (void)mode; /* UNUSED */
- assertion_count(file, line);
- f = fopen(path, "wb");
- if (f == NULL) {
- failure_start(file, line, "Could not create file %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (contents != NULL) {
- size_t wsize;
-
- if (csize < 0)
- wsize = strlen(contents);
- else
- wsize = (size_t)csize;
- if (wsize != fwrite(contents, 1, wsize, f)) {
- fclose(f);
- failure_start(file, line,
- "Could not write file %s", path);
- failure_finish(NULL);
- return (0);
- }
- }
- fclose(f);
- return (1);
-#else
- int fd;
- assertion_count(file, line);
- fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
- if (fd < 0) {
- failure_start(file, line, "Could not create %s", path);
- failure_finish(NULL);
- return (0);
- }
- if (0 != chmod(path, mode)) {
- failure_start(file, line, "Could not chmod %s", path);
- failure_finish(NULL);
- close(fd);
- return (0);
- }
- if (contents != NULL) {
- ssize_t wsize;
-
- if (csize < 0)
- wsize = (ssize_t)strlen(contents);
- else
- wsize = (ssize_t)csize;
- if (wsize != write(fd, contents, wsize)) {
- close(fd);
- failure_start(file, line,
- "Could not write to %s", path);
- failure_finish(NULL);
- close(fd);
- return (0);
- }
- }
- close(fd);
- assertion_file_mode(file, line, path, mode);
- return (1);
-#endif
-}
-
-/* Create a hardlink and report any failures. */
-int
-assertion_make_hardlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
- int succeeded;
-
- assertion_count(file, line);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- succeeded = my_CreateHardLinkA(newpath, linkto);
-#elif HAVE_LINK
- succeeded = !link(linkto, newpath);
-#else
- succeeded = 0;
-#endif
- if (succeeded)
- return (1);
- failure_start(file, line, "Could not create hardlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Create a symlink and report any failures. */
-int
-assertion_make_symlink(const char *file, int line,
- const char *newpath, const char *linkto)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- int targetIsDir = 0; /* TODO: Fix this */
- assertion_count(file, line);
- if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
- return (1);
-#elif HAVE_SYMLINK
- assertion_count(file, line);
- if (0 == symlink(linkto, newpath))
- return (1);
-#endif
- failure_start(file, line, "Could not create symlink");
- logprintf(" New link: %s\n", newpath);
- logprintf(" Old name: %s\n", linkto);
- failure_finish(NULL);
- return(0);
-}
-
-/* Set umask, report failures. */
-int
-assertion_umask(const char *file, int line, int mask)
-{
- assertion_count(file, line);
- (void)file; /* UNUSED */
- (void)line; /* UNUSED */
- umask(mask);
- return (1);
-}
-
-/* Set times, report failures. */
-int
-assertion_utimes(const char *file, int line,
- const char *pathname, long at, long at_nsec, long mt, long mt_nsec)
-{
- int r;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
- + (((nsec)/1000)*10))
- HANDLE h;
- ULARGE_INTEGER wintm;
- FILETIME fatime, fmtime;
- FILETIME *pat, *pmt;
-
- assertion_count(file, line);
- h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (at > 0 || at_nsec > 0) {
- wintm.QuadPart = WINTIME(at, at_nsec);
- fatime.dwLowDateTime = wintm.LowPart;
- fatime.dwHighDateTime = wintm.HighPart;
- pat = &fatime;
- } else
- pat = NULL;
- if (mt > 0 || mt_nsec > 0) {
- wintm.QuadPart = WINTIME(mt, mt_nsec);
- fmtime.dwLowDateTime = wintm.LowPart;
- fmtime.dwHighDateTime = wintm.HighPart;
- pmt = &fmtime;
- } else
- pmt = NULL;
- if (pat != NULL || pmt != NULL)
- r = SetFileTime(h, NULL, pat, pmt);
- else
- r = 1;
- CloseHandle(h);
- if (r == 0) {
- failure_start(file, line, "Can't SetFileTime %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#else /* defined(_WIN32) && !defined(__CYGWIN__) */
- struct stat st;
- struct timeval times[2];
-
-#if !defined(__FreeBSD__)
- mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */
-#endif
- if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0)
- return (1);
-
- r = lstat(pathname, &st);
- if (r < 0) {
- failure_start(file, line, "Can't stat %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-
- if (mt == 0 && mt_nsec == 0) {
- mt = st.st_mtime;
-#if defined(__FreeBSD__)
- mt_nsec = st.st_mtimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- mt_nsec = (mt_nsec / 1000) * 1000;
-#endif
- }
- if (at == 0 && at_nsec == 0) {
- at = st.st_atime;
-#if defined(__FreeBSD__)
- at_nsec = st.st_atimespec.tv_nsec;
- /* FreeBSD generally only stores to microsecond res, so round. */
- at_nsec = (at_nsec / 1000) * 1000;
-#endif
- }
-
- times[1].tv_sec = mt;
- times[1].tv_usec = mt_nsec / 1000;
-
- times[0].tv_sec = at;
- times[0].tv_usec = at_nsec / 1000;
-
-#ifdef HAVE_LUTIMES
- r = lutimes(pathname, times);
-#else
- r = utimes(pathname, times);
-#endif
- if (r < 0) {
- failure_start(file, line, "Can't utimes %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- return (1);
-#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
-}
-
-/* Set nodump, report failures. */
-int
-assertion_nodump(const char *file, int line, const char *pathname)
-{
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
- int r;
-
- assertion_count(file, line);
- r = chflags(pathname, UF_NODUMP);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
-#elif defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)\
- && defined(EXT2_NODUMP_FL)
- int fd, r, flags;
-
- assertion_count(file, line);
- fd = open(pathname, O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
- failure_start(file, line, "Can't open %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't get flags %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
- if (r < 0) {
- failure_start(file, line, "Can't set nodump %s\n", pathname);
- failure_finish(NULL);
- return (0);
- }
- close(fd);
-#else
- (void)pathname; /* UNUSED */
- assertion_count(file, line);
-#endif
- return (1);
-}
-
-/*
- *
- * UTILITIES for use by tests.
- *
- */
-
-/*
- * Check whether platform supports symlinks. This is intended
- * for tests to use in deciding whether to bother testing symlink
- * support; if the platform doesn't support symlinks, there's no point
- * in checking whether the program being tested can create them.
- *
- * Note that the first time this test is called, we actually go out to
- * disk to create and verify a symlink. This is necessary because
- * symlink support is actually a property of a particular filesystem
- * and can thus vary between directories on a single system. After
- * the first call, this returns the cached result from memory, so it's
- * safe to call it as often as you wish.
- */
-int
-canSymlink(void)
-{
- /* Remember the test result */
- static int value = 0, tested = 0;
- if (tested)
- return (value);
-
- ++tested;
- assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a");
- /* Note: Cygwin has its own symlink() emulation that does not
- * use the Win32 CreateSymbolicLink() function. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
- value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
- && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
-#elif HAVE_SYMLINK
- value = (0 == symlink("canSymlink.0", "canSymlink.1"))
- && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
-#endif
- return (value);
-}
-
-/* Platform-dependent options for hiding the output of a subcommand. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
-#else
-static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
-#endif
-/*
- * Can this platform run the bzip2 program?
- */
-int
-canBzip2(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("bzip2 -d -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the grzip program?
- */
-int
-canGrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("grzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the gzip program?
- */
-int
-canGzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("gzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lrzip program?
- */
-int
-canRunCommand(const char *cmd)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("%s %s", cmd, redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-int
-canLrzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lrzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lz4 program?
- */
-int
-canLz4(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lz4 -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzip program?
- */
-int
-canLzip(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzip -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzma program?
- */
-int
-canLzma(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzma -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the lzop program?
- */
-int
-canLzop(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("lzop -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this platform run the xz program?
- */
-int
-canXz(void)
-{
- static int tested = 0, value = 0;
- if (!tested) {
- tested = 1;
- if (systemf("xz -V %s", redirectArgs) == 0)
- value = 1;
- }
- return (value);
-}
-
-/*
- * Can this filesystem handle nodump flags.
- */
-#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
-
-int
-canNodump(void)
-{
- const char *path = "cannodumptest";
- struct stat sb;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- if (chflags(path, UF_NODUMP) < 0)
- return (0);
- if (stat(path, &sb) < 0)
- 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)
-{
- const char *path = "cannodumptest";
- int fd, r, flags;
-
- assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL);
- fd = open(path, O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- return (0);
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &flags);
- if (r < 0)
- return (0);
- flags |= EXT2_NODUMP_FL;
- r = ioctl(fd, EXT2_IOC_SETFLAGS, &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);
- if (r < 0)
- return (0);
- close(fd);
- if (flags & EXT2_NODUMP_FL)
- return (1);
- return (0);
-}
-
-#else
-
-int
-canNodump()
-{
- return (0);
-}
-
-#endif
-
-/*
- * Sleep as needed; useful for verifying disk timestamp changes by
- * ensuring that the wall-clock time has actually changed before we
- * go back to re-read something from disk.
- */
-void
-sleepUntilAfter(time_t t)
-{
- while (t >= time(NULL))
-#if defined(_WIN32) && !defined(__CYGWIN__)
- Sleep(500);
-#else
- sleep(1);
-#endif
-}
-
-/*
- * Call standard system() call, but build up the command line using
- * sprintf() conventions.
- */
-int
-systemf(const char *fmt, ...)
-{
- char buff[8192];
- va_list ap;
- int r;
-
- va_start(ap, fmt);
- vsprintf(buff, fmt, ap);
- if (verbosity > VERBOSITY_FULL)
- logprintf("Cmd: %s\n", buff);
- r = system(buff);
- va_end(ap);
- return (r);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-char *
-slurpfile(size_t * sizep, const char *fmt, ...)
-{
- char filename[8192];
- struct stat st;
- va_list ap;
- char *p;
- ssize_t bytes_read;
- FILE *f;
- int r;
-
- va_start(ap, fmt);
- vsprintf(filename, fmt, ap);
- va_end(ap);
-
- f = fopen(filename, "rb");
- if (f == NULL) {
- /* Note: No error; non-existent file is okay here. */
- return (NULL);
- }
- r = fstat(fileno(f), &st);
- if (r != 0) {
- logprintf("Can't stat file %s\n", filename);
- fclose(f);
- return (NULL);
- }
- p = malloc((size_t)st.st_size + 1);
- if (p == NULL) {
- logprintf("Can't allocate %ld bytes of memory to read file %s\n",
- (long int)st.st_size, filename);
- fclose(f);
- return (NULL);
- }
- bytes_read = fread(p, 1, (size_t)st.st_size, f);
- if (bytes_read < st.st_size) {
- logprintf("Can't read file %s\n", filename);
- fclose(f);
- free(p);
- return (NULL);
- }
- p[st.st_size] = '\0';
- if (sizep != NULL)
- *sizep = (size_t)st.st_size;
- fclose(f);
- return (p);
-}
-
-/*
- * Slurp a file into memory for ease of comparison and testing.
- * Returns size of file in 'sizep' if non-NULL, null-terminates
- * data in memory for ease of use.
- */
-void
-dumpfile(const char *filename, void *data, size_t len)
-{
- ssize_t bytes_written;
- FILE *f;
-
- f = fopen(filename, "wb");
- if (f == NULL) {
- logprintf("Can't open file %s for writing\n", filename);
- return;
- }
- bytes_written = fwrite(data, 1, len, f);
- if (bytes_written < (ssize_t)len)
- logprintf("Can't write file %s\n", filename);
- fclose(f);
-}
-
-/* Read a uuencoded file from the reference directory, decode, and
- * write the result into the current directory. */
-#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
-#define UUDECODE(c) (((c) - 0x20) & 0x3f)
-void
-extract_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
-
- sprintf(buff, "%s/%s.uu", refdir, name);
- in = fopen(buff, "r");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Read up to and including the 'begin' line. */
- for (;;) {
- if (fgets(buff, sizeof(buff), in) == NULL) {
- /* TODO: This is a failure. */
- goto done;
- }
- if (memcmp(buff, "begin ", 6) == 0)
- break;
- }
- /* Now, decode the rest and write it. */
- out = fopen(name, "wb");
- while (fgets(buff, sizeof(buff), in) != NULL) {
- char *p = buff;
- int bytes;
-
- if (memcmp(buff, "end", 3) == 0)
- break;
-
- bytes = UUDECODE(*p++);
- while (bytes > 0) {
- int n = 0;
- /* Write out 1-3 bytes from that. */
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- assert(VALID_UUDECODE(p[1]));
- n = UUDECODE(*p++) << 18;
- n |= UUDECODE(*p++) << 12;
- fputc(n >> 16, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++) << 6;
- fputc((n >> 8) & 0xFF, out);
- --bytes;
- }
- if (bytes > 0) {
- assert(VALID_UUDECODE(p[0]));
- n |= UUDECODE(*p++);
- fputc(n & 0xFF, out);
- --bytes;
- }
- }
- }
- fclose(out);
-done:
- fclose(in);
-}
-
-void
-copy_reference_file(const char *name)
-{
- char buff[1024];
- FILE *in, *out;
- size_t rbytes;
-
- sprintf(buff, "%s/%s", refdir, name);
- in = fopen(buff, "rb");
- failure("Couldn't open reference file %s", buff);
- assert(in != NULL);
- if (in == NULL)
- return;
- /* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
- out = fopen(name, "wb");
- while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- if (fwrite(buff, 1, rbytes, out) != rbytes) {
- logprintf("Error: fwrite\n");
- break;
- }
- }
- fclose(out);
- fclose(in);
-}
-
-int
-is_LargeInode(const char *file)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- BY_HANDLE_FILE_INFORMATION bhfi;
- int r;
-
- r = my_GetFileInformationByName(file, &bhfi);
- if (r != 0)
- return (0);
- return (bhfi.nFileIndexHigh & 0x0000FFFFUL);
-#else
- struct stat st;
- int64_t ino;
-
- if (stat(file, &st) < 0)
- return (0);
- ino = (int64_t)st.st_ino;
- return (ino > 0xffffffff);
-#endif
-}
-
-void
-extract_reference_files(const char **names)
-{
- while (names && *names)
- extract_reference_file(*names++);
-}
-
-/*
- *
- * TEST management
- *
- */
-
-/*
- * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has
- * a line like
- * DEFINE_TEST(test_function)
- * for each test.
- */
-
-/* Use "list.h" to declare all of the test functions. */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void);
-#include "list.h"
-
-/* Use "list.h" to create a list of all tests (functions and names). */
-#undef DEFINE_TEST
-#define DEFINE_TEST(n) { n, #n, 0 },
-struct test_list_t tests[] = {
- #include "list.h"
-};
-
-/*
- * Summarize repeated failures in the just-completed test.
- */
-static void
-test_summarize(int failed, int skips_num)
-{
- unsigned int i;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY:
- printf(failed ? "E" : ".");
- fflush(stdout);
- break;
- case VERBOSITY_PASSFAIL:
- printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n");
- break;
- }
-
- log_console = (verbosity == VERBOSITY_LIGHT_REPORT);
-
- for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
- if (failed_lines[i].count > 1 && !failed_lines[i].skip)
- logprintf("%s:%d: Summary: Failed %d times\n",
- failed_filename, i, failed_lines[i].count);
- }
- /* Clear the failure history for the next file. */
- failed_filename = NULL;
- memset(failed_lines, 0, sizeof(failed_lines));
-}
-
-/*
- * Actually run a single test, with appropriate setup and cleanup.
- */
-static int
-test_run(int i, const char *tmpdir)
-{
- char workdir[1024];
- char logfilename[64];
- int failures_before = failures;
- int skips_before = skips;
- int oldumask;
-
- switch (verbosity) {
- case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
- break;
- case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
- printf("%3d: %-64s", i, tests[i].name);
- fflush(stdout);
- break;
- default: /* Title of test, details will follow */
- printf("%3d: %s\n", i, tests[i].name);
- }
-
- /* Chdir to the top-level work directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to top work dir %s\n", tmpdir);
- exit(1);
- }
- /* Create a log file for this test. */
- sprintf(logfilename, "%s.log", tests[i].name);
- logfile = fopen(logfilename, "w");
- fprintf(logfile, "%s\n\n", tests[i].name);
- /* Chdir() to a work dir for this specific test. */
- snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name);
- testworkdir = workdir;
- if (!assertMakeDir(testworkdir, 0755)
- || !assertChdir(testworkdir)) {
- fprintf(stderr,
- "ERROR: Can't chdir to work dir %s\n", testworkdir);
- exit(1);
- }
- /* Explicitly reset the locale before each test. */
- setlocale(LC_ALL, "C");
- /* Record the umask before we run the test. */
- umask(oldumask = umask(0));
- /*
- * Run the actual test.
- */
- (*tests[i].func)();
- /*
- * Clean up and report afterwards.
- */
- testworkdir = NULL;
- /* Restore umask */
- umask(oldumask);
- /* Reset locale. */
- setlocale(LC_ALL, "C");
- /* Reset directory. */
- if (!assertChdir(tmpdir)) {
- fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n",
- tmpdir);
- exit(1);
- }
- /* Report per-test summaries. */
- tests[i].failures = failures - failures_before;
- test_summarize(tests[i].failures, skips - skips_before);
- /* Close the per-test log file. */
- fclose(logfile);
- logfile = NULL;
- /* If there were no failures, we can remove the work dir and logfile. */
- if (tests[i].failures == 0) {
- if (!keep_temp_files && assertChdir(tmpdir)) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure not to leave empty directories.
- * Sometimes a processing of closing files used by tests
- * is not done, then rmdir will be failed and it will
- * leave a empty test directory. So we should wait a few
- * seconds and retry rmdir. */
- int r, t;
- for (t = 0; t < 10; t++) {
- if (t > 0)
- Sleep(1000);
- r = systemf("rmdir /S /Q %s", tests[i].name);
- if (r == 0)
- break;
- }
- systemf("del %s", logfilename);
-#else
- systemf("rm -rf %s", tests[i].name);
- systemf("rm %s", logfilename);
-#endif
- }
- }
- /* Return appropriate status. */
- return (tests[i].failures);
-}
-
-/*
- *
- *
- * MAIN and support routines.
- *
- *
- */
-
-static void
-usage(const char *program)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int i;
-
- printf("Usage: %s [options] <test> <test> ...\n", program);
- printf("Default is to run all tests.\n");
- printf("Otherwise, specify the numbers of the tests you wish to run.\n");
- printf("Options:\n");
- printf(" -d Dump core after any failure, for debugging.\n");
- printf(" -k Keep all temp files.\n");
- printf(" Default: temp files for successful tests deleted.\n");
-#ifdef PROGRAM
- printf(" -p <path> Path to executable to be tested.\n");
- printf(" Default: path taken from " ENVBASE " environment variable.\n");
-#endif
- printf(" -q Quiet.\n");
- printf(" -r <dir> Path to dir containing reference files.\n");
- printf(" Default: Current directory.\n");
- printf(" -u Keep running specifies tests until one fails.\n");
- printf(" -v Verbose.\n");
- printf("Available tests:\n");
- for (i = 0; i < limit; i++)
- printf(" %d: %s\n", i, tests[i].name);
- exit(1);
-}
-
-static char *
-get_refdir(const char *d)
-{
- size_t tried_size, buff_size;
- char *buff, *tried, *pwd = NULL, *p = NULL;
-
-#ifdef PATH_MAX
- buff_size = PATH_MAX;
-#else
- buff_size = 8192;
-#endif
- buff = calloc(buff_size, 1);
- if (buff == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* Allocate a buffer to hold the various directories we checked. */
- tried_size = buff_size * 2;
- tried = calloc(tried_size, 1);
- if (tried == NULL) {
- fprintf(stderr, "Unable to allocate memory\n");
- exit(1);
- }
-
- /* If a dir was specified, try that */
- if (d != NULL) {
- pwd = NULL;
- snprintf(buff, buff_size, "%s", d);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- goto failure;
- }
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
- /* Look for a known file. */
- snprintf(buff, buff_size, "%s", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(LIBRARY)
- snprintf(buff, buff_size, "%s/%s/test", pwd, LIBRARY);
-#else
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM);
-#endif
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
-#if defined(PROGRAM_ALIAS)
- snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM_ALIAS);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-#endif
-
- if (memcmp(pwd, "/usr/obj", 8) == 0) {
- snprintf(buff, buff_size, "%s", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
-
- snprintf(buff, buff_size, "%s/test", pwd + 8);
- p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
- if (p != NULL) goto success;
- strncat(tried, buff, tried_size - strlen(tried) - 1);
- strncat(tried, "\n", tried_size - strlen(tried) - 1);
- }
-
-failure:
- printf("Unable to locate known reference file %s\n", KNOWNREF);
- printf(" Checked following directories:\n%s\n", tried);
- printf("Use -r option to specify full path to reference directory\n");
-#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
- DebugBreak();
-#endif
- exit(1);
-
-success:
- free(p);
- free(pwd);
- free(tried);
-
- /* Copy result into a fresh buffer to reduce memory usage. */
- p = strdup(buff);
- free(buff);
- return p;
-}
-
-int
-main(int argc, char **argv)
-{
- static const int limit = sizeof(tests) / sizeof(tests[0]);
- int test_set[sizeof(tests) / sizeof(tests[0])];
- int i = 0, j = 0, tests_run = 0, tests_failed = 0, option;
- time_t now;
- char *refdir_alloc = NULL;
- const char *progname;
- char **saved_argv;
- const char *tmp, *option_arg, *p;
- char tmpdir[256], *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL;
- char tmpdir_timestamp[256];
-
- (void)argc; /* UNUSED */
-
- /* Get the current dir. */
-#ifdef PATH_MAX
- pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
-#else
- pwd = getcwd(NULL, 0);
-#endif
- while (pwd[strlen(pwd) - 1] == '\n')
- pwd[strlen(pwd) - 1] = '\0';
-
-#if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__)
- /* To stop to run the default invalid parameter handler. */
- _set_invalid_parameter_handler(invalid_parameter_handler);
- /* Disable annoying assertion message box. */
- _CrtSetReportMode(_CRT_ASSERT, 0);
-#endif
-
- /*
- * Name of this program, used to build root of our temp directory
- * tree.
- */
- progname = p = argv[0];
- if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(testprogdir, progname);
- while (*p != '\0') {
- /* Support \ or / dir separators for Windows compat. */
- if (*p == '/' || *p == '\\')
- {
- progname = p + 1;
- i = j;
- }
- ++p;
- j++;
- }
- testprogdir[i] = '\0';
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (testprogdir[0] != '/' && testprogdir[0] != '\\' &&
- !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') ||
- (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) &&
- testprogdir[1] == ':' &&
- (testprogdir[2] == '/' || testprogdir[2] == '\\')))
-#else
- if (testprogdir[0] != '/')
-#endif
- {
- /* Fixup path for relative directories. */
- if ((testprogdir = (char *)realloc(testprogdir,
- strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir) + 1);
- memcpy(testprogdir, pwd, strlen(pwd));
- testprogdir[strlen(pwd)] = '/';
- }
-
-#ifdef PROGRAM
- /* Get the target program from environment, if available. */
- testprogfile = getenv(ENVBASE);
-#endif
-
- if (getenv("TMPDIR") != NULL)
- tmp = getenv("TMPDIR");
- else if (getenv("TMP") != NULL)
- tmp = getenv("TMP");
- else if (getenv("TEMP") != NULL)
- tmp = getenv("TEMP");
- else if (getenv("TEMPDIR") != NULL)
- tmp = getenv("TEMPDIR");
- else
- tmp = "/tmp";
-
- /* Allow -d to be controlled through the environment. */
- if (getenv(ENVBASE "_DEBUG") != NULL)
- dump_on_failure = 1;
-
- /* Allow -v to be controlled through the environment. */
- if (getenv("_VERBOSITY_LEVEL") != NULL)
- {
- vlevel = getenv("_VERBOSITY_LEVEL");
- verbosity = atoi(vlevel);
- if (verbosity < VERBOSITY_SUMMARY_ONLY || verbosity > VERBOSITY_FULL)
- {
- /* Unsupported verbosity levels are silently ignored */
- vlevel = NULL;
- verbosity = VERBOSITY_PASSFAIL;
- }
- }
-
- /* Get the directory holding test files from environment. */
- refdir = getenv(ENVBASE "_TEST_FILES");
-
- /*
- * Parse options, without using getopt(), which isn't available
- * on all platforms.
- */
- ++argv; /* Skip program name */
- while (*argv != NULL) {
- if (**argv != '-')
- break;
- p = *argv++;
- ++p; /* Skip '-' */
- while (*p != '\0') {
- option = *p++;
- option_arg = NULL;
- /* If 'opt' takes an argument, parse that. */
- if (option == 'p' || option == 'r') {
- if (*p != '\0')
- option_arg = p;
- else if (*argv == NULL) {
- fprintf(stderr,
- "Option -%c requires argument.\n",
- option);
- usage(progname);
- } else
- option_arg = *argv++;
- p = ""; /* End of this option word. */
- }
-
- /* Now, handle the option. */
- switch (option) {
- case 'd':
- dump_on_failure = 1;
- break;
- case 'k':
- keep_temp_files = 1;
- break;
- case 'p':
-#ifdef PROGRAM
- testprogfile = option_arg;
-#else
- fprintf(stderr, "-p option not permitted\n");
- usage(progname);
-#endif
- break;
- case 'q':
- if (!vlevel)
- verbosity--;
- break;
- case 'r':
- refdir = option_arg;
- break;
- case 'u':
- until_failure++;
- break;
- case 'v':
- if (!vlevel)
- verbosity++;
- break;
- default:
- fprintf(stderr, "Unrecognized option '%c'\n",
- option);
- usage(progname);
- }
- }
- }
-
- /*
- * Sanity-check that our options make sense.
- */
-#ifdef PROGRAM
- if (testprogfile == NULL)
- {
- if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 +
- strlen(PROGRAM) + 1)) == NULL)
- {
- fprintf(stderr, "ERROR: Out of memory.");
- exit(1);
- }
- strcpy(tmp2, testprogdir);
- strcat(tmp2, "/");
- strcat(tmp2, PROGRAM);
- testprogfile = tmp2;
- }
-
- {
- char *testprg;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Command.com sometimes rejects '/' separators. */
- testprg = strdup(testprogfile);
- for (i = 0; testprg[i] != '\0'; i++) {
- if (testprg[i] == '/')
- testprg[i] = '\\';
- }
- testprogfile = testprg;
-#endif
- /* Quote the name that gets put into shell command lines. */
- testprg = malloc(strlen(testprogfile) + 3);
- strcpy(testprg, "\"");
- strcat(testprg, testprogfile);
- strcat(testprg, "\"");
- testprog = testprg;
- }
-#endif
-
-#if !defined(_WIN32) && defined(SIGPIPE)
- { /* Ignore SIGPIPE signals */
- struct sigaction sa;
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(SIGPIPE, &sa, NULL);
- }
-#endif
-
- /*
- * Create a temp directory for the following tests.
- * Include the time the tests started as part of the name,
- * to make it easier to track the results of multiple tests.
- */
- now = time(NULL);
- for (i = 0; ; i++) {
- strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp),
- "%Y-%m-%dT%H.%M.%S",
- localtime(&now));
- snprintf(tmpdir, sizeof(tmpdir), "%s/%s.%s-%03d", tmp,
- progname, tmpdir_timestamp, i);
- if (assertMakeDir(tmpdir,0755))
- break;
- if (i >= 999) {
- fprintf(stderr,
- "ERROR: Unable to create temp directory %s\n",
- tmpdir);
- exit(1);
- }
- }
-
- /*
- * If the user didn't specify a directory for locating
- * reference files, try to find the reference files in
- * the "usual places."
- */
- refdir = refdir_alloc = get_refdir(refdir);
-
- /*
- * Banner with basic information.
- */
- printf("\n");
- printf("If tests fail or crash, details will be in:\n");
- printf(" %s\n", tmpdir);
- printf("\n");
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("Reference files will be read from: %s\n", refdir);
-#ifdef PROGRAM
- printf("Running tests on: %s\n", testprog);
-#endif
- printf("Exercising: ");
- fflush(stdout);
- printf("%s\n", EXTRA_VERSION);
- } else {
- printf("Running ");
- fflush(stdout);
- }
-
- /*
- * Run some or all of the individual tests.
- */
- saved_argv = argv;
- do {
- argv = saved_argv;
- do {
- int test_num;
-
- test_num = get_test_set(test_set, limit, *argv, tests);
- if (test_num < 0) {
- printf("*** INVALID Test %s\n", *argv);
- free(refdir_alloc);
- free(testprogdir);
- usage(progname);
- return (1);
- }
- for (i = 0; i < test_num; i++) {
- tests_run++;
- if (test_run(test_set[i], tmpdir)) {
- tests_failed++;
- if (until_failure)
- goto finish;
- }
- }
- if (*argv != NULL)
- argv++;
- } while (*argv != NULL);
- } while (until_failure);
-
-finish:
- /* Must be freed after all tests run */
- free(tmp2);
- free(testprogdir);
- free(pwd);
-
- /*
- * Report summary statistics.
- */
- if (verbosity > VERBOSITY_SUMMARY_ONLY) {
- printf("\n");
- printf("Totals:\n");
- printf(" Tests run: %8d\n", tests_run);
- printf(" Tests failed: %8d\n", tests_failed);
- printf(" Assertions checked:%8d\n", assertions);
- printf(" Assertions failed: %8d\n", failures);
- printf(" Skips reported: %8d\n", skips);
- }
- if (failures) {
- printf("\n");
- printf("Failing tests:\n");
- for (i = 0; i < limit; ++i) {
- if (tests[i].failures)
- printf(" %d: %s (%d failures)\n", i,
- tests[i].name, tests[i].failures);
- }
- printf("\n");
- printf("Details for failing tests: %s\n", tmpdir);
- printf("\n");
- } else {
- if (verbosity == VERBOSITY_SUMMARY_ONLY)
- printf("\n");
- printf("%d tests passed, no failures\n", tests_run);
- }
-
- free(refdir_alloc);
-
- /* If the final tmpdir is empty, we can remove it. */
- /* This should be the usual case when all tests succeed. */
- assertChdir("..");
- rmdir(tmpdir);
-
- return (tests_failed ? 1 : 0);
-}
diff --git a/tar/test/test.h b/tar/test/test.h
index 3a23a05a67ec..1e1bee80709c 100644
--- a/tar/test/test.h
+++ b/tar/test/test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2006 Tim Kientzle
+ * Copyright (c) 2003-2017 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,333 +22,19 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/usr.bin/tar/test/test.h,v 1.4 2008/08/21 07:04:57 kientzle Exp $
+ * $FreeBSD$
*/
/* Every test program should #include "test.h" as the first thing. */
-/*
- * The goal of this file (and the matching test.c) is to
- * simplify the very repetitive test-*.c test programs.
- */
-#if defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "config.h"
-#elif defined(__FreeBSD__)
-/* Building as part of FreeBSD system requires a pre-built config.h. */
-#include "config_freebsd.h"
-#elif defined(_WIN32) && !defined(__CYGWIN__)
-/* Win32 can't run the 'configure' script. */
-#include "config_windows.h"
-#else
-/* Warn if the library hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no pre-built configuration in test.h.
-#endif
-
-#include <sys/types.h> /* Windows requires this before sys/stat.h */
-#include <sys/stat.h>
-
-#if HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#define dirent direct
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <wchar.h>
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-/*
- * System-specific tweaks. We really want to minimize these
- * as much as possible, since they make it harder to understand
- * the mainline code.
- */
-
-/* Windows (including Visual Studio and MinGW but not Cygwin) */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(__BORLANDC__)
-#undef chdir
-#define chdir _chdir
-#define strdup _strdup
-#endif
-#endif
-
-/* Visual Studio */
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf sprintf_s
-#endif
-
-#if defined(__BORLANDC__)
-#pragma warn -8068 /* Constant out of range in comparison. */
-#endif
-
-/* Haiku OS and QNX */
-#if defined(__HAIKU__) || defined(__QNXNTO__)
-/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
-#include <stdint.h>
-#endif
-
-/* Get a real definition for __FBSDID if we can */
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-/* If not, define it so as to avoid dangling semicolons. */
-#ifndef __FBSDID
-#define __FBSDID(a) struct _undefined_hack
-#endif
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/*
- * Redefine DEFINE_TEST for use in defining the test functions.
- */
-#undef DEFINE_TEST
-#define DEFINE_TEST(name) void name(void); void name(void)
-
-/* An implementation of the standard assert() macro */
-#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
-/* chdir() and error if it fails */
-#define assertChdir(path) \
- assertion_chdir(__FILE__, __LINE__, path)
-/* 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)
-/* Assert two strings are the same. Reports value of each one if not. */
-#define assertEqualString(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
-#define assertEqualUTF8String(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
-/* As above, but v1 and v2 are wchar_t * */
-#define assertEqualWString(v1,v2) \
- assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
-/* As above, but raw blocks of bytes. */
-#define assertEqualMem(v1, v2, l) \
- assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
-/* Assert that memory is full of a specified byte */
-#define assertMemoryFilledWith(v1, l, b) \
- assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
-/* Assert two files are the same. */
-#define assertEqualFile(f1, f2) \
- assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
-/* Assert that a file is empty. */
-#define assertEmptyFile(pathname) \
- assertion_empty_file(__FILE__, __LINE__, (pathname))
-/* Assert that a file is not empty. */
-#define assertNonEmptyFile(pathname) \
- assertion_non_empty_file(__FILE__, __LINE__, (pathname))
-#define assertFileAtime(pathname, sec, nsec) \
- assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileAtimeRecent(pathname) \
- assertion_file_atime_recent(__FILE__, __LINE__, pathname)
-#define assertFileBirthtime(pathname, sec, nsec) \
- assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileBirthtimeRecent(pathname) \
- assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
-/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileExists(pathname) \
- assertion_file_exists(__FILE__, __LINE__, pathname)
-/* Assert that a file exists. */
-#define assertFileNotExists(pathname) \
- assertion_file_not_exists(__FILE__, __LINE__, pathname)
-/* Assert that file contents match a string. */
-#define assertFileContents(data, data_size, pathname) \
- assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
-/* Verify that a file does not contain invalid strings */
-#define assertFileContainsNoInvalidStrings(pathname, strings) \
- assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
-#define assertFileMtime(pathname, sec, nsec) \
- assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
-#define assertFileMtimeRecent(pathname) \
- assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
-#define assertFileNLinks(pathname, nlinks) \
- assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
-#define assertFileSize(pathname, size) \
- assertion_file_size(__FILE__, __LINE__, pathname, size)
-#define assertFileMode(pathname, mode) \
- assertion_file_mode(__FILE__, __LINE__, pathname, mode)
-#define assertTextFileContents(text, pathname) \
- assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
-#define assertFileContainsLinesAnyOrder(pathname, lines) \
- assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
-#define assertIsDir(pathname, mode) \
- assertion_is_dir(__FILE__, __LINE__, pathname, mode)
-#define assertIsHardlink(path1, path2) \
- assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsNotHardlink(path1, path2) \
- assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
-#define assertIsReg(pathname, mode) \
- assertion_is_reg(__FILE__, __LINE__, pathname, mode)
-#define assertIsSymlink(pathname, contents) \
- assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
-/* Create a directory, report error if it fails. */
-#define assertMakeDir(dirname, mode) \
- assertion_make_dir(__FILE__, __LINE__, dirname, mode)
-#define assertMakeFile(path, mode, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents)
-#define assertMakeBinFile(path, mode, csize, contents) \
- assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents)
-#define assertMakeHardlink(newfile, oldfile) \
- 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 assertUmask(mask) \
- assertion_umask(__FILE__, __LINE__, mask)
-#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
- assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
-
-/*
- * This would be simple with C99 variadic macros, but I don't want to
- * require that. Instead, I insert a function call before each
- * skipping() call to pass the file and line information down. Crude,
- * but effective.
- */
-#define skipping \
- skipping_setup(__FILE__, __LINE__);test_skipping
-
-/* Function declarations. These are defined in test_utility.c. */
-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_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 *);
-int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
-int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
-int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
-int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
-int assertion_file_atime(const char *, int, const char *, long, long);
-int assertion_file_atime_recent(const char *, int, const char *);
-int assertion_file_birthtime(const char *, int, const char *, long, long);
-int assertion_file_birthtime_recent(const char *, int, const char *);
-int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
-int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
-int assertion_file_contents(const char *, int, const void *, int, const char *);
-int assertion_file_exists(const char *, int, const char *);
-int assertion_file_mode(const char *, int, const char *, int);
-int assertion_file_mtime(const char *, int, const char *, long, long);
-int assertion_file_mtime_recent(const char *, int, const char *);
-int assertion_file_nlinks(const char *, int, const char *, int);
-int assertion_file_not_exists(const char *, int, const char *);
-int assertion_file_size(const char *, int, const char *, long);
-int assertion_is_dir(const char *, int, const char *, int);
-int assertion_is_hardlink(const char *, int, const char *, const char *);
-int assertion_is_not_hardlink(const char *, int, const char *, const char *);
-int assertion_is_reg(const char *, int, const char *, int);
-int assertion_is_symlink(const char *, int, const char *, const char *);
-int assertion_make_dir(const char *, int, const char *, int);
-int assertion_make_file(const char *, int, const char *, int, int, const void *);
-int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
-int assertion_make_symlink(const char *, int, const char *newpath, const char *);
-int assertion_nodump(const char *, int, const char *);
-int assertion_non_empty_file(const char *, int, const char *);
-int assertion_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 );
-
-void skipping_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
-
-/* Like sprintf, then system() */
-int systemf(const char * fmt, ...);
-
-/* Delay until time() returns a value after this. */
-void sleepUntilAfter(time_t);
-
-/* Return true if this platform can create symlinks. */
-int canSymlink(void);
-
-/* Return true if this platform can run the "bzip2" program. */
-int canBzip2(void);
-
-/* Return true if this platform can run the "grzip" program. */
-int canGrzip(void);
-
-/* Return true if this platform can run the "gzip" program. */
-int canGzip(void);
-
-/* Return true if this platform can run the specified command. */
-int canRunCommand(const char *);
-
-/* Return true if this platform can run the "lrzip" program. */
-int canLrzip(void);
-
-/* Return true if this platform can run the "lz4" program. */
-int canLz4(void);
-
-/* Return true if this platform can run the "lzip" program. */
-int canLzip(void);
-
-/* Return true if this platform can run the "lzma" program. */
-int canLzma(void);
-
-/* Return true if this platform can run the "lzop" program. */
-int canLzop(void);
-
-/* Return true if this platform can run the "xz" program. */
-int canXz(void);
-
-/* Return true if this filesystem can handle nodump flags. */
-int canNodump(void);
-
-/* Return true if the file has large i-node number(>0xffffffff). */
-int is_LargeInode(const char *);
-
-/* 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, ...);
-
-/* Dump block of bytes to a file. */
-void dumpfile(const char *filename, void *, size_t);
-
-/* Extracts named reference file to the current directory. */
-void extract_reference_file(const char *);
-/* Copies named reference file to the current directory. */
-void copy_reference_file(const char *);
-
-/* Extracts a list of files to the current directory.
- * List must be NULL terminated.
- */
-void extract_reference_files(const char **);
-
-/* Subtract umask from mode */
-mode_t umasked(mode_t expected_mode);
-
-/* Path to working directory for current test */
-extern const char *testworkdir;
-
-/*
- * Special interfaces for program test harness.
- */
-
-/* Pathname of exe to be tested. */
-extern const char *testprogfile;
-/* Name of exe to use in printf-formatted command strings. */
-/* On Windows, this includes leading/trailing quotes. */
-extern const char *testprog;
-
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
+#define KNOWNREF "test_patterns_2.tar.uu"
+#define ENVBASE "BSDTAR" /* Prefix for environment variables. */
+#define PROGRAM "bsdtar" /* Name of program being tested. */
+#define PROGRAM_ALIAS "tar" /* Generic alias for program */
+#undef LIBRARY /* Not testing a library. */
+#undef EXTRA_DUMP /* How to dump extra data */
+#undef EXTRA_ERRNO /* How to dump errno */
+/* How to generate extra version info. */
+#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
+
+#include "test_common.h"
diff --git a/tar/test/test_version.c b/tar/test/test_version.c
index 0c904d705c22..1b896c0c49d1 100644
--- a/tar/test/test_version.c
+++ b/tar/test/test_version.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2017 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,7 +23,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
-__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_version.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $");
/*
* Test that --version option works and generates reasonable output.
@@ -31,73 +30,5 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/test/test_version.c,v 1.2 2008/05/26 17:10:1
DEFINE_TEST(test_version)
{
- int r;
- char *p, *q;
- size_t s;
-
-
- r = systemf("%s --version >version.stdout 2>version.stderr", testprog);
- if (r != 0)
- r = systemf("%s -W version >version.stdout 2>version.stderr",
- testprog);
- failure("Unable to run either %s --version or %s -W version",
- testprog, testprog);
- if (!assert(r == 0))
- return;
-
- /* --version should generate nothing to stdout. */
- assertEmptyFile("version.stderr");
- /* Verify format of version message. */
- q = p = slurpfile(&s, "version.stdout");
- /* Version message should start with name of program, then space. */
- assert(s > 6);
- failure("Version must start with 'bsdtar': ``%s''", p);
- if (!assertEqualMem(q, "bsdtar ", 7))
- goto done;
- q += 7; s -= 7;
- /* Version number is a series of digits and periods. */
- while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
- ++q;
- --s;
- }
- /* Version number terminated by space. */
- failure("No space after bsdtar version: ``%s''", p);
- assert(s > 1);
- /* Skip a single trailing a,b,c, or d. */
- if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
- ++q;
- failure("No space after bsdtar version: ``%s''", p);
- assert(*q == ' ');
- ++q; --s;
- /* Separator. */
- failure("No `-' between bsdtar and libarchive versions: ``%s''", p);
- assertEqualMem(q, "- ", 2);
- q += 2; s -= 2;
- /* libarchive name and version number */
- failure("Not long enough for libarchive version: ``%s''", p);
- assert(s > 11);
- failure("Libarchive version must start with `libarchive': ``%s''", p);
- assertEqualMem(q, "libarchive ", 11);
- q += 11; s -= 11;
- /* Version number is a series of digits and periods. */
- while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
- ++q;
- --s;
- }
- /* Skip a single trailing a,b,c, or d. */
- if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
- ++q;
- /* Skip arbitrary third-party version numbers. */
- while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || isalnum(*q))) {
- ++q;
- --s;
- }
- /* All terminated by end-of-line. */
- assert(s >= 1);
- /* Skip an optional CR character (e.g., Windows) */
- failure("Version output must end with \\n or \\r\\n");
- if (*q == '\r') { ++q; --s; }
- assertEqualMem(q, "\n", 1);
-done:
- free(p);
+ assertVersion(testprog, "bsdtar");
}
diff --git a/tar/util.c b/tar/util.c
index 8f65b1762740..662db5baa796 100644
--- a/tar/util.c
+++ b/tar/util.c
@@ -534,7 +534,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
}
}
- 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 fb8bb92b26e9..9c2456625271 100644
--- a/tar/write.c
+++ b/tar/write.c
@@ -583,7 +583,7 @@ cleanup:
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 @@ archive_names_from_file(struct bsdtar *bsdtar, struct archive *a)
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 @@ archive_names_from_file(struct bsdtar *bsdtar, struct archive *a)
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 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
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 @@ excluded_callback(struct archive *a, void *_data, struct archive_entry *entry)
{
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 @@ metadata_filter(struct archive *a, void *_data, struct archive_entry *entry)
* 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);
@@ -1010,7 +1013,7 @@ report_write(struct bsdtar *bsdtar, struct archive *a,
uncomp = archive_filter_bytes(a, 0);
fprintf(stderr, "In: %d files, %s bytes;",
archive_file_count(a), tar_i64toa(uncomp));
- if (comp > uncomp)
+ if (comp >= uncomp)
compression = 0;
else
compression = (int)((uncomp - comp) * 100 / uncomp);
diff --git a/test_utils/test_common.h b/test_utils/test_common.h
new file mode 100644
index 000000000000..82e8483f0134
--- /dev/null
+++ b/test_utils/test_common.h
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2003-2017 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef TEST_COMMON_H
+#define TEST_COMMON_H
+
+/*
+ * The goal of this file (and the matching test.c) is to
+ * simplify the very repetitive test-*.c test programs.
+ */
+#if defined(HAVE_CONFIG_H)
+/* Most POSIX platforms use the 'configure' script to build config.h */
+#include "config.h"
+#elif defined(__FreeBSD__)
+/* Building as part of FreeBSD system requires a pre-built config.h. */
+#include "config_freebsd.h"
+#elif defined(_WIN32) && !defined(__CYGWIN__)
+/* Win32 can't run the 'configure' script. */
+#include "config_windows.h"
+#else
+/* Warn if the library hasn't been (automatically or manually) configured. */
+#error Oops: No config.h and no pre-built configuration in test.h.
+#endif
+
+#include <sys/types.h> /* Windows requires this before sys/stat.h */
+#include <sys/stat.h>
+
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#define dirent direct
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <wchar.h>
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+/*
+ * System-specific tweaks. We really want to minimize these
+ * as much as possible, since they make it harder to understand
+ * the mainline code.
+ */
+
+/* Windows (including Visual Studio and MinGW but not Cygwin) */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if !defined(__BORLANDC__)
+#undef chdir
+#define chdir _chdir
+#define strdup _strdup
+#endif
+#endif
+
+/* Visual Studio */
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define snprintf sprintf_s
+#endif
+
+#if defined(__BORLANDC__)
+#pragma warn -8068 /* Constant out of range in comparison. */
+#endif
+
+/* Haiku OS and QNX */
+#if defined(__HAIKU__) || defined(__QNXNTO__)
+/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
+#include <stdint.h>
+#endif
+
+/* Get a real definition for __FBSDID if we can */
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+/* If not, define it so as to avoid dangling semicolons. */
+#ifndef __FBSDID
+#define __FBSDID(a) struct _undefined_hack
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/*
+ * If this platform has <sys/acl.h>, acl_create(), acl_init(),
+ * acl_set_file(), and ACL_USER, we assume it has the rest of the
+ * POSIX.1e draft functions used in archive_read_extract.c.
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
+#if HAVE_ACL_USER
+#define HAVE_POSIX_ACL 1
+#elif HAVE_ACL_TYPE_EXTENDED
+#define HAVE_DARWIN_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
+#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
+#endif
+
+/*
+ * Redefine DEFINE_TEST for use in defining the test functions.
+ */
+#undef DEFINE_TEST
+#define DEFINE_TEST(name) void name(void); void name(void)
+
+/* An implementation of the standard assert() macro */
+#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
+/* chdir() and error if it fails */
+#define assertChdir(path) \
+ assertion_chdir(__FILE__, __LINE__, path)
+/* 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)
+/* Assert two strings are the same. Reports value of each one if not. */
+#define assertEqualString(v1,v2) \
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
+#define assertEqualUTF8String(v1,v2) \
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
+/* As above, but v1 and v2 are wchar_t * */
+#define assertEqualWString(v1,v2) \
+ assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+/* As above, but raw blocks of bytes. */
+#define assertEqualMem(v1, v2, l) \
+ assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
+/* Assert that memory is full of a specified byte */
+#define assertMemoryFilledWith(v1, l, b) \
+ assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL)
+/* Assert two files are the same. */
+#define assertEqualFile(f1, f2) \
+ assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
+/* Assert that a file is empty. */
+#define assertEmptyFile(pathname) \
+ assertion_empty_file(__FILE__, __LINE__, (pathname))
+/* Assert that a file is not empty. */
+#define assertNonEmptyFile(pathname) \
+ assertion_non_empty_file(__FILE__, __LINE__, (pathname))
+#define assertFileAtime(pathname, sec, nsec) \
+ assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
+#define assertFileAtimeRecent(pathname) \
+ assertion_file_atime_recent(__FILE__, __LINE__, pathname)
+#define assertFileBirthtime(pathname, sec, nsec) \
+ assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
+#define assertFileBirthtimeRecent(pathname) \
+ assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
+/* Assert that a file exists; supports printf-style arguments. */
+#define assertFileExists(pathname) \
+ assertion_file_exists(__FILE__, __LINE__, pathname)
+/* Assert that a file exists. */
+#define assertFileNotExists(pathname) \
+ assertion_file_not_exists(__FILE__, __LINE__, pathname)
+/* Assert that file contents match a string. */
+#define assertFileContents(data, data_size, pathname) \
+ assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
+/* Verify that a file does not contain invalid strings */
+#define assertFileContainsNoInvalidStrings(pathname, strings) \
+ assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings)
+#define assertFileMtime(pathname, sec, nsec) \
+ assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
+#define assertFileMtimeRecent(pathname) \
+ assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
+#define assertFileNLinks(pathname, nlinks) \
+ assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
+#define assertFileSize(pathname, size) \
+ assertion_file_size(__FILE__, __LINE__, pathname, size)
+#define assertFileMode(pathname, mode) \
+ assertion_file_mode(__FILE__, __LINE__, pathname, mode)
+#define assertTextFileContents(text, pathname) \
+ assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
+#define assertFileContainsLinesAnyOrder(pathname, lines) \
+ assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
+#define assertIsDir(pathname, mode) \
+ assertion_is_dir(__FILE__, __LINE__, pathname, mode)
+#define assertIsHardlink(path1, path2) \
+ assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
+#define assertIsNotHardlink(path1, path2) \
+ assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
+#define assertIsReg(pathname, mode) \
+ assertion_is_reg(__FILE__, __LINE__, pathname, mode)
+#define assertIsSymlink(pathname, contents) \
+ assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
+/* Create a directory, report error if it fails. */
+#define assertMakeDir(dirname, mode) \
+ assertion_make_dir(__FILE__, __LINE__, dirname, mode)
+#define assertMakeFile(path, mode, contents) \
+ assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents)
+#define assertMakeBinFile(path, mode, csize, contents) \
+ assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents)
+#define assertMakeHardlink(newfile, oldfile) \
+ 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 assertUmask(mask) \
+ assertion_umask(__FILE__, __LINE__, mask)
+#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
+ assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
+#ifndef PROGRAM
+#define assertEntrySetAcls(entry, acls, count) \
+ assertion_entry_set_acls(__FILE__, __LINE__, entry, acls, count)
+#define assertEntryCompareAcls(entry, acls, count, type, mode) \
+ assertion_entry_compare_acls(__FILE__, __LINE__, entry, acls, count, type, mode)
+#endif
+
+/*
+ * This would be simple with C99 variadic macros, but I don't want to
+ * require that. Instead, I insert a function call before each
+ * skipping() call to pass the file and line information down. Crude,
+ * but effective.
+ */
+#define skipping \
+ skipping_setup(__FILE__, __LINE__);test_skipping
+
+/* Function declarations. These are defined in test_utility.c. */
+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_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 *);
+int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
+int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *);
+int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
+int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
+int assertion_file_atime(const char *, int, const char *, long, long);
+int assertion_file_atime_recent(const char *, int, const char *);
+int assertion_file_birthtime(const char *, int, const char *, long, long);
+int assertion_file_birthtime_recent(const char *, int, const char *);
+int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
+int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **);
+int assertion_file_contents(const char *, int, const void *, int, const char *);
+int assertion_file_exists(const char *, int, const char *);
+int assertion_file_mode(const char *, int, const char *, int);
+int assertion_file_mtime(const char *, int, const char *, long, long);
+int assertion_file_mtime_recent(const char *, int, const char *);
+int assertion_file_nlinks(const char *, int, const char *, int);
+int assertion_file_not_exists(const char *, int, const char *);
+int assertion_file_size(const char *, int, const char *, long);
+int assertion_is_dir(const char *, int, const char *, int);
+int assertion_is_hardlink(const char *, int, const char *, const char *);
+int assertion_is_not_hardlink(const char *, int, const char *, const char *);
+int assertion_is_reg(const char *, int, const char *, int);
+int assertion_is_symlink(const char *, int, const char *, const char *);
+int assertion_make_dir(const char *, int, const char *, int);
+int assertion_make_file(const char *, int, const char *, int, int, const void *);
+int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
+int assertion_make_symlink(const char *, int, const char *newpath, const char *);
+int assertion_nodump(const char *, int, const char *);
+int assertion_non_empty_file(const char *, int, const char *);
+int assertion_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 );
+int assertion_version(const char*, int, const char *, const char *);
+
+void skipping_setup(const char *, int);
+void test_skipping(const char *fmt, ...);
+
+/* Like sprintf, then system() */
+int systemf(const char * fmt, ...);
+
+/* Delay until time() returns a value after this. */
+void sleepUntilAfter(time_t);
+
+/* Return true if this platform can create symlinks. */
+int canSymlink(void);
+
+/* Return true if this platform can run the "bzip2" program. */
+int canBzip2(void);
+
+/* Return true if this platform can run the "grzip" program. */
+int canGrzip(void);
+
+/* Return true if this platform can run the "gzip" program. */
+int canGzip(void);
+
+/* Return true if this platform can run the specified command. */
+int canRunCommand(const char *);
+
+/* Return true if this platform can run the "lrzip" program. */
+int canLrzip(void);
+
+/* Return true if this platform can run the "lz4" program. */
+int canLz4(void);
+
+/* Return true if this platform can run the "lzip" program. */
+int canLzip(void);
+
+/* Return true if this platform can run the "lzma" program. */
+int canLzma(void);
+
+/* Return true if this platform can run the "lzop" program. */
+int canLzop(void);
+
+/* Return true if this platform can run the "xz" program. */
+int canXz(void);
+
+/* Return true if this filesystem can handle nodump flags. */
+int canNodump(void);
+
+/* Return true if the file has large i-node number(>0xffffffff). */
+int is_LargeInode(const char *);
+
+/* 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, ...);
+
+/* Dump block of bytes to a file. */
+void dumpfile(const char *filename, void *, size_t);
+
+/* Extracts named reference file to the current directory. */
+void extract_reference_file(const char *);
+/* Copies named reference file to the current directory. */
+void copy_reference_file(const char *);
+
+/* Extracts a list of files to the current directory.
+ * List must be NULL terminated.
+ */
+void extract_reference_files(const char **);
+
+/* Subtract umask from mode */
+mode_t umasked(mode_t expected_mode);
+
+/* Path to working directory for current test */
+extern const char *testworkdir;
+
+#ifndef PROGRAM
+/*
+ * Special interfaces for libarchive test harness.
+ */
+
+#include "archive.h"
+#include "archive_entry.h"
+
+/* ACL structure */
+struct archive_test_acl_t {
+ int type; /* Type of ACL */
+ int permset; /* Permissions for this class of users. */
+ int tag; /* Owner, User, Owning group, group, other, etc. */
+ int qual; /* GID or UID of user/group, depending on tag. */
+ const char *name; /* Name of user/group, depending on tag. */
+};
+
+/* Set ACLs */
+int assertion_entry_set_acls(const char *, int, struct archive_entry *,
+ struct archive_test_acl_t *, int);
+
+/* Compare ACLs */
+int assertion_entry_compare_acls(const char *, int, struct archive_entry *,
+ struct archive_test_acl_t *, int, int, int);
+
+/* Special customized read-from-memory interface. */
+int read_open_memory(struct archive *, const void *, size_t, size_t);
+/* _minimal version exercises a slightly different set of libarchive APIs. */
+int read_open_memory_minimal(struct archive *, const void *, size_t, size_t);
+/* _seek version produces a seekable file. */
+int read_open_memory_seek(struct archive *, const void *, size_t, size_t);
+
+/* Versions of above that accept an archive argument for additional info. */
+#define assertA(e) assertion_assert(__FILE__, __LINE__, (e), #e, (a))
+#define assertEqualIntA(a,v1,v2) \
+ assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
+#define assertEqualStringA(a,v1,v2) \
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a), 0)
+
+#else /* defined(PROGRAM) */
+/*
+ * Special interfaces for program test harness.
+ */
+
+/* Pathname of exe to be tested. */
+extern const char *testprogfile;
+/* Name of exe to use in printf-formatted command strings. */
+/* On Windows, this includes leading/trailing quotes. */
+extern const char *testprog;
+
+void assertVersion(const char *prog, const char *base);
+
+#endif /* defined(PROGRAM) */
+
+#ifdef USE_DMALLOC
+#include <dmalloc.h>
+#endif
+
+#endif /* TEST_COMMON_H */
diff --git a/libarchive/test/main.c b/test_utils/test_main.c
index 46685f8b83a3..2ae6b38db06e 100644
--- a/libarchive/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
@@ -54,22 +57,6 @@
#include <time.h>
/*
- * This same file is used pretty much verbatim for all test harnesses.
- *
- * The next few lines are the only differences.
- * TODO: Move this into a separate configuration header, have all test
- * suites share one copy of this file.
- */
-__FBSDID("$FreeBSD: head/lib/libarchive/test/main.c 201247 2009-12-30 05:59:21Z kientzle $");
-#define KNOWNREF "test_compat_gtar_1.tar.uu"
-#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */
-#undef PROGRAM /* Testing a library, not a program. */
-#define LIBRARY "libarchive"
-#define EXTRA_DUMP(x) archive_error_string((struct archive *)(x))
-#define EXTRA_ERRNO(x) archive_errno((struct archive *)(x))
-#define EXTRA_VERSION archive_version_details()
-
-/*
*
* Windows support routines
*
@@ -1910,8 +1897,10 @@ assertion_nodump(const char *file, int line, const char *pathname)
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);
@@ -1921,14 +1910,31 @@ assertion_nodump(const char *file, int line, const char *pathname)
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);
@@ -1942,6 +1948,117 @@ assertion_nodump(const char *file, int line, const char *pathname)
return (1);
}
+#ifdef PROGRAM
+static void assert_version_id(char **qq, size_t *ss)
+{
+ char *q = *qq;
+ size_t s = *ss;
+
+ /* Version number is a series of digits and periods. */
+ while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
+ ++q;
+ --s;
+ }
+
+ if (q[0] == 'd' && q[1] == 'e' && q[2] == 'v') {
+ q += 3;
+ s -= 3;
+ }
+
+ /* Skip a single trailing a,b,c, or d. */
+ if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
+ ++q;
+
+ /* Version number terminated by space. */
+ failure("No space after version: ``%s''", q);
+ assert(s > 1);
+ failure("No space after version: ``%s''", q);
+ assert(*q == ' ');
+
+ ++q; --s;
+
+ *qq = q;
+ *ss = s;
+}
+
+
+/*
+ * Check program version
+ */
+void assertVersion(const char *prog, const char *base)
+{
+ int r;
+ char *p, *q;
+ size_t s;
+ unsigned int prog_len = strlen(base);
+
+ r = systemf("%s --version >version.stdout 2>version.stderr", prog);
+ if (r != 0)
+ r = systemf("%s -W version >version.stdout 2>version.stderr",
+ prog);
+
+ failure("Unable to run either %s --version or %s -W version",
+ prog, prog);
+ if (!assert(r == 0))
+ return;
+
+ /* --version should generate nothing to stdout. */
+ assertEmptyFile("version.stderr");
+
+ /* Verify format of version message. */
+ q = p = slurpfile(&s, "version.stdout");
+
+ /* Version message should start with name of program, then space. */
+ assert(s > prog_len + 1);
+
+ failure("Version must start with '%s': ``%s''", base, p);
+ if (!assertEqualMem(q, base, prog_len)) {
+ free(p);
+ return;
+ }
+
+ q += prog_len; s -= prog_len;
+
+ assert(*q == ' ');
+ q++; s--;
+
+ assert_version_id(&q, &s);
+
+ /* Separator. */
+ failure("No `-' between program name and versions: ``%s''", p);
+ assertEqualMem(q, "- ", 2);
+ q += 2; s -= 2;
+
+ failure("Not long enough for libarchive version: ``%s''", p);
+ assert(s > 11);
+
+ failure("Libarchive version must start with `libarchive': ``%s''", p);
+ assertEqualMem(q, "libarchive ", 11);
+
+ q += 11; s -= 11;
+
+ assert_version_id(&q, &s);
+
+ /* Skip arbitrary third-party version numbers. */
+ while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' ||
+ isalnum(*q))) {
+ ++q;
+ --s;
+ }
+
+ /* All terminated by end-of-line. */
+ assert(s >= 1);
+
+ /* Skip an optional CR character (e.g., Windows) */
+ failure("Version output must end with \\n or \\r\\n");
+
+ if (*q == '\r') { ++q; --s; }
+ assertEqualMem(q, "\n", 1);
+
+ free(p);
+}
+#endif /* PROGRAM */
+
/*
*
* UTILITIES for use by tests.
@@ -2157,9 +2274,10 @@ canNodump(void)
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
canNodump(void)
{
@@ -2170,22 +2288,48 @@ canNodump(void)
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);
+#ifdef FS_NODUMP_FL
+ if (flags & FS_NODUMP_FL)
+#else
if (flags & EXT2_NODUMP_FL)
+#endif
return (1);
return (0);
}
@@ -2429,23 +2573,33 @@ extract_reference_files(const char **names)
extract_reference_file(*names++);
}
+#ifndef PROGRAM
/* Set ACLs */
-void
-archive_test_set_acls(struct archive_entry *ae,
+int
+assertion_entry_set_acls(const char *file, int line, struct archive_entry *ae,
struct archive_test_acl_t *acls, int n)
{
- int i;
+ int i, r, ret;
+
+ assertion_count(file, line);
+ ret = 0;
archive_entry_acl_clear(ae);
for (i = 0; i < n; i++) {
- failure("type=%#010x, permset=%#010x, tag=%d, qual=%d name=%s",
+ r = archive_entry_acl_add_entry(ae,
acls[i].type, acls[i].permset, acls[i].tag,
acls[i].qual, acls[i].name);
- assertEqualInt(ARCHIVE_OK,
- archive_entry_acl_add_entry(ae,
- acls[i].type, acls[i].permset, acls[i].tag,
- acls[i].qual, acls[i].name));
+ if (r != 0) {
+ ret = 1;
+ failure_start(file, line, "type=%#010x, ",
+ "permset=%#010x, tag=%d, qual=%d name=%s",
+ acls[i].type, acls[i].permset, acls[i].tag,
+ acls[i].qual, acls[i].name);
+ failure_finish(NULL);
+ }
}
+
+ return (ret);
}
static int
@@ -2482,16 +2636,20 @@ archive_test_acl_match(struct archive_test_acl_t *acl, int type, int permset,
}
/* Compare ACLs */
-void
-archive_test_compare_acls(struct archive_entry *ae,
- struct archive_test_acl_t *acls, int cnt, int want_type, int mode)
+int
+assertion_entry_compare_acls(const char *file, int line,
+ struct archive_entry *ae, struct archive_test_acl_t *acls, int cnt,
+ int want_type, int mode)
{
int *marker;
- int i, r, n;
+ int i, r, n, ret;
int type, permset, tag, qual;
int matched;
const char *name;
+ assertion_count(file, line);
+
+ ret = 0;
n = 0;
marker = malloc(sizeof(marker[0]) * cnt);
@@ -2502,10 +2660,11 @@ archive_test_compare_acls(struct archive_entry *ae,
}
}
- failure("No ACL's to compare, type mask: %d", want_type);
- assert(n > 0);
- if (n == 0)
- return;
+ if (n == 0) {
+ failure_start(file, line, "No ACL's to compare, type mask: %d",
+ want_type);
+ return (1);
+ }
while (0 == (r = archive_entry_acl_next(ae, want_type,
&type, &permset, &tag, &qual, &name))) {
@@ -2520,40 +2679,83 @@ archive_test_compare_acls(struct archive_entry *ae,
}
if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
&& tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
- if (!matched) printf("No match for user_obj perm\n");
- failure("USER_OBJ permset (%02o) != user mode (%02o)",
- permset, 07 & (mode >> 6));
- assert((permset << 6) == (mode & 0700));
+ if (!matched) {
+ failure_start(file, line, "No match for "
+ "user_obj perm");
+ failure_finish(NULL);
+ ret = 1;
+ }
+ if ((permset << 6) != (mode & 0700)) {
+ failure_start(file, line, "USER_OBJ permset "
+ "(%02o) != user mode (%02o)", permset,
+ 07 & (mode >> 6));
+ failure_finish(NULL);
+ ret = 1;
+ }
} else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
&& tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
- if (!matched) printf("No match for group_obj perm\n");
- failure("GROUP_OBJ permset %02o != group mode %02o",
- permset, 07 & (mode >> 3));
- assert((permset << 3) == (mode & 0070));
+ if (!matched) {
+ failure_start(file, line, "No match for "
+ "group_obj perm");
+ failure_finish(NULL);
+ ret = 1;
+ }
+ if ((permset << 3) != (mode & 0070)) {
+ failure_start(file, line, "GROUP_OBJ permset "
+ "(%02o) != group mode (%02o)", permset,
+ 07 & (mode >> 3));
+ failure_finish(NULL);
+ ret = 1;
+ }
} else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
&& tag == ARCHIVE_ENTRY_ACL_OTHER) {
- if (!matched) printf("No match for other perm\n");
- failure("OTHER permset (%02o) != other mode (%02o)",
- permset, mode & 07);
- assert((permset << 0) == (mode & 0007));
- } else {
- failure("Could not find match for ACL "
- "(type=%#010x,permset=%#010x,tag=%d,qual=%d,"
+ if (!matched) {
+ failure_start(file, line, "No match for "
+ "other perm");
+ failure_finish(NULL);
+ ret = 1;
+ }
+ if ((permset << 0) != (mode & 0007)) {
+ failure_start(file, line, "OTHER permset "
+ "(%02o) != other mode (%02o)", permset,
+ mode & 07);
+ failure_finish(NULL);
+ ret = 1;
+ }
+ } else if (matched != 1) {
+ failure_start(file, line, "Could not find match for "
+ "ACL (type=%#010x,permset=%#010x,tag=%d,qual=%d,"
"name=``%s'')", type, permset, tag, qual, name);
- assert(matched == 1);
+ failure_finish(NULL);
+ ret = 1;
}
}
- assertEqualInt(ARCHIVE_EOF, r);
- if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
- assert((mode_t)(mode & 0777) == (archive_entry_mode(ae)
- & 0777));
- failure("Could not find match for ACL "
- "(type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s'')",
- acls[marker[0]].type, acls[marker[0]].permset,
- acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
- assert(n == 0); /* Number of ACLs not matched should == 0 */
+ if (r != ARCHIVE_EOF) {
+ failure_start(file, line, "Should not exit before EOF");
+ failure_finish(NULL);
+ ret = 1;
+ }
+ if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 &&
+ (mode_t)(mode & 0777) != (archive_entry_mode(ae) & 0777)) {
+ failure_start(file, line, "Mode (%02o) and entry mode (%02o) "
+ "mismatch", mode, archive_entry_mode(ae));
+ failure_finish(NULL);
+ ret = 1;
+ }
+ if (n != 0) {
+ failure_start(file, line, "Could not find match for ACL "
+ "(type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s'')",
+ acls[marker[0]].type, acls[marker[0]].permset,
+ acls[marker[0]].tag, acls[marker[0]].qual,
+ acls[marker[0]].name);
+ failure_finish(NULL);
+ ret = 1;
+ /* Number of ACLs not matched should == 0 */
+ }
free(marker);
+ return (ret);
}
+#endif /* !defined(PROGRAM) */
/*
*