diff options
Diffstat (limited to 'archivers/libarchive/files/tar/test')
23 files changed, 4744 insertions, 835 deletions
diff --git a/archivers/libarchive/files/tar/test/CMakeLists.txt b/archivers/libarchive/files/tar/test/CMakeLists.txt new file mode 100644 index 00000000000..6064e142407 --- /dev/null +++ b/archivers/libarchive/files/tar/test/CMakeLists.txt @@ -0,0 +1,67 @@ +############################################ +# +# How to build bsdtar_test +# +############################################ +IF(ENABLE_TAR AND ENABLE_TEST) + SET(bsdtar_test_SOURCES + ../getdate.c + main.c + test.h + test_0.c + test_basic.c + test_copy.c + test_empty_mtree.c + test_getdate.c + test_help.c + test_option_T_upper.c + test_option_q.c + test_option_r.c + test_option_s.c + test_patterns.c + test_stdio.c + test_strip_components.c + test_symlink_dir.c + test_version.c + test_windows.c + ) + IF(WIN32 AND NOT CYGWIN) + LIST(APPEND bsdtar_test_SOURCES ../bsdtar_windows.c) + LIST(APPEND bsdtar_test_SOURCES ../bsdtar_windows.h) + ENDIF(WIN32 AND NOT CYGWIN) + + # + # Register target + # + ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES}) + SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H) + + # + # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. + # + GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h + ${CMAKE_CURRENT_LIST_FILE} ${bsdtar_test_SOURCES}) + SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_BINARY_DIR}) + + # list.h has a line DEFINE_TEST(testname) for every + # test. We can use that to define the tests for cmake by + # defining a DEFINE_TEST macro and reading list.h in. + MACRO (DEFINE_TEST _testname) + ADD_TEST_28( + NAME bsdtar_${_testname} + COMMAND bsdtar_test -vv + -p $<TARGET_FILE:bsdtar> + -r ${CMAKE_CURRENT_SOURCE_DIR} + ${_testname}) + ENDMACRO (DEFINE_TEST _testname) + + INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) + + # Experimental new test handling + ADD_CUSTOM_TARGET(run_bsdtar_test + COMMAND bsdtar_test -p ${BSDTAR} -r ${CMAKE_CURRENT_SOURCE_DIR}) + ADD_DEPENDENCIES(run_bsdtar_test bsdtar) + ADD_DEPENDENCIES(run_all_tests run_bsdtar_test) + +ENDIF (ENABLE_TAR AND ENABLE_TEST) diff --git a/archivers/libarchive/files/tar/test/list.h b/archivers/libarchive/files/tar/test/list.h new file mode 100644 index 00000000000..4b91fb68416 --- /dev/null +++ b/archivers/libarchive/files/tar/test/list.h @@ -0,0 +1,16 @@ +DEFINE_TEST(test_0) +DEFINE_TEST(test_basic) +DEFINE_TEST(test_copy) +DEFINE_TEST(test_empty_mtree) +DEFINE_TEST(test_getdate) +DEFINE_TEST(test_help) +DEFINE_TEST(test_option_T_upper) +DEFINE_TEST(test_option_q) +DEFINE_TEST(test_option_r) +DEFINE_TEST(test_option_s) +DEFINE_TEST(test_patterns) +DEFINE_TEST(test_stdio) +DEFINE_TEST(test_strip_components) +DEFINE_TEST(test_symlink_dir) +DEFINE_TEST(test_version) +DEFINE_TEST(test_windows) diff --git a/archivers/libarchive/files/tar/test/main.c b/archivers/libarchive/files/tar/test/main.c index 27bb48d4094..6028d7789a4 100644 --- a/archivers/libarchive/files/tar/test/main.c +++ b/archivers/libarchive/files/tar/test/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2003-2009 Tim Kientzle * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,12 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * Various utility routines useful for test programs. - * Each test program is linked against this file. - */ #include "test.h" - #include <errno.h> #include <locale.h> #include <stdarg.h> @@ -38,148 +33,319 @@ * 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 PROGRAM "bsdtar" /* Name of program being tested. */ -#define ENVBASE "BSDTAR" /* Prefix for environment variables. */ +__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. */ +#undef LIBRARY /* Not testing a library. */ #undef EXTRA_DUMP /* How to dump extra data */ /* How to generate extra version info. */ #define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "") -__FBSDID("$FreeBSD: src/usr.bin/tar/test/main.c,v 1.3 2008/06/15 10:07:54 kientzle Exp $"); /* - * "list.h" is simply created by "grep DEFINE_TEST"; it has - * a line like - * DEFINE_TEST(test_function) - * for each test. - * Include it here with a suitable DEFINE_TEST to declare all of the - * test functions. + * + * 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. */ -#undef DEFINE_TEST -#define DEFINE_TEST(name) void name(void); -#include "list.h" +#if defined(_WIN32) && !defined(__CYGWIN__) +#include <io.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 + +#if defined(_WIN32) && !defined(__CYGWIN__) +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); +} + +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_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + return (0); + r = GetFileInformationByHandle(h, bhfi); + CloseHandle(h); + return (r); +} +#endif -/* Interix doesn't define these in a standard header. */ -#if __INTERIX__ -extern char *optarg; -extern int optind; +#if defined(HAVE__CrtSetReportMode) +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 for successful tests. */ +/* Default is to remove temp dirs and log data for successful tests. */ static int keep_temp_files = 0; -/* Default is to print some basic information about each test. */ -static int quiet_flag = 0; -/* Default is to summarize repeated failures. */ -static int verbose = 0; -/* Cumulative count of component failures. */ +/* 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 skipped component tests. */ +/* Cumulative count of reported skips. */ static int skips = 0; -/* Cumulative count of assertions. */ +/* Cumulative count of assertions checked. */ static int assertions = 0; /* Directory where uuencoded reference files can be found. */ -static char *refdir; +static const char *refdir; /* - * My own implementation of the standard assert() macro emits the - * message in the same format as GCC (file:line: message). - * It also includes some additional useful information. - * This makes it a lot easier to skim through test failures in - * Emacs. ;-) - * - * It also supports a few special features specifically to simplify - * test harnesses: - * failure(fmt, args) -- Stores a text string that gets - * printed if the following assertion fails, good for - * explaining subtle tests. + * Report log information selectively to console and/or disk log. */ -static char msg[4096]; - -/* - * For each test source file, we remember how many times each - * failure was reported. - */ -static const char *failed_filename = NULL; -static struct line { - int line; - int count; -} failed_lines[1000]; - -/* - * Count this failure; return the number of previous failures. - */ -static int -previous_failures(const char *filename, int line) +static int log_console = 0; +static FILE *logfile; +static void +vlogprintf(const char *fmt, va_list ap) { - unsigned int i; - int count; +#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 +} - if (failed_filename == NULL || strcmp(failed_filename, filename) != 0) - memset(failed_lines, 0, sizeof(failed_lines)); - failed_filename = filename; +static void +logprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vlogprintf(fmt, ap); + va_end(ap); +} - for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { - if (failed_lines[i].line == line) { - count = failed_lines[i].count; - failed_lines[i].count++; - return (count); - } - if (failed_lines[i].line == 0) { - failed_lines[i].line = line; - failed_lines[i].count = 1; - return (0); - } - } - return (0); +/* 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; + 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 noticably. */ static const char *test_filename; static int test_line; static void *test_extra; -void test_setup(const char *filename, int line) +void assertion_setup(const char *filename, int line) { test_filename = filename; test_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); */ +} + /* - * Inform user that we're skipping a test. + * For each test source file, we remember how many times each + * assertion was reported. Cleared before each new test, + * used by test_summarize(). */ -void -test_skipping(const char *fmt, ...) +static struct line { + int count; + int skip; +} failed_lines[10000]; + +/* 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; - if (previous_failures(test_filename, test_line)) - return; + /* Record another failure for this line. */ + ++failures; + /* test_filename = filename; */ + failed_lines[line].count++; + + /* Determine whether to log header to console. */ + switch (verbosity) { + case VERBOSITY_FULL: + log_console = 1; + break; + case VERBOSITY_LIGHT_REPORT: + log_console = (failed_lines[line].count < 2); + break; + default: + log_console = 0; + } + /* Log file:line header for this failure */ va_start(ap, fmt); - fprintf(stderr, " *** SKIPPING: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); +#if _MSC_VER + logprintf("%s(%d): ", filename, line); +#else + logprintf("%s:%d: ", filename, line); +#endif + vlogprintf(fmt, ap); va_end(ap); - ++skips; + 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; } -/* Common handling of failed tests. */ +/* 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 -report_failure(void *extra) +failure_finish(void *extra) { - if (msg[0] != '\0') { - fprintf(stderr, " Description: %s\n", msg); - msg[0] = '\0'; - } - + (void)extra; /* UNUSED (maybe) */ #ifdef EXTRA_DUMP if (extra != NULL) - fprintf(stderr, " detail: %s\n", EXTRA_DUMP(extra)); -#else - (void)extra; /* UNUSED */ + logprintf(" detail: %s\n", EXTRA_DUMP(extra)); #endif if (dump_on_failure) { @@ -190,203 +356,154 @@ report_failure(void *extra) } } -/* - * Summarize repeated failures in the just-completed test file. - * The reports above suppress multiple failures from the same source - * line; this reports on any tests that did fail multiple times. - */ -static int -summarize_comparator(const void *a0, const void *b0) -{ - const struct line *a = a0, *b = b0; - if (a->line == 0 && b->line == 0) - return (0); - if (a->line == 0) - return (1); - if (b->line == 0) - return (-1); - return (a->line - b->line); -} - -static void -summarize(void) -{ - unsigned int i; - - qsort(failed_lines, sizeof(failed_lines)/sizeof(failed_lines[0]), - sizeof(failed_lines[0]), summarize_comparator); - for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { - if (failed_lines[i].line == 0) - break; - if (failed_lines[i].count > 1) - fprintf(stderr, "%s:%d: Failed %d times\n", - failed_filename, failed_lines[i].line, - failed_lines[i].count); - } - /* Clear the failure history for the next file. */ - memset(failed_lines, 0, sizeof(failed_lines)); -} - -/* Set up a message to display only after a test fails. */ +/* Inform user that we're skipping some checks. */ void -failure(const char *fmt, ...) +test_skipping(const char *fmt, ...) { + char buff[1024]; va_list ap; + va_start(ap, fmt); - vsprintf(msg, fmt, ap); + vsprintf(buff, fmt, ap); va_end(ap); + /* failure_start() isn't quite right, but is awfully convenient. */ + failure_start(test_filename, test_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[test_line].skip = 1; + ++skips; } +/* + * + * ASSERTIONS + * + */ + /* Generic assert() just displays the failed condition. */ int -test_assert(const char *file, int line, int value, const char *condition, void *extra) +assertion_assert(const char *file, int line, int value, + const char *condition, void *extra) { - ++assertions; - if (value) { - msg[0] = '\0'; - return (value); + assertion_count(file, line); + if (!value) { + failure_start(file, line, "Assertion failed: %s", condition); + failure_finish(extra); } - failures ++; - if (!verbose && previous_failures(file, line)) - return (value); - fprintf(stderr, "%s:%d: Assertion failed\n", file, line); - fprintf(stderr, " Condition: %s\n", condition); - report_failure(extra); return (value); } -/* assertEqualInt() displays the values of the two integers. */ +/* chdir() and report any errors */ int -test_assert_equal_int(const char *file, int line, - int v1, const char *e1, int v2, const char *e2, void *extra) +assertion_chdir(const char *file, int line, const char *pathname) { - ++assertions; - if (v1 == v2) { - msg[0] = '\0'; + assertion_count(file, line); + if (chdir(pathname) == 0) return (1); - } - failures ++; - if (!verbose && previous_failures(file, line)) - return (0); - fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n", - file, line); - fprintf(stderr, " %s=%d\n", e1, v1); - fprintf(stderr, " %s=%d\n", e2, v2); - report_failure(extra); + failure_start(file, line, "chdir(\"%s\")", pathname); + failure_finish(NULL); return (0); + } -static void strdump(const char *p) +/* 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); +} + +static void strdump(const char *e, const char *p) +{ + const char *q = p; + + logprintf(" %s = ", e); if (p == NULL) { - fprintf(stderr, "(null)"); + logprintf("NULL"); return; } - fprintf(stderr, "\""); + logprintf("\""); while (*p != '\0') { unsigned int c = 0xff & *p++; switch (c) { - case '\a': fprintf(stderr, "\a"); break; - case '\b': fprintf(stderr, "\b"); break; - case '\n': fprintf(stderr, "\n"); break; - case '\r': fprintf(stderr, "\r"); break; + case '\a': printf("\a"); break; + case '\b': printf("\b"); break; + case '\n': printf("\n"); break; + case '\r': printf("\r"); break; default: if (c >= 32 && c < 127) - fprintf(stderr, "%c", c); + logprintf("%c", c); else - fprintf(stderr, "\\x%02X", c); + logprintf("\\x%02X", c); } } - fprintf(stderr, "\""); + logprintf("\""); + logprintf(" (length %d)\n", q == NULL ? -1 : (int)strlen(q)); } -/* assertEqualString() displays the values of the two strings. */ +/* Verify two strings are equal, dump them if not. */ int -test_assert_equal_string(const char *file, int line, +assertion_equal_string(const char *file, int line, const char *v1, const char *e1, const char *v2, const char *e2, void *extra) { - ++assertions; - if (v1 == NULL || v2 == NULL) { - if (v1 == v2) { - msg[0] = '\0'; - return (1); - } - } else if (strcmp(v1, v2) == 0) { - msg[0] = '\0'; + assertion_count(file, line); + if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0)) return (1); - } - failures ++; - if (!verbose && previous_failures(file, line)) - return (0); - fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n", - file, line); - fprintf(stderr, " %s = ", e1); - strdump(v1); - fprintf(stderr, " (length %d)\n", v1 == NULL ? 0 : strlen(v1)); - fprintf(stderr, " %s = ", e2); - strdump(v2); - fprintf(stderr, " (length %d)\n", v2 == NULL ? 0 : strlen(v2)); - report_failure(extra); + failure_start(file, line, "%s != %s", e1, e2); + strdump(e1, v1); + strdump(e2, v2); + failure_finish(extra); return (0); } -static void wcsdump(const wchar_t *w) +static void +wcsdump(const char *e, const wchar_t *w) { + logprintf(" %s = ", e); if (w == NULL) { - fprintf(stderr, "(null)"); + logprintf("(null)"); return; } - fprintf(stderr, "\""); + logprintf("\""); while (*w != L'\0') { unsigned int c = *w++; if (c >= 32 && c < 127) - fprintf(stderr, "%c", c); + logprintf("%c", c); else if (c < 256) - fprintf(stderr, "\\x%02X", c); + logprintf("\\x%02X", c); else if (c < 0x10000) - fprintf(stderr, "\\u%04X", c); + logprintf("\\u%04X", c); else - fprintf(stderr, "\\U%08X", c); + logprintf("\\U%08X", c); } - fprintf(stderr, "\""); + logprintf("\"\n"); } -/* assertEqualWString() displays the values of the two strings. */ +/* Verify that two wide strings are equal, dump them if not. */ int -test_assert_equal_wstring(const char *file, int line, +assertion_equal_wstring(const char *file, int line, const wchar_t *v1, const char *e1, const wchar_t *v2, const char *e2, void *extra) { - ++assertions; - if (v1 == NULL) { - if (v2 == NULL) { - msg[0] = '\0'; - return (1); - } - } else if (v2 == NULL) { - if (v1 == NULL) { - msg[0] = '\0'; - return (1); - } - } else if (wcscmp(v1, v2) == 0) { - msg[0] = '\0'; + assertion_count(file, line); + if (v1 == v2 || wcscmp(v1, v2) == 0) return (1); - } - failures ++; - if (!verbose && previous_failures(file, line)) - return (0); - fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n", - file, line); - fprintf(stderr, " %s = ", e1); - wcsdump(v1); - fprintf(stderr, "\n"); - fprintf(stderr, " %s = ", e2); - wcsdump(v2); - fprintf(stderr, "\n"); - report_failure(extra); + failure_start(file, line, "%s != %s", e1, e2); + wcsdump(e1, v1); + wcsdump(e2, v2); + failure_finish(extra); return (0); } @@ -401,226 +518,1051 @@ 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) { - fprintf(stderr, "%04x", i + offset); + 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 = '_'; - fprintf(stderr, "%c%02x", sep, 0xff & (int)p[i+j]); + logprintf("%c%02x", sep, 0xff & (int)p[i+j]); if (ref != NULL && p[i + j] == ref[i + j]) sep = ' '; } for (; j < 16; j++) { - fprintf(stderr, "%c ", sep); + logprintf("%c ", sep); sep = ' '; } - fprintf(stderr, "%c", sep); + logprintf("%c", sep); for (j=0; j < 16 && i + j < l; j++) { int c = p[i + j]; if (c >= ' ' && c <= 126) - fprintf(stderr, "%c", c); + logprintf("%c", c); else - fprintf(stderr, "."); + logprintf("."); } - fprintf(stderr, "\n"); + logprintf("\n"); } } -/* assertEqualMem() displays the values of the two memory blocks. */ -/* TODO: For long blocks, hexdump the first bytes that actually differ. */ +/* Verify that two blocks of memory are the same, display the first + * block of differences if they're not. */ int -test_assert_equal_mem(const char *file, int line, - const char *v1, const char *e1, - const char *v2, const char *e2, +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) { - ++assertions; - if (v1 == NULL || v2 == NULL) { - if (v1 == v2) { - msg[0] = '\0'; - return (1); - } - } else if (memcmp(v1, v2, l) == 0) { - msg[0] = '\0'; + 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); + + 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; } - failures ++; - if (!verbose && previous_failures(file, line)) - return (0); - fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n", - file, line); - fprintf(stderr, " size %s = %d\n", ld, (int)l); - fprintf(stderr, " Dump of %s\n", e1); - hexdump(v1, v2, l < 32 ? l : 32, 0); - fprintf(stderr, " Dump of %s\n", e2); - hexdump(v2, v1, l < 32 ? l : 32, 0); - fprintf(stderr, "\n"); - report_failure(extra); + logprintf(" Dump of %s\n", e1); + hexdump(v1, v2, l < 64 ? l : 64, offset); + logprintf(" Dump of %s\n", e2); + hexdump(v2, v1, l < 64 ? l : 64, offset); + logprintf("\n"); + failure_finish(extra); return (0); } +/* Verify that the named file exists and is empty. */ int -test_assert_empty_file(const char *f1fmt, ...) +assertion_empty_file(const char *f1fmt, ...) { char buff[1024]; char f1[1024]; struct stat st; va_list ap; ssize_t s; - int fd; - + FILE *f; + assertion_count(test_filename, test_line); va_start(ap, f1fmt); vsprintf(f1, f1fmt, ap); va_end(ap); if (stat(f1, &st) != 0) { - fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1); - report_failure(NULL); + failure_start(test_filename, test_line, "Stat failed: %s", f1); + failure_finish(NULL); return (0); } if (st.st_size == 0) return (1); - failures ++; - if (!verbose && previous_failures(test_filename, test_line)) - return (0); - - fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1); - fprintf(stderr, " File size: %d\n", (int)st.st_size); - fprintf(stderr, " Contents:\n"); - fd = open(f1, O_RDONLY); - if (fd < 0) { - fprintf(stderr, " Unable to open %s\n", f1); + failure_start(test_filename, test_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 = sizeof(buff) < st.st_size ? sizeof(buff) : st.st_size; - s = read(fd, buff, s); + 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); } - report_failure(NULL); + failure_finish(NULL); return (0); } -/* assertEqualFile() asserts that two files have the same contents. */ +/* Verify that the named file exists and is not empty. */ +int +assertion_non_empty_file(const char *f1fmt, ...) +{ + char f1[1024]; + struct stat st; + va_list ap; + + assertion_count(test_filename, test_line); + va_start(ap, f1fmt); + vsprintf(f1, f1fmt, ap); + va_end(ap); + + if (stat(f1, &st) != 0) { + failure_start(test_filename, test_line, "Stat failed: %s", f1); + failure_finish(NULL); + return (0); + } + if (st.st_size == 0) { + failure_start(test_filename, test_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 -test_assert_equal_file(const char *f1, const char *f2pattern, ...) +assertion_equal_file(const char *fn1, const char *f2pattern, ...) { - char f2[1024]; + char fn2[1024]; va_list ap; char buff1[1024]; char buff2[1024]; - int fd1, fd2; + FILE *f1, *f2; int n1, n2; + assertion_count(test_filename, test_line); va_start(ap, f2pattern); - vsprintf(f2, f2pattern, ap); + vsprintf(fn2, f2pattern, ap); va_end(ap); - fd1 = open(f1, O_RDONLY); - fd2 = open(f2, O_RDONLY); + f1 = fopen(fn1, "rb"); + f2 = fopen(fn2, "rb"); for (;;) { - n1 = read(fd1, buff1, sizeof(buff1)); - n2 = read(fd2, buff2, sizeof(buff2)); + n1 = fread(buff1, 1, sizeof(buff1), f1); + n2 = fread(buff2, 1, sizeof(buff2), f2); if (n1 != n2) break; - if (n1 == 0 && n2 == 0) + if (n1 == 0 && n2 == 0) { + fclose(f1); + fclose(f2); return (1); + } if (memcmp(buff1, buff2, n1) != 0) break; } - failures ++; - if (!verbose && previous_failures(test_filename, test_line)) - return (0); - fprintf(stderr, "%s:%d: Files are not identical\n", - test_filename, test_line); - fprintf(stderr, " file1=\"%s\"\n", f1); - fprintf(stderr, " file2=\"%s\"\n", f2); - report_failure(test_extra); + fclose(f1); + fclose(f2); + failure_start(test_filename, test_line, "Files not identical"); + logprintf(" file1=\"%s\"\n", fn1); + logprintf(" file2=\"%s\"\n", fn2); + failure_finish(test_extra); return (0); } +/* Verify that the named file does exist. */ int -test_assert_file_exists(const char *fpattern, ...) +assertion_file_exists(const char *fpattern, ...) { char f[1024]; va_list ap; + assertion_count(test_filename, test_line); va_start(ap, fpattern); vsprintf(f, fpattern, ap); va_end(ap); +#if defined(_WIN32) && !defined(__CYGWIN__) + if (!_access(f, 0)) + return (1); +#else if (!access(f, F_OK)) return (1); - if (!previous_failures(test_filename, test_line)) { - fprintf(stderr, "%s:%d: File doesn't exist\n", - test_filename, test_line); - fprintf(stderr, " file=\"%s\"\n", f); - report_failure(test_extra); - } +#endif + failure_start(test_filename, test_line, "File should exist: %s", f); + failure_finish(test_extra); return (0); } +/* Verify that the named file doesn't exist. */ int -test_assert_file_not_exists(const char *fpattern, ...) +assertion_file_not_exists(const char *fpattern, ...) { char f[1024]; va_list ap; + assertion_count(test_filename, test_line); va_start(ap, fpattern); vsprintf(f, fpattern, ap); va_end(ap); +#if defined(_WIN32) && !defined(__CYGWIN__) + if (_access(f, 0)) + return (1); +#else if (access(f, F_OK)) return (1); - if (!previous_failures(test_filename, test_line)) { - fprintf(stderr, "%s:%d: File exists and shouldn't\n", - test_filename, test_line); - fprintf(stderr, " file=\"%s\"\n", f); - report_failure(test_extra); - } +#endif + failure_start(test_filename, test_line, "File should not exist: %s", f); + failure_finish(test_extra); return (0); } -/* assertFileContents() asserts the contents of a file. */ +/* Compare the contents of a file to a block of memory. */ int -test_assert_file_contents(const void *buff, int s, const char *fpattern, ...) +assertion_file_contents(const void *buff, int s, const char *fpattern, ...) { - char f[1024]; + char fn[1024]; va_list ap; char *contents; - int fd; + FILE *f; int n; + assertion_count(test_filename, test_line); va_start(ap, fpattern); - vsprintf(f, fpattern, ap); + vsprintf(fn, fpattern, ap); va_end(ap); - fd = open(f, O_RDONLY); + f = fopen(fn, "rb"); + if (f == NULL) { + failure_start(test_filename, test_line, + "File should exist: %s", fn); + failure_finish(test_extra); + return (0); + } contents = malloc(s * 2); - n = read(fd, contents, s * 2); + n = fread(contents, 1, s * 2, f); + fclose(f); if (n == s && memcmp(buff, contents, s) == 0) { free(contents); return (1); } - failures ++; - if (!previous_failures(test_filename, test_line)) { - fprintf(stderr, "%s:%d: File contents don't match\n", - test_filename, test_line); - fprintf(stderr, " file=\"%s\"\n", f); - if (n > 0) - hexdump(contents, buff, n, 0); - else { - fprintf(stderr, " File empty, contents should be:\n"); - hexdump(buff, NULL, s, 0); + failure_start(test_filename, test_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(test_extra); + free(contents); + return (0); +} + +/* Check the contents of a text file, being tolerant of line endings. */ +int +assertion_text_file_contents(const char *buff, const char *fn) +{ + char *contents; + const char *btxt, *ftxt; + FILE *f; + int n, s; + + assertion_count(test_filename, test_line); + f = fopen(fn, "r"); + s = strlen(buff); + contents = malloc(s * 2 + 128); + n = 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; } - report_failure(test_extra); + 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(test_filename, test_line, "Contents don't match"); + logprintf(" file=\"%s\"\n", fn); + if (n > 0) + hexdump(contents, buff, n, 0); + else { + logprintf(" File empty, contents should be:\n"); + hexdump(buff, NULL, s, 0); } + failure_finish(test_extra); 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; + char *p, **actual; + 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. + expected_count = 0; + for (i = 0; lines[i] != NULL; ++i) { + } + expected_count = i; + expected = malloc(sizeof(char *) * expected_count); + 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; + } + actual = malloc(sizeof(char *) * actual_count); + 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); +} + +/* 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 ftime, fbirthtime, fatime, fmtime; + ULARGE_INTEGER wintm; + HANDLE h; + ftime.dwLowDateTime = 0; + ftime.dwHighDateTime = 0; + + assertion_count(file, line); + h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 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': ftime = fatime; break; + case 'b': ftime = fbirthtime; break; + case 'm': ftime = fmtime; break; + } + CloseHandle(h); + if (r == 0) { + failure_start(file, line, "Can't GetFileTime %s\n", pathname); + failure_finish(NULL); + return (0); + } + wintm.LowPart = ftime.dwLowDateTime; + wintm.HighPart = ftime.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; + 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 %ld, %ld 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 %ld.%09ld, expected %ld.%09ld", + 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 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 && 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 != (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 != (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)) + 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, const char *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) { + if (strlen(contents) + != fwrite(contents, 1, strlen(contents), 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 (contents != NULL) { + if ((ssize_t)strlen(contents) + != write(fd, contents, strlen(contents))) { + close(fd); + failure_start(file, line, "Could not write to %s", path); + failure_finish(NULL); + return (0); + } + } + close(fd); + 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); +} + +/* + * + * 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, "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); +} + +/* + * Can this platform run the gzip program? + */ +/* 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 +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 gunzip program? + */ +int +canGunzip(void) +{ + static int tested = 0, value = 0; + if (!tested) { + tested = 1; + if (systemf("gunzip -V %s", redirectArgs) == 0) + value = 1; + } + return (value); +} + +/* + * 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. @@ -634,6 +1576,8 @@ systemf(const char *fmt, ...) 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); @@ -652,112 +1596,263 @@ slurpfile(size_t * sizep, const char *fmt, ...) va_list ap; char *p; ssize_t bytes_read; - int fd; + FILE *f; int r; va_start(ap, fmt); vsprintf(filename, fmt, ap); va_end(ap); - fd = open(filename, O_RDONLY); - if (fd < 0) { + f = fopen(filename, "rb"); + if (f == NULL) { /* Note: No error; non-existent file is okay here. */ return (NULL); } - r = fstat(fd, &st); + r = fstat(fileno(f), &st); if (r != 0) { - fprintf(stderr, "Can't stat file %s\n", filename); - close(fd); + logprintf("Can't stat file %s\n", filename); + fclose(f); return (NULL); } - p = malloc(st.st_size + 1); + p = malloc((size_t)st.st_size + 1); if (p == NULL) { - fprintf(stderr, "Can't allocate %ld bytes of memory to read file %s\n", (long int)st.st_size, filename); - close(fd); + 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 = read(fd, p, st.st_size); + bytes_read = fread(p, 1, (size_t)st.st_size, f); if (bytes_read < st.st_size) { - fprintf(stderr, "Can't read file %s\n", filename); - close(fd); + 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; - close(fd); + fclose(f); return (p); } +/* Read a uuencoded file from the reference directory, decode, and + * write the result into the current directory. */ +#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. */ + /* Not a lot of error checking here; the input better be right. */ + 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) { + n = UUDECODE(*p++) << 18; + n |= UUDECODE(*p++) << 12; + fputc(n >> 16, out); + --bytes; + } + if (bytes > 0) { + n |= UUDECODE(*p++) << 6; + fputc((n >> 8) & 0xFF, out); + --bytes; + } + if (bytes > 0) { + n |= UUDECODE(*p++); + fputc(n & 0xFF, out); + --bytes; + } + } + } + fclose(out); + fclose(in); +} + /* - * "list.h" is automatically generated; it just has a lot of lines like: - * DEFINE_TEST(function_name) - * It's used above to declare all of the test functions. - * We reuse it here to define a list of all tests (functions and 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(n) { n, #n }, -struct { void (*func)(void); const char *name; } tests[] = { +#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 { void (*func)(void); const char *name; int failures; } tests[] = { #include "list.h" }; /* - * Each test is run in a private work dir. Those work dirs - * do have consistent and predictable names, in case a group - * of tests need to collaborate. However, there is no provision - * for requiring that tests run in a certain order. + * Summarize repeated failures in the just-completed test. */ -static int test_run(int i, const char *tmpdir) +static void +test_summarize(const char *filename, int failed) { - int failures_before = failures; + unsigned int i; - if (!quiet_flag) { - printf("%d: %s\n", i, tests[i].name); + switch (verbosity) { + case VERBOSITY_SUMMARY_ONLY: + printf(failed ? "E" : "."); fflush(stdout); + break; + case VERBOSITY_PASSFAIL: + printf(failed ? "FAIL\n" : "ok\n"); + break; } - /* - * Always explicitly chdir() in case the last test moved us to - * a strange place. - */ - if (chdir(tmpdir)) { - fprintf(stderr, - "ERROR: Couldn't chdir to temp dir %s\n", - tmpdir); - exit(1); + 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", + filename, i, failed_lines[i].count); } - /* Create a temp directory for this specific test. */ - if (mkdir(tests[i].name, 0755)) { + /* Clear the failure history for the next file. */ + 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 logfilename[64]; + int failures_before = failures; + 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: %-50s", 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: Couldn't create temp dir ``%s''\n", - tests[i].name); + "ERROR: Can't chdir to top work dir %s\n", tmpdir); exit(1); } - /* Chdir() to that work directory. */ - if (chdir(tests[i].name)) { + /* 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. */ + if (!assertMakeDir(tests[i].name, 0755) + || !assertChdir(tests[i].name)) { fprintf(stderr, - "ERROR: Couldn't chdir to temp dir ``%s''\n", - tests[i].name); + "ERROR: Can't chdir to work dir %s/%s\n", + tmpdir, tests[i].name); exit(1); } /* Explicitly reset the locale before each test. */ setlocale(LC_ALL, "C"); - /* Run the actual test. */ + /* Record the umask before we run the test. */ + umask(oldumask = umask(0)); + /* + * Run the actual test. + */ (*tests[i].func)(); - /* Summarize the results of this test. */ - summarize(); - /* If there were no failures, we can remove the work dir. */ - if (failures == failures_before) { - if (!keep_temp_files && chdir(tmpdir) == 0) { + /* + * Clean up and report afterwards. + */ + /* 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(test_filename, tests[i].failures); + /* 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 (failures == failures_before ? 0 : 1); + return (tests[i].failures); } -static void usage(const char *program) +/* + * + * + * MAIN and support routines. + * + * + */ + +static void +usage(const char *program) { static const int limit = sizeof(tests) / sizeof(tests[0]); int i; @@ -783,92 +1878,129 @@ static void usage(const char *program) exit(1); } -#define UUDECODE(c) (((c) - 0x20) & 0x3f) - -void -extract_reference_file(const char *name) +static char * +get_refdir(const char *d) { - char buff[1024]; - FILE *in, *out; + char tried[512] = { '\0' }; + char buff[128]; + char *pwd, *p; + + /* If a dir was specified, try that */ + if (d != NULL) { + pwd = NULL; + snprintf(buff, sizeof(buff), "%s", d); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, sizeof(tried) - strlen(tried) - 1); + strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1); + goto failure; + } - 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; + /* Get the current dir. */ + pwd = getcwd(NULL, 0); + while (pwd[strlen(pwd) - 1] == '\n') + pwd[strlen(pwd) - 1] = '\0'; + + /* Look for a known file. */ + snprintf(buff, sizeof(buff), "%s", pwd); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, sizeof(tried) - strlen(tried) - 1); + strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1); + + snprintf(buff, sizeof(buff), "%s/test", pwd); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, sizeof(tried) - strlen(tried) - 1); + strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1); + +#if defined(LIBRARY) + snprintf(buff, sizeof(buff), "%s/%s/test", pwd, LIBRARY); +#else + snprintf(buff, sizeof(buff), "%s/%s/test", pwd, PROGRAM); +#endif + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, sizeof(tried) - strlen(tried) - 1); + strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1); + + if (memcmp(pwd, "/usr/obj", 8) == 0) { + snprintf(buff, sizeof(buff), "%s", pwd + 8); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, sizeof(tried) - strlen(tried) - 1); + strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1); + + snprintf(buff, sizeof(buff), "%s/test", pwd + 8); + p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); + if (p != NULL) goto success; + strncat(tried, buff, sizeof(tried) - strlen(tried) - 1); + strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1); } - /* Now, decode the rest and write it. */ - /* Not a lot of error checking here; the input better be right. */ - out = fopen(name, "w"); - while (fgets(buff, sizeof(buff), in) != NULL) { - char *p = buff; - int bytes; - if (memcmp(buff, "end", 3) == 0) - break; +failure: + printf("Unable to locate known reference file %s\n", KNOWNREF); + printf(" Checked following directories:\n%s\n", tried); +#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) + DebugBreak(); +#endif + exit(1); - bytes = UUDECODE(*p++); - while (bytes > 0) { - int n = 0; - /* Write out 1-3 bytes from that. */ - if (bytes > 0) { - n = UUDECODE(*p++) << 18; - n |= UUDECODE(*p++) << 12; - fputc(n >> 16, out); - --bytes; - } - if (bytes > 0) { - n |= UUDECODE(*p++) << 6; - fputc((n >> 8) & 0xFF, out); - --bytes; - } - if (bytes > 0) { - n |= UUDECODE(*p++); - fputc(n & 0xFF, out); - --bytes; - } - } - } - fclose(out); - fclose(in); +success: + free(p); + free(pwd); + return strdup(buff); } - -int main(int argc, char **argv) +int +main(int argc, char **argv) { static const int limit = sizeof(tests) / sizeof(tests[0]); - int i, tests_run = 0, tests_failed = 0, opt; + int i, tests_run = 0, tests_failed = 0, option; time_t now; char *refdir_alloc = NULL; - char *progname, *p; + const char *progname; + const char *tmp, *option_arg, *p; char tmpdir[256]; char tmpdir_timestamp[256]; + (void)argc; /* UNUSED */ + +#if defined(HAVE__CrtSetReportMode) + /* 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]; while (*p != '\0') { - if (*p == '/') + /* Support \ or / dir separators for Windows compat. */ + if (*p == '/' || *p == '\\') progname = p + 1; ++p; } #ifdef PROGRAM /* Get the target program from environment, if available. */ - testprog = getenv(ENVBASE); + 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; @@ -877,46 +2009,92 @@ int main(int argc, char **argv) refdir = getenv(ENVBASE "_TEST_FILES"); /* - * Parse options. + * Parse options, without using getopt(), which isn't available + * on all platforms. */ - while ((opt = getopt(argc, argv, "dkp:qr:v")) != -1) { - switch (opt) { - case 'd': - dump_on_failure = 1; - break; - case 'k': - keep_temp_files = 1; + ++argv; /* Skip program name */ + while (*argv != NULL) { + if (**argv != '-') break; - case 'p': + 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 - testprog = optarg; + testprogfile = option_arg; #else - usage(progname); + fprintf(stderr, "-p option not permitted\n"); + usage(progname); #endif - break; - case 'q': - quiet_flag++; - break; - case 'r': - refdir = optarg; - break; - case 'v': - verbose = 1; - break; - case '?': - default: - usage(progname); + break; + case 'q': + verbosity--; + break; + case 'r': + refdir = option_arg; + break; + case 'v': + verbosity++; + break; + default: + fprintf(stderr, "Unrecognized option '%c'\n", + option); + usage(progname); + } } } - argc -= optind; - argv += optind; /* * Sanity-check that our options make sense. */ #ifdef PROGRAM - if (testprog == NULL) + if (testprogfile == NULL) { + fprintf(stderr, "Program executable required\n"); usage(progname); + } + + { + 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 /* @@ -925,40 +2103,37 @@ int main(int argc, char **argv) * to make it easier to track the results of multiple tests. */ now = time(NULL); - for (i = 0; i < 1000; i++) { + for (i = 0; ; i++) { strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp), "%Y-%m-%dT%H.%M.%S", localtime(&now)); - sprintf(tmpdir, "/tmp/%s.%s-%03d", progname, tmpdir_timestamp, i); - if (mkdir(tmpdir,0755) == 0) + sprintf(tmpdir, "%s/%s.%s-%03d", tmp, progname, + tmpdir_timestamp, i); + if (assertMakeDir(tmpdir,0755)) break; - if (errno == EEXIST) - continue; - fprintf(stderr, "ERROR: Unable to create temp directory %s\n", - tmpdir); - exit(1); + 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, use the current directory for that. + * reference files, try to find the reference files in + * the "usual places." */ - if (refdir == NULL) { - systemf("/bin/pwd > %s/refdir", tmpdir); - refdir = refdir_alloc = slurpfile(NULL, "%s/refdir", tmpdir); - p = refdir + strlen(refdir); - while (p[-1] == '\n') { - --p; - *p = '\0'; - } - systemf("rm %s/refdir", tmpdir); - } + refdir = refdir_alloc = get_refdir(refdir); /* * Banner with basic information. */ - if (!quiet_flag) { - printf("Running tests in: %s\n", tmpdir); + 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); @@ -966,12 +2141,15 @@ int main(int argc, char **argv) printf("Exercising: "); fflush(stdout); printf("%s\n", EXTRA_VERSION); + } else { + printf("Running "); + fflush(stdout); } /* * Run some or all of the individual tests. */ - if (argc == 0) { + if (*argv == NULL) { /* Default: Run all tests. */ for (i = 0; i < limit; i++) { if (test_run(i, tmpdir)) @@ -980,15 +2158,30 @@ int main(int argc, char **argv) } } else { while (*(argv) != NULL) { - i = atoi(*argv); - if (**argv < '0' || **argv > '9' || i < 0 || i >= limit) { - printf("*** INVALID Test %s\n", *argv); - usage(progname); + if (**argv >= '0' && **argv <= '9') { + i = atoi(*argv); + if (i < 0 || i >= limit) { + printf("*** INVALID Test %s\n", *argv); + free(refdir_alloc); + usage(progname); + /* usage() never returns */ + } } else { - if (test_run(i, tmpdir)) - tests_failed++; - tests_run++; + for (i = 0; i < limit; ++i) { + if (strcmp(*argv, tests[i].name) == 0) + break; + } + if (i >= limit) { + printf("*** INVALID Test ``%s''\n", + *argv); + free(refdir_alloc); + usage(progname); + /* usage() never returns */ + } } + if (test_run(i, tmpdir)) + tests_failed++; + tests_run++; argv++; } } @@ -996,20 +2189,38 @@ int main(int argc, char **argv) /* * Report summary statistics. */ - if (!quiet_flag) { + if (verbosity > VERBOSITY_SUMMARY_ONLY) { printf("\n"); - printf("%d of %d tests reported failures\n", - tests_failed, tests_run); - printf(" Total of %d assertions checked.\n", assertions); - printf(" Total of %d assertions failed.\n", failures); - printf(" Total of %d assertions skipped.\n", skips); + 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); + return (tests_failed ? 1 : 0); } diff --git a/archivers/libarchive/files/tar/test/test.h b/archivers/libarchive/files/tar/test/test.h index 30321e845d6..54c8b8b10c9 100644 --- a/archivers/libarchive/files/tar/test/test.h +++ b/archivers/libarchive/files/tar/test/test.h @@ -22,7 +22,7 @@ * (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.3 2008/06/15 10:07:54 kientzle Exp $ + * $FreeBSD: src/usr.bin/tar/test/test.h,v 1.4 2008/08/21 07:04:57 kientzle Exp $ */ /* Every test program should #include "test.h" as the first thing. */ @@ -33,39 +33,95 @@ */ #if defined(HAVE_CONFIG_H) /* Most POSIX platforms use the 'configure' script to build config.h */ -#include "../../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) +#include "config_freebsd.h" +#elif defined(_WIN32) && !defined(__CYGWIN__) /* Win32 can't run the 'configure' script. */ -#include "../config_windows.h" +#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> + +#ifdef USE_DMALLOC +#include <dmalloc.h> +#endif +#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 #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/stat.h> -#ifndef _WIN32 +#include <time.h> +#ifdef HAVE_UNISTD_H #include <unistd.h> #endif #include <wchar.h> - -#ifdef USE_DMALLOC -#include <dmalloc.h> +#ifdef HAVE_WINDOWS_H +#include <windows.h> #endif -/* No non-FreeBSD platform will have __FBSDID, so just define it here. */ -#ifdef __FreeBSD__ -#include <sys/cdefs.h> /* For __FBSDID */ +/* + * 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__) +#include "../bsdtar_windows.h" +#if !defined(__BORLANDC__) +#define strdup _strdup +#endif +#define LOCALE_DE "deu" #else -#define __FBSDID(a) /* null */ +#define LOCALE_DE "de_DE.UTF-8" +#endif + +/* Visual Studio */ +#ifdef _MSC_VER +#define snprintf sprintf_s +#endif + +/* Cygwin */ +#if defined(__CYGWIN__) +/* Cygwin-1.7.x is lazy about populating nlinks, so don't + * expect it to be accurate. */ +# define NLINKS_INACCURATE_FOR_DIRS +#endif + +/* Haiku OS */ +#if defined(__HAIKU__) +/* Haiku has 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 /* @@ -75,38 +131,83 @@ #define DEFINE_TEST(name) void name(void); void name(void) /* An implementation of the standard assert() macro */ -#define assert(e) test_assert(__FILE__, __LINE__, (e), #e, NULL) - +#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) \ - test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) - +#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) \ - test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) + assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) /* As above, but v1 and v2 are wchar_t * */ #define assertEqualWString(v1,v2) \ - test_assert_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) + assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) /* As above, but raw blocks of bytes. */ #define assertEqualMem(v1, v2, l) \ - test_assert_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL) + assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL) /* Assert two files are the same; allow printf-style expansion of second name. * See below for comments about variable arguments here... */ #define assertEqualFile \ - test_setup(__FILE__, __LINE__);test_assert_equal_file + assertion_setup(__FILE__, __LINE__);assertion_equal_file /* Assert that a file is empty; supports printf-style arguments. */ #define assertEmptyFile \ - test_setup(__FILE__, __LINE__);test_assert_empty_file + assertion_setup(__FILE__, __LINE__);assertion_empty_file +/* Assert that a file is not empty; supports printf-style arguments. */ +#define assertNonEmptyFile \ + assertion_setup(__FILE__, __LINE__);assertion_non_empty_file +#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 \ - test_setup(__FILE__, __LINE__);test_assert_file_exists + assertion_setup(__FILE__, __LINE__);assertion_file_exists /* Assert that a file exists; supports printf-style arguments. */ #define assertFileNotExists \ - test_setup(__FILE__, __LINE__);test_assert_file_not_exists + assertion_setup(__FILE__, __LINE__);assertion_file_not_exists /* Assert that file contents match a string; supports printf-style arguments. */ #define assertFileContents \ - test_setup(__FILE__, __LINE__);test_assert_file_contents + assertion_setup(__FILE__, __LINE__);assertion_file_contents +#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 assertTextFileContents \ + assertion_setup(__FILE__, __LINE__);assertion_text_file_contents +#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, contents) +#define assertMakeHardlink(newfile, oldfile) \ + assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile) +#define assertMakeSymlink(newfile, linkto) \ + assertion_make_symlink(__FILE__, __LINE__, newfile, linkto) +#define assertUmask(mask) \ + assertion_umask(__FILE__, __LINE__, mask) /* * This would be simple with C99 variadic macros, but I don't want to @@ -115,26 +216,61 @@ * but effective. */ #define skipping \ - test_setup(__FILE__, __LINE__);test_skipping + assertion_setup(__FILE__, __LINE__);test_skipping /* Function declarations. These are defined in test_utility.c. */ void failure(const char *fmt, ...); -void test_setup(const char *, int); +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 assertion_equal_file(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_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *); +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_contents(const void *, int, const char *, ...); +int assertion_file_exists(const char *, ...); +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 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, const char *); +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_non_empty_file(const char *, ...); +int assertion_text_file_contents(const char *buff, const char *f); +int assertion_umask(const char *, int, int); +void assertion_setup(const char *, int); + void test_skipping(const char *fmt, ...); -int test_assert(const char *, int, int, const char *, void *); -int test_assert_empty_file(const char *, ...); -int test_assert_equal_file(const char *, const char *, ...); -int test_assert_equal_int(const char *, int, int, const char *, int, const char *, void *); -int test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *); -int test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *); -int test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *); -int test_assert_file_contents(const void *, int, const char *, ...); -int test_assert_file_exists(const char *, ...); -int test_assert_file_not_exists(const char *, ...); /* 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 "gzip" program. */ +int canGzip(void); + +/* Return true if this platform can run the "gunzip" program. */ +int canGunzip(void); + /* 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, ...); @@ -147,4 +283,7 @@ void extract_reference_file(const char *); */ /* Pathname of exe to be tested. */ -char *testprog; +const char *testprogfile; +/* Name of exe to use in printf-formatted command strings. */ +/* On Windows, this includes leading/trailing quotes. */ +const char *testprog; diff --git a/archivers/libarchive/files/tar/test/test_0.c b/archivers/libarchive/files/tar/test/test_0.c index 36c8b1ebe1f..c9277da16bc 100644 --- a/archivers/libarchive/files/tar/test/test_0.c +++ b/archivers/libarchive/files/tar/test/test_0.c @@ -29,13 +29,18 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/test/test_0.c,v 1.2 2008/05/26 17:10:10 kien * This first test does basic sanity checks on the environment. For * most of these, we just exit on failure. */ +#if !defined(_WIN32) || defined(__CYGWIN__) +#define DEV_NULL "/dev/null" +#else +#define DEV_NULL "NUL" +#endif DEFINE_TEST(test_0) { struct stat st; failure("File %s does not exist?!", testprog); - if (!assertEqualInt(0, stat(testprog, &st))) + if (!assertEqualInt(0, stat(testprogfile, &st))) exit(1); failure("%s is not executable?!", testprog); @@ -46,9 +51,9 @@ DEFINE_TEST(test_0) * Try to succesfully run the program; this requires that * we know some option that will succeed. */ - if (0 == systemf("%s --version >/dev/null", testprog)) { + if (0 == systemf("%s --version >" DEV_NULL, testprog)) { /* This worked. */ - } else if (0 == systemf("%s -W version >/dev/null", testprog)) { + } else if (0 == systemf("%s -W version >" DEV_NULL, testprog)) { /* This worked. */ } else { failure("Unable to successfully run any of the following:\n" diff --git a/archivers/libarchive/files/tar/test/test_basic.c b/archivers/libarchive/files/tar/test/test_basic.c index fff51123019..4dc7cf6364f 100644 --- a/archivers/libarchive/files/tar/test/test_basic.c +++ b/archivers/libarchive/files/tar/test/test_basic.c @@ -27,20 +27,19 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/test/test_basic.c,v 1.2 2008/05/26 17:10:10 static void -basic_tar(const char *target, const char *pack_options, const char *unpack_options) +basic_tar(const char *target, const char *pack_options, + const char *unpack_options, const char *flist) { - struct stat st, st2; - char buff[128]; int r; - assertEqualInt(0, mkdir(target, 0775)); + assertMakeDir(target, 0775); /* Use the tar program to create an archive. */ - r = systemf("%s cf - %s `cat filelist` >%s/archive 2>%s/pack.err", testprog, pack_options, target, target); + r = systemf("%s cf - %s %s >%s/archive 2>%s/pack.err", testprog, pack_options, flist, target, target); failure("Error invoking %s cf -", testprog, pack_options); assertEqualInt(r, 0); - chdir(target); + assertChdir(target); /* Verify that nothing went to stderr. */ assertEmptyFile("pack.err"); @@ -60,99 +59,57 @@ basic_tar(const char *target, const char *pack_options, const char *unpack_optio */ /* Regular file with 2 links. */ - r = lstat("file", &st); - failure("Failed to stat file %s/file, errno=%d", target, errno); - assertEqualInt(r, 0); - if (r == 0) { - assert(S_ISREG(st.st_mode)); - assertEqualInt(0644, st.st_mode & 0777); - assertEqualInt(10, st.st_size); - failure("file %s/file", target); - assertEqualInt(2, st.st_nlink); - } + assertIsReg("file", -1); + assertFileSize("file", 10); + failure("%s", target); + assertFileNLinks("file", 2); /* Another name for the same file. */ - r = lstat("linkfile", &st2); - failure("Failed to stat file %s/linkfile, errno=%d", target, errno); - assertEqualInt(r, 0); - if (r == 0) { - assert(S_ISREG(st2.st_mode)); - assertEqualInt(0644, st2.st_mode & 0777); - assertEqualInt(10, st2.st_size); - failure("file %s/linkfile", target); - assertEqualInt(2, st2.st_nlink); - /* Verify that the two are really hardlinked. */ - assertEqualInt(st.st_dev, st2.st_dev); - failure("%s/linkfile and %s/file aren't really hardlinks", target, target); - assertEqualInt(st.st_ino, st2.st_ino); - } + assertIsReg("linkfile", -1); + assertFileSize("linkfile", 10); + assertFileNLinks("linkfile", 2); + assertIsHardlink("file", "linkfile"); /* Symlink */ - r = lstat("symlink", &st); - failure("Failed to stat file %s/symlink, errno=%d", target, errno); - assertEqualInt(r, 0); - if (r == 0) { - failure("symlink should be a symlink; actual mode is %o", - st.st_mode); - assert(S_ISLNK(st.st_mode)); - if (S_ISLNK(st.st_mode)) { - r = readlink("symlink", buff, sizeof(buff)); - assertEqualInt(r, 4); - buff[r] = '\0'; - assertEqualString(buff, "file"); - } - } + if (canSymlink()) + assertIsSymlink("symlink", "file"); /* dir */ - r = lstat("dir", &st); - if (r == 0) { - assertEqualInt(r, 0); - assert(S_ISDIR(st.st_mode)); - assertEqualInt(0775, st.st_mode & 0777); - } - - chdir(".."); + assertIsDir("dir", 0775); + assertChdir(".."); } DEFINE_TEST(test_basic) { - int fd; - int filelist; - int oldumask; + FILE *f; + const char *flist; - oldumask = umask(0); - - /* - * Create an assortment of files on disk. - */ - filelist = open("filelist", O_CREAT | O_WRONLY, 0644); + assertUmask(0); /* File with 10 bytes content. */ - fd = open("file", O_CREAT | O_WRONLY, 0644); - assert(fd >= 0); - assertEqualInt(10, write(fd, "123456789", 10)); - close(fd); - write(filelist, "file\n", 5); + f = fopen("file", "wb"); + assert(f != NULL); + assertEqualInt(10, fwrite("123456789", 1, 10, f)); + fclose(f); /* hardlink to above file. */ - assertEqualInt(0, link("file", "linkfile")); - write(filelist, "linkfile\n", 9); + assertMakeHardlink("linkfile", "file"); + assertIsHardlink("file", "linkfile"); /* Symlink to above file. */ - assertEqualInt(0, symlink("file", "symlink")); - write(filelist, "symlink\n", 8); + if (canSymlink()) + assertMakeSymlink("symlink", "file"); /* Directory. */ - assertEqualInt(0, mkdir("dir", 0775)); - write(filelist, "dir\n", 4); - /* All done. */ - close(filelist); + assertMakeDir("dir", 0775); + if (canSymlink()) + flist = "file linkfile symlink dir"; + else + flist = "file linkfile dir"; /* Archive/dearchive with a variety of options. */ - basic_tar("copy", "", ""); + basic_tar("copy", "", "", flist); /* tar doesn't handle cpio symlinks correctly */ /* basic_tar("copy_odc", "--format=odc", ""); */ - basic_tar("copy_ustar", "--format=ustar", ""); - - umask(oldumask); + basic_tar("copy_ustar", "--format=ustar", "", flist); } diff --git a/archivers/libarchive/files/tar/test/test_copy.c b/archivers/libarchive/files/tar/test/test_copy.c index b2eef8cf791..69112900e53 100644 --- a/archivers/libarchive/files/tar/test/test_copy.c +++ b/archivers/libarchive/files/tar/test/test_copy.c @@ -23,7 +23,110 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_copy.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_copy.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $"); + +#if defined(__CYGWIN__) +# include <limits.h> +# include <sys/cygwin.h> +#endif + +/* + * Try to figure out how deep we can go in our tests. Assumes that + * the first call to this function has the longest starting cwd (which + * is currently "<testdir>/original"). This is mostly to work around + * limits in our Win32 support. + * + * Background: On Posix systems, PATH_MAX is merely a limit on the + * length of the string passed into a system call. By repeatedly + * calling chdir(), you can work with arbitrarily long paths on such + * systems. In contrast, Win32 APIs apply PATH_MAX limits to the full + * absolute path, so the permissible length of a system call argument + * varies with the cwd. Some APIs actually enforce limits + * significantly less than PATH_MAX to ensure that you can create + * files within the current working directory. The Win32 limits also + * apply to Cygwin before 1.7. + * + * Someday, I want to convert the Win32 support to use newer + * wide-character paths with '\\?\' prefix, which has a 32k PATH_MAX + * instead of the rather anemic 260 character limit of the older + * system calls. Then we can drop this mess (unless we want to + * continue to special-case Cygwin 1.5 and earlier). + */ +static int +compute_loop_max(void) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + static int LOOP_MAX = 0; + char buf[MAX_PATH]; + size_t cwdlen; + + if (LOOP_MAX == 0) { + assert(_getcwd(buf, MAX_PATH) != NULL); + cwdlen = strlen(buf); + /* 12 characters = length of 8.3 filename */ + /* 4 characters = length of "/../" used in symlink tests */ + /* 1 character = length of extra "/" separator */ + LOOP_MAX = MAX_PATH - (int)cwdlen - 12 - 4 - 1; + } + return LOOP_MAX; +#elif defined(__CYGWIN__) && !defined(HAVE_CYGWIN_CONV_PATH) + static int LOOP_MAX = 0; + if (LOOP_MAX == 0) { + char wbuf[PATH_MAX]; + char pbuf[PATH_MAX]; + size_t wcwdlen; + size_t pcwdlen; + size_t cwdlen; + assert(getcwd(pbuf, PATH_MAX) != NULL); + pcwdlen = strlen(pbuf); + cygwin_conv_to_full_win32_path(pbuf, wbuf); + wcwdlen = strlen(wbuf); + cwdlen = ((wcwdlen > pcwdlen) ? wcwdlen : pcwdlen); + /* Cygwin helper needs an extra few characters. */ + LOOP_MAX = PATH_MAX - (int)cwdlen - 12 - 4 - 4; + } + return LOOP_MAX; +#else + /* cygwin-1.7 ends up here, along with "normal" unix */ + return 200; /* restore pre-r278 depth */ +#endif +} + +/* filenames[i] is a distinctive filename of length i. */ +/* To simplify interpreting failures, each filename ends with a + * decimal integer which is the length of the filename. E.g., A + * filename ending in "_92" is 92 characters long. To detect errors + * which drop or misplace characters, the filenames use a repeating + * "abcdefghijklmnopqrstuvwxyz..." pattern. */ +static char *filenames[201]; + +static void +compute_filenames(void) +{ + char buff[250]; + size_t i,j; + + filenames[0] = strdup(""); + filenames[1] = strdup("1"); + filenames[2] = strdup("a2"); + for (i = 3; i < sizeof(filenames)/sizeof(filenames[0]); ++i) { + /* Fill with "abcdefghij..." */ + for (j = 0; j < i; ++j) + buff[j] = 'a' + (j % 26); + buff[j--] = '\0'; + /* Work from the end to fill in the number portion. */ + buff[j--] = '0' + (i % 10); + if (i > 9) { + buff[j--] = '0' + ((i / 10) % 10); + if (i > 99) + buff[j--] = '0' + (i / 100); + } + buff[j] = '_'; + /* Guard against obvious screwups in the above code. */ + assertEqualInt(strlen(buff), i); + filenames[i] = strdup(buff); + } +} static void create_tree(void) @@ -31,208 +134,145 @@ create_tree(void) char buff[260]; char buff2[260]; int i; - int fd; - - assertEqualInt(0, mkdir("original", 0775)); - chdir("original"); - assertEqualInt(0, mkdir("f", 0775)); - assertEqualInt(0, mkdir("l", 0775)); - assertEqualInt(0, mkdir("m", 0775)); - assertEqualInt(0, mkdir("s", 0775)); - assertEqualInt(0, mkdir("d", 0775)); - - for (i = 0; i < 200; i++) { - buff[0] = 'f'; - buff[1] = '/'; - /* Create a file named "f/abcdef..." */ - buff[i + 2] = 'a' + (i % 26); - buff[i + 3] = '\0'; - fd = open(buff, O_CREAT | O_WRONLY, 0644); - assert(fd >= 0); - assertEqualInt(i + 3, write(fd, buff, strlen(buff))); - close(fd); + int LOOP_MAX; + + compute_filenames(); + + /* Log that we'll be omitting some checks. */ + if (!canSymlink()) { + skipping("Symlink checks"); + } + + assertMakeDir("original", 0775); + assertEqualInt(0, chdir("original")); + LOOP_MAX = compute_loop_max(); + + assertMakeDir("f", 0775); + assertMakeDir("l", 0775); + assertMakeDir("m", 0775); + assertMakeDir("s", 0775); + assertMakeDir("d", 0775); + + for (i = 1; i < LOOP_MAX; i++) { + failure("Internal sanity check failed: i = %d", i); + assert(filenames[i] != NULL); + + sprintf(buff, "f/%s", filenames[i]); + assertMakeFile(buff, 0777, buff); /* Create a link named "l/abcdef..." to the above. */ - strcpy(buff2, buff); - buff2[0] = 'l'; - assertEqualInt(0, link(buff, buff2)); + sprintf(buff2, "l/%s", filenames[i]); + assertMakeHardlink(buff2, buff); /* Create a link named "m/abcdef..." to the above. */ - strcpy(buff2, buff); - buff2[0] = 'm'; - assertEqualInt(0, link(buff, buff2)); - - /* Create a symlink named "s/abcdef..." to the above. */ - strcpy(buff2 + 3, buff); - buff[0] = 's'; - buff2[0] = '.'; - buff2[1] = '.'; - buff2[2] = '/'; - assertEqualInt(0, symlink(buff2, buff)); - + sprintf(buff2, "m/%s", filenames[i]); + assertMakeHardlink(buff2, buff); + + if (canSymlink()) { + /* Create a symlink named "s/abcdef..." to the above. */ + sprintf(buff, "s/%s", filenames[i]); + sprintf(buff2, "../f/%s", filenames[i]); + failure("buff=\"%s\" buff2=\"%s\"", buff, buff2); + assertMakeSymlink(buff, buff2); + } /* Create a dir named "d/abcdef...". */ buff[0] = 'd'; - assertEqualInt(0, mkdir(buff, 0775)); + failure("buff=\"%s\"", buff); + assertMakeDir(buff, 0775); } - chdir(".."); + assertEqualInt(0, chdir("..")); } -#define LIMIT_NONE 0 -#define LIMIT_USTAR 1 +#define LIMIT_NONE 200 +#define LIMIT_USTAR 100 static void -verify_tree(int limit) +verify_tree(size_t limit) { - struct stat st, st2; - char filename[260]; char name1[260]; char name2[260]; - char contents[260]; - int i, j, r; - int fd; - int len; - const char *p, *dp; - DIR *d; - struct dirent *de; + size_t i, LOOP_MAX; - /* Generate the names we know should be there and verify them. */ - for (i = 1; i < 200; i++) { - /* Generate a base name of the correct length. */ - for (j = 0; j < i; ++j) - filename[j] = 'a' + (j % 26); -#if 0 - for (n = i; n > 0; n /= 10) - filename[--j] = '0' + (n % 10); -#endif - filename[i] = '\0'; + LOOP_MAX = compute_loop_max(); + /* Generate the names we know should be there and verify them. */ + for (i = 1; i < LOOP_MAX; i++) { /* Verify a file named "f/abcdef..." */ - strcpy(name1, "f/"); - strcat(name1, filename); - if (limit != LIMIT_USTAR || strlen(filename) <= 100) { - fd = open(name1, O_RDONLY); - failure("Couldn't open \"%s\": %s", - name1, strerror(errno)); - if (assert(fd >= 0)) { - len = read(fd, contents, i + 10); - close(fd); - assertEqualInt(len, i + 2); - /* Verify contents of 'contents' */ - contents[len] = '\0'; - failure("Each test file contains its own name"); - assertEqualString(name1, contents); - /* stat() for dev/ino for next check */ - assertEqualInt(0, lstat(name1, &st)); - } + sprintf(name1, "f/%s", filenames[i]); + if (i <= limit) { + assertFileExists(name1); + assertFileContents(name1, strlen(name1), name1); } - /* - * ustar allows 100 chars for links, and we have - * "original/" as part of the name, so the link - * names here can't exceed 91 chars. - */ - strcpy(name2, "l/"); - strcat(name2, filename); - if (limit != LIMIT_USTAR || strlen(name2) <= 100) { + sprintf(name2, "l/%s", filenames[i]); + if (i + 2 <= limit) { /* Verify hardlink "l/abcdef..." */ - assertEqualInt(0, (r = lstat(name2, &st2))); - if (r == 0) { - assertEqualInt(st2.st_dev, st.st_dev); - assertEqualInt(st2.st_ino, st.st_ino); - } - - /* Verify hardlink "m_abcdef..." */ + assertIsHardlink(name1, name2); + /* Verify hardlink "m/abcdef..." */ name2[0] = 'm'; - assertEqualInt(0, (r = lstat(name2, &st2))); - if (r == 0) { - assertEqualInt(st2.st_dev, st.st_dev); - assertEqualInt(st2.st_ino, st.st_ino); - } + assertIsHardlink(name1, name2); } - /* - * Symlink text doesn't include the 'original/' prefix, - * so the limit here is 100 characters. - */ - /* Verify symlink "s/abcdef..." */ - strcpy(name2, "../s/"); - strcat(name2, filename); - if (limit != LIMIT_USTAR || strlen(name2) <= 100) { - /* This is a symlink. */ - failure("Couldn't stat %s (length %d)", - filename, strlen(filename)); - if (assertEqualInt(0, lstat(name2 + 3, &st2))) { - assert(S_ISLNK(st2.st_mode)); - /* This is a symlink to the file above. */ - failure("Couldn't stat %s", name2 + 3); - if (assertEqualInt(0, stat(name2 + 3, &st2))) { - assertEqualInt(st2.st_dev, st.st_dev); - assertEqualInt(st2.st_ino, st.st_ino); - } - } + if (canSymlink()) { + /* Verify symlink "s/abcdef..." */ + sprintf(name1, "s/%s", filenames[i]); + sprintf(name2, "../f/%s", filenames[i]); + if (strlen(name2) <= limit) + assertIsSymlink(name1, name2); } /* Verify dir "d/abcdef...". */ - strcpy(name1, "d/"); - strcat(name1, filename); - if (limit != LIMIT_USTAR || strlen(filename) < 100) { - /* This is a dir. */ - failure("Couldn't stat %s (length %d)", - name1, strlen(filename)); - if (assertEqualInt(0, lstat(name1, &st2))) { - if (assert(S_ISDIR(st2.st_mode))) { - /* TODO: opendir/readdir this - * directory and make sure - * it's empty. - */ - } + sprintf(name1, "d/%s", filenames[i]); + if (i + 1 <= limit) { /* +1 for trailing slash */ + if (assertIsDir(name1, -1)) { + /* TODO: opendir/readdir this + * directory and make sure + * it's empty. + */ } } } - /* Now make sure nothing is there that shouldn't be. */ - for (dp = "dflms"; *dp != '\0'; ++dp) { - char dir[2]; - dir[0] = *dp; dir[1] = '\0'; - d = opendir(dir); - while ((de = readdir(d)) != NULL) { - p = de->d_name; - switch(dp[0]) { - case 'l': case 'm': - if (limit == LIMIT_USTAR) { - failure("strlen(p) = %d", strlen(p)); - assert(strlen(p) <= 100); - } - case 'd': - if (limit == LIMIT_USTAR) { +#if !defined(_WIN32) || defined(__CYGWIN__) + { + const char *dp; + /* Now make sure nothing is there that shouldn't be. */ + for (dp = "dflms"; *dp != '\0'; ++dp) { + DIR *d; + struct dirent *de; + char dir[2]; + dir[0] = *dp; dir[1] = '\0'; + d = opendir(dir); + failure("Unable to open dir '%s'", dir); + if (!assert(d != NULL)) + continue; + while ((de = readdir(d)) != NULL) { + char *p = de->d_name; + if (p[0] == '.') + continue; + switch(dp[0]) { + case 'l': case 'm': case 'd': failure("strlen(p)=%d", strlen(p)); - assert(strlen(p) < 100); - } - case 'f': case 's': - if (limit == LIMIT_USTAR) { + assert(strlen(p) < limit); + assertEqualString(p, + filenames[strlen(p)]); + break; + case 'f': case 's': failure("strlen(p)=%d", strlen(p)); - assert(strlen(p) < 101); - } - /* Our files have very particular filename patterns. */ - if (p[0] != '.' || (p[1] != '.' && p[1] != '\0')) { - for (i = 0; p[i] != '\0' && i < 200; i++) { - failure("i=%d, p[i]='%c' 'a'+(i%%26)='%c'", i, p[i], 'a' + (i % 26)); - assertEqualInt(p[i], 'a' + (i % 26)); - } - assert(p[i] == '\0'); + assert(strlen(p) < limit + 1); + assertEqualString(p, + filenames[strlen(p)]); + break; + default: + failure("File %s shouldn't be here", p); + assert(0); } - break; - case '.': - assert(p[1] == '\0' || (p[1] == '.' && p[2] == '\0')); - break; - default: - failure("File %s shouldn't be here", p); - assert(0); } + closedir(d); } - closedir(d); } +#endif } static void @@ -240,7 +280,13 @@ copy_basic(void) { int r; - assertEqualInt(0, mkdir("plain", 0775)); + /* NOTE: for proper operation on cygwin-1.5 and windows, the + * length of the name of the directory below, "plain", must be + * less than or equal to the lengthe of the name of the original + * directory, "original" This restriction derives from the + * extremely limited pathname lengths on those platforms. + */ + assertMakeDir("plain", 0775); assertEqualInt(0, chdir("plain")); /* @@ -276,7 +322,13 @@ copy_ustar(void) const char *target = "ustar"; int r; - assertEqualInt(0, mkdir(target, 0775)); + /* NOTE: for proper operation on cygwin-1.5 and windows, the + * length of the name of the directory below, "ustar", must be + * less than or equal to the lengthe of the name of the original + * directory, "original" This restriction derives from the + * extremely limited pathname lengths on those platforms. + */ + assertMakeDir(target, 0775); assertEqualInt(0, chdir(target)); /* @@ -303,17 +355,13 @@ copy_ustar(void) assertEmptyFile("unpack.err"); assertEmptyFile("unpack.out"); - chdir("original"); verify_tree(LIMIT_USTAR); - chdir("../.."); + assertEqualInt(0, chdir("../..")); } DEFINE_TEST(test_copy) { - int oldumask; - - oldumask = umask(0); - + assertUmask(0); create_tree(); /* Create sample files in "original" dir. */ /* Test simple "tar -c | tar -x" pipeline copy. */ @@ -321,6 +369,4 @@ DEFINE_TEST(test_copy) /* Same, but constrain to ustar format. */ copy_ustar(); - - umask(oldumask); } diff --git a/archivers/libarchive/files/tar/test/test_empty_mtree.c b/archivers/libarchive/files/tar/test/test_empty_mtree.c new file mode 100644 index 00000000000..6f8a5e91aa1 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_empty_mtree.c @@ -0,0 +1,45 @@ +/*- + * 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" +__FBSDID("$FreeBSD$"); + +/* + * Regression test: We used to get a bogus error message when we + * asked tar to copy entries out of an empty archive. See + * Issue 51 on libarchive.googlecode.com for details. + */ +DEFINE_TEST(test_empty_mtree) +{ + int r; + + assertMakeFile("test1.mtree", 0777, "#mtree\n"); + + r = systemf("%s cf test1.tar @test1.mtree >test1.out 2>test1.err", + testprog); + failure("Error invoking %s cf", testprog); + assertEqualInt(r, 0); + assertEmptyFile("test1.out"); + assertEmptyFile("test1.err"); +} diff --git a/archivers/libarchive/files/tar/test/test_getdate.c b/archivers/libarchive/files/tar/test/test_getdate.c index d75119cc33a..eac571049fe 100644 --- a/archivers/libarchive/files/tar/test/test_getdate.c +++ b/archivers/libarchive/files/tar/test/test_getdate.c @@ -25,14 +25,56 @@ #include "test.h" __FBSDID("$FreeBSD: src/usr.bin/tar/test/test_getdate.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); +#include <time.h> + /* * Verify that the getdate() function works. */ -time_t get_date(const char *); +time_t get_date(time_t, const char *); DEFINE_TEST(test_getdate) { - assertEqualInt(0, get_date("Jan 1, 1970 UTC")); + time_t now = time(NULL); + + assertEqualInt(get_date(now, "Jan 1, 1970 UTC"), 0); + assertEqualInt(get_date(now, "7:12:18-0530 4 May 1983"), 420900138); + assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980); + assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000); + assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460); + /* It's important that we handle ctime() format. */ + assertEqualInt(get_date(now, "Sun Feb 22 17:38:26 PST 2009"), + 1235353106); + /* Basic relative offsets. */ + /* If we use the actual current time as the reference, then + * these tests break around DST changes, so it's actually + * important to use a specific reference time here. */ + assertEqualInt(get_date(0, "tomorrow"), 24 * 60 * 60); + assertEqualInt(get_date(0, "yesterday"), - 24 * 60 * 60); + assertEqualInt(get_date(0, "now + 1 hour"), 60 * 60); + assertEqualInt(get_date(0, "now + 1 hour + 1 minute"), 60 * 60 + 60); + /* Repeat the above for a different start time. */ + now = 1231113600; /* Jan 5, 2009 00:00 UTC */ + assertEqualInt(get_date(0, "Jan 5, 2009 00:00 UTC"), now); + assertEqualInt(get_date(now, "tomorrow"), now + 24 * 60 * 60); + assertEqualInt(get_date(now, "yesterday"), now - 24 * 60 * 60); + assertEqualInt(get_date(now, "now + 1 hour"), now + 60 * 60); + assertEqualInt(get_date(now, "now + 1 hour + 1 minute"), + now + 60 * 60 + 60); + assertEqualInt(get_date(now, "tomorrow 5:16am UTC"), + now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); + assertEqualInt(get_date(now, "UTC 5:16am tomorrow"), + now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); + + /* Jan 5, 2009 was a Monday. */ + assertEqualInt(get_date(now, "monday UTC"), now); + assertEqualInt(get_date(now, "sunday UTC"), now + 6 * 24 * 60 * 60); + assertEqualInt(get_date(now, "tuesday UTC"), now + 24 * 60 * 60); + /* "next tuesday" is one week after "tuesday" */ + assertEqualInt(get_date(now, "UTC next tuesday"), + now + 8 * 24 * 60 * 60); + /* "last tuesday" is one week before "tuesday" */ + assertEqualInt(get_date(now, "last tuesday UTC"), + now - 6 * 24 * 60 * 60); /* TODO: Lots more tests here. */ } diff --git a/archivers/libarchive/files/tar/test/test_help.c b/archivers/libarchive/files/tar/test/test_help.c index 163e2127f26..3bb517d00cd 100644 --- a/archivers/libarchive/files/tar/test/test_help.c +++ b/archivers/libarchive/files/tar/test/test_help.c @@ -51,6 +51,7 @@ DEFINE_TEST(test_help) /* Exercise --help option. */ r = systemf("%s --help >help.stdout 2>help.stderr", testprog); + assertEqualInt(r, 0); failure("--help should generate nothing to stderr."); assertEmptyFile("help.stderr"); /* Help message should start with name of program. */ @@ -67,6 +68,7 @@ DEFINE_TEST(test_help) /* -h option should generate the same output. */ r = systemf("%s -h >h.stdout 2>h.stderr", testprog); + assertEqualInt(r, 0); failure("-h should generate nothing to stderr."); assertEmptyFile("h.stderr"); failure("stdout should be same for -h and --help"); @@ -74,6 +76,7 @@ DEFINE_TEST(test_help) /* -W help should be another synonym. */ r = systemf("%s -W help >Whelp.stdout 2>Whelp.stderr", testprog); + assertEqualInt(r, 0); failure("-W help should generate nothing to stderr."); assertEmptyFile("Whelp.stderr"); failure("stdout should be same for -W help and --help"); diff --git a/archivers/libarchive/files/tar/test/test_option_T_upper.c b/archivers/libarchive/files/tar/test/test_option_T_upper.c new file mode 100644 index 00000000000..3d2a8b1e2a5 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_option_T_upper.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2003-2008 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" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_T.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $"); + +static int +touch(const char *fn, int fail) +{ + FILE *f = fopen(fn, "w"); + if (fail) { + failure("Couldn't create file '%s', errno=%d (%s)\n", + fn, errno, strerror(errno)); + if (!assert(f != NULL)) + return (0); /* Failure. */ + } else { + if (f == NULL) + return (0); /* Soft failure. */ + } + fclose(f); + return (1); /* Success */ +} + +DEFINE_TEST(test_option_T_upper) +{ + FILE *f; + int r; + struct stat st; + int gnarlyFilesSupported; + + /* Create a simple dir heirarchy; bail if anything fails. */ + if (!assertMakeDir("d1", 0755)) return; + if (!assertMakeDir("d1/d2", 0755)) return; + if (!touch("f", 1)) return; + if (!touch("d1/f1", 1)) return; + if (!touch("d1/f2", 1)) return; + if (!touch("d1/d2/f3", 1)) return; + if (!touch("d1/d2/f4", 1)) return; + if (!touch("d1/d2/f5", 1)) return; + if (!touch("d1/d2/f6", 1)) return; + /* Some platforms don't permit such things; just skip it. */ + gnarlyFilesSupported = touch("d1/d2/f\x0a", 0); + + /* Populate a file list */ + f = fopen("filelist", "w+"); + if (!assert(f != NULL)) + return; + /* Use a variety of text line endings. */ + fprintf(f, "f\x0d"); /* CR */ + fprintf(f, "d1/f1\x0d\x0a"); /* CRLF */ + fprintf(f, "d1/d2/f4\x0a"); /* NL */ + fprintf(f, "d1/d2/f6"); /* EOF */ + fclose(f); + + /* Populate a second file list */ + f = fopen("filelist2", "w+"); + if (!assert(f != NULL)) + return; + /* Use null-terminated names. */ + fprintf(f, "d1/d2/f3"); + fwrite("\0", 1, 1, f); + fprintf(f, "d1/d2/f5"); + fwrite("\0", 1, 1, f); + if (gnarlyFilesSupported) { + fprintf(f, "d1/d2/f\x0a"); + fwrite("\0", 1, 1, f); + } + fclose(f); + + /* Use -c -T to archive up the files. */ + r = systemf("%s -c -f test1.tar -T filelist > test1.out 2> test1.err", + testprog); + assert(r == 0); + assertEmptyFile("test1.out"); + assertEmptyFile("test1.err"); + + /* Use -x -T to dearchive the files */ + if (!assertMakeDir("test1", 0755)) return; + systemf("%s -x -f test1.tar -T filelist -C test1" + " > test1b.out 2> test1b.err", testprog); + assertEmptyFile("test1b.out"); + assertEmptyFile("test1b.err"); + + /* Verify the files were extracted. */ + assertFileExists("test1/f"); + assertFileExists("test1/d1/f1"); + assertFileNotExists("test1/d1/f2"); + assertFileNotExists("test1/d1/d2/f3"); + assertFileExists("test1/d1/d2/f4"); + assertFileNotExists("test1/d1/d2/f5"); + assertFileExists("test1/d1/d2/f6"); + if (gnarlyFilesSupported) { + assertFileNotExists("test1/d1/d2/f\x0a"); + } + + /* Use -r -T to add more files to the archive. */ + systemf("%s -r -f test1.tar --null -T filelist2 > test2.out 2> test2.err", + testprog); + assertEmptyFile("test2.out"); + assertEmptyFile("test2.err"); + + /* Use -x without -T to dearchive the files (ensure -r worked) */ + if (!assertMakeDir("test3", 0755)) return; + systemf("%s -x -f test1.tar -C test3" + " > test3.out 2> test3.err", testprog); + assertEmptyFile("test3.out"); + assertEmptyFile("test3.err"); + /* Verify the files were extracted.*/ + assertFileExists("test3/f"); + assertFileExists("test3/d1/f1"); + assertFileNotExists("test3/d1/f2"); + assertFileExists("test3/d1/d2/f3"); + assertFileExists("test3/d1/d2/f4"); + assertFileExists("test3/d1/d2/f5"); + assertFileExists("test3/d1/d2/f6"); + if (gnarlyFilesSupported) { + assertFileExists("test3/d1/d2/f\x0a"); + } + + /* Use -x -T to dearchive the files (verify -x -T together) */ + if (!assertMakeDir("test2", 0755)) return; + systemf("%s -x -f test1.tar -T filelist -C test2" + " > test2b.out 2> test2b.err", testprog); + assertEmptyFile("test2b.out"); + assertEmptyFile("test2b.err"); + /* Verify the files were extracted.*/ + assertFileExists("test2/f"); + assertFileExists("test2/d1/f1"); + assertFileNotExists("test2/d1/f2"); + assertFileNotExists("test2/d1/d2/f3"); + assertFileExists("test2/d1/d2/f4"); + assertFileNotExists("test2/d1/d2/f5"); + assertFileExists("test2/d1/d2/f6"); + if (gnarlyFilesSupported) { + assertFileNotExists("test2/d1/d2/f\x0a"); + } + + assertMakeDir("test4", 0755); + assertMakeDir("test4_out", 0755); + assertMakeDir("test4_out2", 0755); + assertMakeDir("test4/d1", 0755); + assertEqualInt(1, touch("test4/d1/foo", 0)); + + /* Does bsdtar support -s option ? */ + systemf("%s -cf - -s /foo/bar/ test4/d1/foo > check.out 2> check.err", + testprog); + assertEqualInt(0, stat("check.err", &st)); + if (st.st_size == 0) { + systemf("%s -cf - -s /foo/bar/ test4/d1/foo | %s -xf - -C test4_out", + testprog, testprog); + assertEmptyFile("test4_out/test4/d1/bar"); + systemf("%s -cf - -s /d1/d2/ test4/d1/foo | %s -xf - -C test4_out", + testprog, testprog); + assertEmptyFile("test4_out/test4/d2/foo"); + systemf("%s -cf - -s ,test4/d1/foo,, test4/d1/foo | %s -tvf - > test4.lst", + testprog, testprog); + assertEmptyFile("test4.lst"); + systemf("%s -cf - test4/d1/foo | %s -xf - -s /foo/bar/ -C test4_out2", + testprog, testprog); + assertEmptyFile("test4_out2/test4/d1/bar"); + } else { + skipping("bsdtar does not support -s option on this platform"); + } + + /* TODO: Include some use of -C directory-changing within the filelist. */ + /* I'm pretty sure -C within the filelist is broken on extract. */ +} diff --git a/archivers/libarchive/files/tar/test/test_option_q.c b/archivers/libarchive/files/tar/test/test_option_q.c new file mode 100644 index 00000000000..68867b52a82 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_option_q.c @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_q.c,v 1.3 2008/08/22 01:35:08 kientzle Exp $"); + +DEFINE_TEST(test_option_q) +{ + FILE *f; + int r; + + /* + * Create an archive with several different versions of the + * same files. By default, the last version will overwrite + * any earlier versions. The -q/--fast-read option will + * stop early, so we can verify -q/--fast-read by seeing + * which version of each file actually ended up being + * extracted. This also exercises -r mode, since that's + * what we use to build up the test archive. + */ + + f = fopen("foo", "w"); + assert(f != NULL); + fprintf(f, "foo1"); + fclose(f); + + assertEqualInt(0, systemf("%s -cf archive.tar foo", testprog)); + + f = fopen("foo", "w"); + assert(f != NULL); + fprintf(f, "foo2"); + fclose(f); + + assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog)); + + f = fopen("bar", "w"); + assert(f != NULL); + fprintf(f, "bar1"); + fclose(f); + + assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog)); + + f = fopen("foo", "w"); + assert(f != NULL); + fprintf(f, "foo3"); + fclose(f); + + assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog)); + + f = fopen("bar", "w"); + assert(f != NULL); + fprintf(f, "bar2"); + fclose(f); + + assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog)); + + /* + * Now, try extracting from the test archive with various + * combinations of -q. + */ + + /* Test 1: -q foo should only extract the first foo. */ + assertMakeDir("test1", 0755); + assertChdir("test1"); + r = systemf("%s -xf ../archive.tar -q foo >test.out 2>test.err", + testprog); + failure("Fatal error trying to use -q option"); + if (!assertEqualInt(0, r)) + return; + + assertFileContents("foo1", 4, "foo"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 2: -q foo bar should extract up to the first bar. */ + assertMakeDir("test2", 0755); + assertChdir("test2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -q foo bar >test.out 2>test.err", testprog)); + assertFileContents("foo2", 4, "foo"); + assertFileContents("bar1", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 3: Same as test 2, but use --fast-read spelling. */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar --fast-read foo bar >test.out 2>test.err", testprog)); + assertFileContents("foo2", 4, "foo"); + assertFileContents("bar1", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: Without -q, should extract everything. */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar foo bar >test.out 2>test.err", testprog)); + assertFileContents("foo3", 4, "foo"); + assertFileContents("bar2", 4, "bar"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); +} diff --git a/archivers/libarchive/files/tar/test/test_option_r.c b/archivers/libarchive/files/tar/test/test_option_r.c new file mode 100644 index 00000000000..516a8307936 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_option_r.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Also see test_option_q for additional validation of -r support. + */ +DEFINE_TEST(test_option_r) +{ + char buff[15]; + char *p0, *p1; + size_t s; + FILE *f; + int r; + + /* Create a file */ + f = fopen("f1", "w"); + if (!assert(f != NULL)) + return; + assertEqualInt(3, fwrite("abc", 1, 3, f)); + fclose(f); + + /* Archive that one file. */ + r = systemf("%s cf archive.tar --format=ustar f1 >step1.out 2>step1.err", testprog); + failure("Error invoking %s cf archive.tar f1", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("step1.out"); + assertEmptyFile("step1.err"); + + + /* Do some basic validation of the constructed archive. */ + p0 = slurpfile(&s, "archive.tar"); + if (!assert(p0 != NULL)) + return; + if (!assert(s >= 2048)) { + free(p0); + return; + } + assertEqualMem(p0 + 0, "f1", 3); + assertEqualMem(p0 + 512, "abc", 3); + assertEqualMem(p0 + 1024, "\0\0\0\0\0\0\0\0", 8); + assertEqualMem(p0 + 1536, "\0\0\0\0\0\0\0\0", 8); + + /* Edit that file */ + f = fopen("f1", "w"); + if (!assert(f != NULL)) + return; + assertEqualInt(3, fwrite("123", 1, 3, f)); + fclose(f); + + /* Update the archive. */ + r = systemf("%s rf archive.tar --format=ustar f1 >step2.out 2>step2.err", testprog); + failure("Error invoking %s rf archive.tar f1", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("step2.out"); + assertEmptyFile("step2.err"); + + /* Do some basic validation of the constructed archive. */ + p1 = slurpfile(&s, "archive.tar"); + if (!assert(p1 != NULL)) { + free(p0); + return; + } + assert(s >= 3072); + /* Verify first entry is unchanged. */ + assertEqualMem(p0, p1, 1024); + /* Verify that second entry is correct. */ + assertEqualMem(p1 + 1024, "f1", 3); + assertEqualMem(p1 + 1536, "123", 3); + /* Verify end-of-archive marker. */ + assertEqualMem(p1 + 2048, "\0\0\0\0\0\0\0\0", 8); + assertEqualMem(p1 + 2560, "\0\0\0\0\0\0\0\0", 8); + free(p0); + free(p1); + + /* Unpack both items */ + assertMakeDir("step3", 0775); + assertChdir("step3"); + r = systemf("%s xf ../archive.tar", testprog); + failure("Error invoking %s xf archive.tar", testprog); + assertEqualInt(r, 0); + + /* Verify that the second one overwrote the first. */ + f = fopen("f1", "r"); + if (assert(f != NULL)) { + assertEqualInt(3, fread(buff, 1, 3, f)); + assertEqualMem(buff, "123", 3); + fclose(f); + } +} diff --git a/archivers/libarchive/files/tar/test/test_option_s.c b/archivers/libarchive/files/tar/test/test_option_s.c new file mode 100644 index 00000000000..8eb415e1cea --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_option_s.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2003-2008 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" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_option_T.c,v 1.3 2008/08/15 06:12:02 kientzle Exp $"); + +static int +mkfile(const char *fn, const char *contents) +{ + FILE *f = fopen(fn, "w"); + failure("Couldn't create file '%s', errno=%d (%s)\n", + fn, errno, strerror(errno)); + if (!assert(f != NULL)) + return (1); /* Failure. */ + if (contents != NULL) + assertEqualInt(strlen(contents), + fwrite(contents, 1, strlen(contents), f)); + assertEqualInt(0, fclose(f)); + return (0); /* Success */ +} + +DEFINE_TEST(test_option_s) +{ + struct stat st; + + /* Create a sample file heirarchy. */ + assertMakeDir("in", 0755); + assertMakeDir("in/d1", 0755); + assertEqualInt(0, mkfile("in/d1/foo", "foo")); + assertEqualInt(0, mkfile("in/d1/bar", "bar")); + + /* Does bsdtar support -s option ? */ + systemf("%s -cf - -s /foo/bar/ in/d1/foo > NUL 2> check.err", + testprog); + assertEqualInt(0, stat("check.err", &st)); + if (st.st_size != 0) { + skipping("%s does not support -s option on this platform", + testprog); + return; + } + + /* + * Test 1: Filename substitution when creating archives. + */ + assertMakeDir("test1", 0755); + systemf("%s -cf - -s /foo/bar/ in/d1/foo | %s -xf - -C test1", + testprog, testprog); + assertFileContents("foo", 3, "test1/in/d1/bar"); + systemf("%s -cf - -s /d1/d2/ in/d1/foo | %s -xf - -C test1", + testprog, testprog); + assertFileContents("foo", 3, "test1/in/d2/foo"); + + + /* + * Test 2: Basic substitution when extracting archive. + */ + assertMakeDir("test2", 0755); + systemf("%s -cf - in/d1/foo | %s -xf - -s /foo/bar/ -C test2", + testprog, testprog); + assertFileContents("foo", 3, "test2/in/d1/bar"); + + /* + * Test 3: Files with empty names shouldn't be archived. + */ + systemf("%s -cf - -s ,in/d1/foo,, in/d1/foo | %s -tvf - > in.lst", + testprog, testprog); + assertEmptyFile("in.lst"); + + /* + * Test 4: Multiple substitutions when extracting archive. + */ + assertMakeDir("test4", 0755); + systemf("%s -cf - in/d1/foo in/d1/bar | %s -xf - -s /foo/bar/ -s }bar}baz} -C test4", + testprog, testprog); + assertFileContents("foo", 3, "test4/in/d1/bar"); + assertFileContents("bar", 3, "test4/in/d1/baz"); + + /* + * Test 5: Name-switching substitutions when extracting archive. + */ + assertMakeDir("test5", 0755); + systemf("%s -cf - in/d1/foo in/d1/bar | %s -xf - -s /foo/bar/ -s }bar}foo} -C test5", + testprog, testprog); + assertFileContents("foo", 3, "test5/in/d1/bar"); + assertFileContents("bar", 3, "test5/in/d1/foo"); +} diff --git a/archivers/libarchive/files/tar/test/test_patterns.c b/archivers/libarchive/files/tar/test/test_patterns.c index e7b1679fd9d..fee98be9b27 100644 --- a/archivers/libarchive/files/tar/test/test_patterns.c +++ b/archivers/libarchive/files/tar/test/test_patterns.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2009 Michihiro NAKAJIMA * Copyright (c) 2003-2007 Tim Kientzle * All rights reserved. * @@ -23,25 +24,161 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_patterns.c,v 1.6 2008/08/21 22:28:00 kientzle Exp $"); DEFINE_TEST(test_patterns) { - int fd, r; + FILE *f; + int r; + const char *reffile2 = "test_patterns_2.tar"; + const char *reffile3 = "test_patterns_3.tar"; + const char *reffile4 = "test_patterns_4.tar"; + + const char *tar2aExpected[] = { + "/tmp/foo/bar/", + "/tmp/foo/bar/baz", + NULL + }; /* * Test basic command-line pattern handling. */ /* + * Test 1: Files on the command line that don't get matched + * didn't produce an error. + * * John Baldwin reported this problem in PR bin/121598 */ - fd = open("foo", O_CREAT | O_WRONLY, 0644); - assert(fd >= 0); - close(fd); - r = systemf("%s zcfv tar1.tgz foo > tar1a.out 2> tar1a.err", testprog); + f = fopen("foo", "w"); + assert(f != NULL); + fclose(f); + r = systemf("%s cfv tar1.tgz foo > tar1a.out 2> tar1a.err", testprog); assertEqualInt(r, 0); - r = systemf("%s zxfv tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog); + r = systemf("%s xv --no-same-owner -f tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog); failure("tar should return non-zero because a file was given on the command line that's not in the archive"); assert(r != 0); + + /* + * Test 2: Check basic matching of full paths that start with / + */ + extract_reference_file(reffile2); + + r = systemf("%s tf %s /tmp/foo/bar > tar2a.out 2> tar2a.err", + testprog, reffile2); + assertEqualInt(r, 0); + assertFileContainsLinesAnyOrder("tar2a.out", tar2aExpected); + assertEmptyFile("tar2a.err"); + + /* + * Test 3 archive has some entries starting with '/' and some not. + */ + extract_reference_file(reffile3); + + /* Test 3a: Pattern tmp/foo/bar should not match /tmp/foo/bar */ + r = systemf("%s x --no-same-owner -f %s tmp/foo/bar > tar3a.out 2> tar3a.err", + testprog, reffile3); + assert(r != 0); + assertEmptyFile("tar3a.out"); + + /* Test 3b: Pattern /tmp/foo/baz should not match tmp/foo/baz */ + assertNonEmptyFile("tar3a.err"); + /* Again, with the '/' */ + r = systemf("%s x --no-same-owner -f %s /tmp/foo/baz > tar3b.out 2> tar3b.err", + testprog, reffile3); + assert(r != 0); + assertEmptyFile("tar3b.out"); + assertNonEmptyFile("tar3b.err"); + + /* Test 3c: ./tmp/foo/bar should not match /tmp/foo/bar */ + r = systemf("%s x --no-same-owner -f %s ./tmp/foo/bar > tar3c.out 2> tar3c.err", + testprog, reffile3); + assert(r != 0); + assertEmptyFile("tar3c.out"); + assertNonEmptyFile("tar3c.err"); + + /* Test 3d: ./tmp/foo/baz should match tmp/foo/baz */ + r = systemf("%s x --no-same-owner -f %s ./tmp/foo/baz > tar3d.out 2> tar3d.err", + testprog, reffile3); + assertEqualInt(r, 0); + assertEmptyFile("tar3d.out"); + assertEmptyFile("tar3d.err"); + assertFileExists("tmp/foo/baz/bar"); + + /* + * Test 4 archive has some entries starting with windows drive letters + * such as 'c:\', '//./c:/' or '//?/c:/'. + */ + extract_reference_file(reffile4); + + r = systemf("%s x --no-same-owner -f %s -C tmp > tar4.out 2> tar4.err", + testprog, reffile4); + assert(r != 0); + assertEmptyFile("tar4.out"); + assertNonEmptyFile("tar4.err"); + + for (r = 1; r <= 54; r++) { + char file_a[] = "tmp/fileXX"; + char file_b1[] = "tmp/server/share/fileXX"; + char file_b2[] = "tmp/server\\share\\fileXX"; + char file_c[] = "tmp/../fileXX"; + char *filex; + int xsize; + + switch (r) { + case 15: case 18: + /* + * Including server and share names. + * //?/UNC/server/share/file15 + * //?/unc/server/share/file18 + */ + filex = file_b1; + xsize = sizeof(file_b1); + break; + case 35: case 38: case 52: + /* + * Including server and share names. + * \\?\UNC\server\share\file35 + * \\?\unc\server\share\file38 + * \/?/uNc/server\share\file52 + */ + filex = file_b2; + xsize = sizeof(file_b2); + break; + default: + filex = file_a; + xsize = sizeof(file_a); + break; + } + filex[xsize-3] = '0' + r / 10; + filex[xsize-2] = '0' + r % 10; + switch (r) { + case 5: case 6: case 17: case 20: case 25: + case 26: case 37: case 40: case 43: case 54: + /* + * Not extracted patterns. + * D:../file05 + * c:../../file06 + * //?/UNC/../file17 + * //?/unc/../file20 + * z:..\file25 + * c:..\..\file26 + * \\?\UNC\..\file37 + * \\?\unc\..\file40 + * c:../..\file43 + * \/?\UnC\../file54 + */ + assertFileNotExists(filex); + filex = file_c; + xsize = sizeof(file_c); + filex[xsize-3] = '0' + r / 10; + filex[xsize-2] = '0' + r % 10; + assertFileNotExists(filex); + break; + default: + /* Extracted patterns. */ + assertFileExists(filex); + break; + } + } } diff --git a/archivers/libarchive/files/tar/test/test_patterns_2.tar.uu b/archivers/libarchive/files/tar/test/test_patterns_2.tar.uu new file mode 100644 index 00000000000..eba2daece09 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_patterns_2.tar.uu @@ -0,0 +1,231 @@ +begin 644 test_patterns_2.tar +M+W1M<"]F;V\O```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#<U-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P,#`P,#`P +M(#$Q,#4Q,C$R-C4V(#`Q,C0T,0`@-0`````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,'1I;0`` +M````````````````````````````````````=VAE96P````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````O=&UP+V9O;R]B87(O```````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````,#`P-S4U(``P,#$W-3`@`#`P +M,#`P,"``,#`P,#`P,#`P,#`@,3$P-3$R,3(V-3,@,#$S,C`R`"`U```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````'5S=&%R`#`P=&EM``````````````````````````````````````!W +M:&5E;````````````````````````````````````#`P,#`P,"``,#`P,#`P +M(``````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````"]T;7`O9F]O+V)A +M>@`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V-#0@`#`P,3<U,"``,#`P,#`P(``P,#`P,#`P,#`P,"`Q,3`U,3(Q,C8U +M-B`P,3,Q,C8`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#!T:6T````````````````` +M`````````````````````'=H965L```````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````+W1M<"]F;V\O8F%R+V)A>@`````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````#`P,#8T-"``,#`Q-S4P(``P,#`P,#`@`#`P,#`P +M,#`P,#`P(#$Q,#4Q,C$R-C4S(#`Q,S8V-P`@,``````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!U<W1A<@`P +M,'1I;0``````````````````````````````````````=VAE96P````````` +M```````````````````````````P,#`P,#`@`#`P,#`P,"`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +9```````````````````````````````````` +` +end diff --git a/archivers/libarchive/files/tar/test/test_patterns_3.tar.uu b/archivers/libarchive/files/tar/test/test_patterns_3.tar.uu new file mode 100644 index 00000000000..de60b8dc8e1 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_patterns_3.tar.uu @@ -0,0 +1,231 @@ +begin 644 test_patterns_3.tar +M+W1M<"]F;V\O8F%R+P`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#<U-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P,#`P,#`P +M(#$Q,#4S,C`W-34R(#`Q,S(P-@`@-0`````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,'1I;0`` +M````````````````````````````````````=VAE96P````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````O=&UP+V9O;R]B87(O8F%Z+P`````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````,#`P-S4U(``P,#$W-3`@`#`P +M,#`P,"``,#`P,#`P,#`P,#`@,3$P-3,R,#<U-3(@,#$S-S8R`"`U```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````'5S=&%R`#`P=&EM``````````````````````````````````````!W +M:&5E;````````````````````````````````````#`P,#`P,"``,#`P,#`P +M(``````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````'1M<"]F;V\O8F%Z +M+P`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`W-34@`#`P,3<U,"``,#`P,#`P(``P,#`P,#`P,#`P,"`Q,3`U,S(P-S4V +M,"`P,3,Q,S8`(#4````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#!T:6T````````````````` +M`````````````````````'=H965L```````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````=&UP+V9O;R]B87HO8F%R+P`````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````#`P,#<U-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P +M,#`P,#`P(#$Q,#4S,C`W-38P(#`Q,S<P,@`@-0`````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!U<W1A<@`P +M,'1I;0``````````````````````````````````````=VAE96P````````` +M```````````````````````````P,#`P,#`@`#`P,#`P,"`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +9```````````````````````````````````` +` +end diff --git a/archivers/libarchive/files/tar/test/test_patterns_4.tar.uu b/archivers/libarchive/files/tar/test/test_patterns_4.tar.uu new file mode 100644 index 00000000000..240af208934 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_patterns_4.tar.uu @@ -0,0 +1,641 @@ +begin 644 test_patterns_4.tar +M+V9I;&4P,0`````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P +M(#$Q,34P-C<T-C0R(#`Q,#,S-@`@,``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,``````` +M```````````````````````````````````````````````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````O+BXO9FEL93`R```````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P +M,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$P-34R`"`P```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````'5S=&%R`#`P```````````````````````````````````````````` +M`````````````````````````````````````````#`P,#`P,"``,#`P,#`P +M(``````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````"\N+B\N+B]F:6QE +M,#,````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T +M,B`P,3`W-C8`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#`````````````````````` +M```````````````````````````````````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````8SHO9FEL93`T```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P +M,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,#4W-@`@,``````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!U<W1A<@`P +M,``````````````````````````````````````````````````````````` +M```````````````````````````P,#`P,#`@`#`P,#`P,"`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````!$.BXN+V9I;&4P-0`````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````,#`P-C0T(``P,#$W +M-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$P-C<T`"`P +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````'5S=&%R`#`P```````````````````````````````````` +M`````````````````````````````````````````````````#`P,#`P,"`` +M,#`P,#`P(``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````&,Z+BXO +M+BXO9FEL93`V```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U +M,#8W-#8T,B`P,3$Q-#<`(#`````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````=7-T87(`,#`````````````` +M```````````````````````````````````````````````````````````` +M````````````,#`P,#`P(``P,#`P,#`@```````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````0SHO+BXO9FEL93`W```````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@ +M`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,#<U-``@,``````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!U +M<W1A<@`P,``````````````````````````````````````````````````` +M```````````````````````````````````P,#`P,#`@`#`P,#`P,"`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````!A.B\N+B\N+B]F:6QE,#@` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````,#`P-C0T +M(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q +M,C(V`"`P```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````'5S=&%R`#`P```````````````````````````` +M`````````````````````````````````````````````````````````#`P +M,#`P,"``,#`P,#`P(``````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`"\O+B]C.B]F:6QE,#D````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P +M,"`Q,3$U,#8W-#8T,B`P,3$P-S8`(#`````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````=7-T87(`,#`````` +M```````````````````````````````````````````````````````````` +M````````````````````,#`P,#`P(``P,#`P,#`@```````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````+R\N+T,Z+RXN+V9I;&4Q,``````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P +M,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,3(T,0`@,``````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````!U<W1A<@`P,``````````````````````````````````````````` +M```````````````````````````````````````````P,#`P,#`@`#`P,#`P +M,"`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````O+S\O8SHO9FEL +M93$Q```````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V +M-#(@,#$Q,3$P`"`P```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````'5S=&%R`#`P```````````````````` +M```````````````````````````````````````````````````````````` +M`````#`P,#`P,"``,#`P,#`P(``````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````"\O/R]#.B\N+B]F:6QE,3(````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P +M,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$R-C0`(#`````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````=7-T87(` +M,#`````````````````````````````````````````````````````````` +M````````````````````````````,#`P,#`P(``P,#`P,#`@```````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````+R\O+V,Z+V9I;&4Q,P`````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````#`P,#8T-"``,#`Q +M-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,3`W,@`@ +M,``````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````!U<W1A<@`P,``````````````````````````````````` +M```````````````````````````````````````````````````P,#`P,#`@ +M`#`P,#`P,"`````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````O+R\O +M0SHO+R\O+V9I;&4Q-``````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q +M-3`V-S0V-#(@,#$Q,S(W`"`P```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````'5S=&%R`#`P```````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#`P,"``,#`P,#`P(``````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````"\O/R]53D,O<V5R=F5R+W-H87)E+V9I;&4Q-0`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q +M(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3,V,S4`(#`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M=7-T87(`,#`````````````````````````````````````````````````` +M````````````````````````````````````,#`P,#`P(``P,#`P,#`@```` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````+R\_+U5.0R]F:6QE,38` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````#`P,#8T +M-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q +M,3(R-@`@,``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````!U<W1A<@`P,``````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`P,#`@`#`P,#`P,"`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```O+S\O54Y#+RXN+V9I;&4Q-P`````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P +M,#`@,3$Q-3`V-S0V-#(@,#$Q-#0R`"`P```````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````'5S=&%R`#`P```` +M```````````````````````````````````````````````````````````` +M`````````````````````#`P,#`P,"``,#`P,#`P(``````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````"\O/R]U;F,O<V5R=F5R+W-H87)E+V9I;&4Q +M.``````````````````````````````````````````````````````````` +M```````````````````````````````````````P,#`V-#0@`#`P,3<U,2`` +M,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,30P,#``(#`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````=7-T87(`,#`````````````````````````````````````````` +M````````````````````````````````````````````,#`P,#`P(``P,#`P +M,#`@```````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````+R\_+W5N8R]F +M:6QE,3D````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T +M-C0R(#`Q,3,W,0`@,``````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````!U<W1A<@`P,``````````````````` +M```````````````````````````````````````````````````````````` +M```````P,#`P,#`@`#`P,#`P,"`````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````O+S\O=6YC+RXN+V9I;&4R,``````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P +M,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q-3<T`"`P```````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````'5S=&%R +M`#`P```````````````````````````````````````````````````````` +M`````````````````````````````#`P,#`P,"``,#`P,#`P(``````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````%QF:6QE,C$````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````P,#`V-#0@`#`P +M,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3`T,34` +M(#`````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````=7-T87(`,#`````````````````````````````````` +M````````````````````````````````````````````````````,#`P,#`P +M(``P,#`P,#`@```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````````7"XN +M7&9I;&4R,@`````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q +M,34P-C<T-C0R(#`Q,#<P-@`@,``````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````!U<W1A<@`P,``````````` +M```````````````````````````````````````````````````````````` +M```````````````P,#`P,#`@`#`P,#`P,"`````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````!<+BY<+BY<9FEL93(S```````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U +M,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,3<W`"`P```````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`'5S=&%R`#`P```````````````````````````````````````````````` +M`````````````````````````````````````#`P,#`P,"``,#`P,#`P(``` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````$,Z7&9I;&4R-``````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````P,#`V +M-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P +M,3`V,34`(#`````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````=7-T87(`,#`````````````````````````` +M```````````````````````````````````````````````````````````` +M,#`P,#`P(``P,#`P,#`@```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````>CHN+EQF:6QE,C4````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P +M,#`P(#$Q,34P-C<T-C0R(#`Q,3`T,0`@,``````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````!U<W1A<@`P,``` +M```````````````````````````````````````````````````````````` +M```````````````````````P,#`P,#`@`#`P,#`P,"`````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````!C.BXN7"XN7&9I;&4R-@`````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````,#`P-C0T(``P,#$W-3$@ +M`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,S`S`"`P```` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````'5S=&%R`#`P```````````````````````````````````````` +M`````````````````````````````````````````````#`P,#`P,"``,#`P +M,#`P(``````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````%HZ7"XN7&9I +M;&4R-P`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W +M-#8T,B`P,3$Q,S<`(#`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````=7-T87(`,#`````````````````` +M```````````````````````````````````````````````````````````` +M````````,#`P,#`P(``P,#`P,#`@```````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````0SI<+BY<+BY<9FEL93(X```````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P +M,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,30P,0`@,``````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````!U<W1A +M<@`P,``````````````````````````````````````````````````````` +M```````````````````````````````P,#`P,#`@`#`P,#`P,"`````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````!<7"Y<8SI<9FEL93(Y```````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````,#`P-C0T(``P +M,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,S8T +M`"`P```````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````'5S=&%R`#`P```````````````````````````````` +M`````````````````````````````````````````````````````#`P,#`P +M,"``,#`P,#`P(``````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````%Q< +M+EQ#.EPN+EQF:6QE,S`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q +M,3$U,#8W-#8T,B`P,3$V,#0`(#`````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````=7-T87(`,#`````````` +M```````````````````````````````````````````````````````````` +M````````````````,#`P,#`P(``P,#`P,#`@```````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````7%P_7&,Z7&9I;&4S,0`````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W +M-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,3,W-@`@,``````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``!U<W1A<@`P,``````````````````````````````````````````````` +M```````````````````````````````````````P,#`P,#`@`#`P,#`P,"`` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!<7#]<1#I<+BY<9FEL +M93,R```````````````````````````````````````````````````````` +M````````````````````````````````````````````````````````,#`P +M-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@ +M,#$Q-C,P`"`P```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````'5S=&%R`#`P```````````````````````` +M```````````````````````````````````````````````````````````` +M`#`P,#`P,"``,#`P,#`P(``````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````%Q<7%QC.EQF:6QE,S,````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P +M,#`P,"`Q,3$U,#8W-#8T,B`P,3$T,S4`(#`````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````=7-T87(`,#`` +M```````````````````````````````````````````````````````````` +M````````````````````````,#`P,#`P(``P,#`P,#`@```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````7%Q<7$,Z7%Q<7%QF:6QE,S0````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````#`P,#8T-"``,#`Q-S4Q +M(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,C$U-@`@,``` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````!U<W1A<@`P,``````````````````````````````````````` +M```````````````````````````````````````````````P,#`P,#`@`#`P +M,#`P,"`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!<7#]<54Y# +M7'-E<G9E<EQS:&%R95QF:6QE,S4````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V +M-S0V-#(@,#$T,C4U`"`P```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````'5S=&%R`#`P```````````````` +M```````````````````````````````````````````````````````````` +M`````````#`P,#`P,"``,#`P,#`P(``````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````%Q</UQ53D-<9FEL93,V```````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P +M,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$U,30`(#`````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````````=7-T +M87(`,#`````````````````````````````````````````````````````` +M````````````````````````````````,#`P,#`P(``P,#`P,#`@```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````7%P_7%5.0UPN+EQF:6QE,S<` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````#`P,#8T-"`` +M,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,C`P +M-0`@,``````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````!U<W1A<@`P,``````````````````````````````` +M```````````````````````````````````````````````````````P,#`P +M,#`@`#`P,#`P,"`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!< +M7#]<=6YC7'-E<G9E<EQS:&%R95QF:6QE,S@````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@ +M,3$Q-3`V-S0V-#(@,#$T-#(P`"`P```````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````'5S=&%R`#`P```````` +M```````````````````````````````````````````````````````````` +M`````````````````#`P,#`P,"``,#`P,#`P(``````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````%Q</UQU;F-<9FEL93,Y```````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````P,#`V-#0@`#`P,3<U,2``,#`Q +M-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$V-3<`(#`````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````=7-T87(`,#`````````````````````````````````````````````` +M````````````````````````````````````````,#`P,#`P(``P,#`P,#`@ +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````7%P_7'5N8UPN+EQF +M:6QE-#`````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````#`P +M,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R +M(#`Q,C$S-P`@,``````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````!U<W1A<@`P,``````````````````````` +M```````````````````````````````````````````````````````````` +M```P,#`P,#`@`#`P,#`P,"`````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````!<+BXO9FEL930Q```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P +M,#`P,#`@,3$Q-3`V-S0V-#(@,#$P-C,R`"`P```````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````'5S=&%R`#`P +M```````````````````````````````````````````````````````````` +M`````````````````````````#`P,#`P,"``,#`P,#`P(``````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````%PN+B\N+EQF:6QE-#(````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````P,#`V-#0@`#`P,3<U +M,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$Q,C,`(#`` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````=7-T87(`,#`````````````````````````````````````` +M````````````````````````````````````````````````,#`P,#`P(``P +M,#`P,#`@```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````8SHN+B\N +M+EQF:6QE-#,````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P(#$Q,34P +M-C<T-C0R(#`Q,3(R-0`@,``````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````!U<W1A<@`P,``````````````` +M```````````````````````````````````````````````````````````` +M```````````P,#`P,#`@`#`P,#`P,"`````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````!#.B\N+EQF:6QE-#0````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P,3<U,2`` +M,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,#,R`"`P```````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````'5S +M=&%R`#`P```````````````````````````````````````````````````` +M`````````````````````````````````#`P,#`P,"``,#`P,#`P(``````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````$0Z7"XN+RXN7&9I;&4T-0`` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````P,#`V-#0@ +M`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T,B`P,3$S +M,C0`(#`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````=7-T87(`,#`````````````````````````````` +M````````````````````````````````````````````````````````,#`P +M,#`P(``P,#`P,#`@```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M7"\N+V,Z7&9I;&4T-@`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P,#`P,#`P +M(#$Q,34P-C<T-C0R(#`Q,3(S,0`@,``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,``````` +M```````````````````````````````````````````````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````!<7"XO0SI<+BY<9FEL930W```````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````,#`P-C0T(``P,#$W-3$@`#`P +M,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q-3,W`"`P```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````'5S=&%R`#`P```````````````````````````````````````````` +M`````````````````````````````````````````#`P,#`P,"``,#`P,#`P +M(``````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````%PO/UQC.B]F:6QE +M-#@````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U,#8W-#8T +M,B`P,3$R-30`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#`````````````````````` +M```````````````````````````````````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````7%P_+T0Z+RXN7&9I;&4T.0`````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@`#`P,#`P +M,#`P,#`P(#$Q,34P-C<T-C0R(#`Q,34P-@`@,``````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!U<W1A<@`P +M,``````````````````````````````````````````````````````````` +M```````````````````````````P,#`P,#`@`#`P,#`P,"`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````!<+R]<1#I<9FEL934P```````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````,#`P-C0T(``P,#$W +M-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q,C0S`"`P +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````'5S=&%R`#`P```````````````````````````````````` +M`````````````````````````````````````````````````#`P,#`P,"`` +M,#`P,#`P(``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````%Q<+R]C +M.EPO+UQ<9FEL934Q```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P,"`Q,3$U +M,#8W-#8T,B`P,3$W,S$`(#`````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````=7-T87(`,#`````````````` +M```````````````````````````````````````````````````````````` +M````````````,#`P,#`P(``P,#`P,#`@```````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````7"\_+W5.8R]S97)V97)<<VAA<F5<9FEL934R```````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````#`P,#8T-"``,#`Q-S4Q(``P,#$W-3$@ +M`#`P,#`P,#`P,#`P(#$Q,34P-C<T-C0R(#`Q-#$T-0`@,``````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!U +M<W1A<@`P,``````````````````````````````````````````````````` +M```````````````````````````````````P,#`P,#`@`#`P,#`P,"`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````!<7#\O54YC7&9I;&4U,P`` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````,#`P-C0T +M(``P,#$W-3$@`#`P,3<U,2``,#`P,#`P,#`P,#`@,3$Q-3`V-S0V-#(@,#$Q +M-#<V`"`P```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````'5S=&%R`#`P```````````````````````````` +M`````````````````````````````````````````````````````````#`P +M,#`P,"``,#`P,#`P(``````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`%PO/UQ5;D-<+BXO9FEL934T```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````P,#`V-#0@`#`P,3<U,2``,#`Q-S4Q(``P,#`P,#`P,#`P +M,"`Q,3$U,#8W-#8T,B`P,3$W,3(`(#`````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````=7-T87(`,#`````` +M```````````````````````````````````````````````````````````` +M````````````````````,#`P,#`P(``P,#`P,#`@```````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +'```````````` +` +end diff --git a/archivers/libarchive/files/tar/test/test_stdio.c b/archivers/libarchive/files/tar/test/test_stdio.c index d770cf11f40..b95a4e30542 100644 --- a/archivers/libarchive/files/tar/test/test_stdio.c +++ b/archivers/libarchive/files/tar/test/test_stdio.c @@ -27,27 +27,27 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/test/test_stdio.c,v 1.2 2008/05/26 17:10:10 DEFINE_TEST(test_stdio) { - int fd; - int filelist; - int oldumask; + FILE *filelist; + char *p; + size_t s; int r; - oldumask = umask(0); + assertUmask(0); /* * Create a couple of files on disk. */ - filelist = open("filelist", O_CREAT | O_WRONLY, 0644); /* File */ - fd = open("f", O_CREAT | O_WRONLY, 0644); - assert(fd >= 0); - write(fd, "f\n", 2); - close(fd); - write(filelist, "f\n", 2); + assertMakeFile("f", 0755, "abc"); /* Link to above file. */ - assertEqualInt(0, link("f", "l")); - write(filelist, "l\n", 2); - close(filelist); + assertMakeHardlink("l", "f"); + + /* Create file list (text mode here) */ + filelist = fopen("filelist", "w"); + assert(filelist != NULL); + fprintf(filelist, "f\n"); + fprintf(filelist, "l\n"); + fclose(filelist); /* * Archive/dearchive with a variety of options, verifying @@ -111,7 +111,10 @@ DEFINE_TEST(test_stdio) /* 'xvOf' should generate list on stderr, file contents on stdout. */ r = systemf("%s xvOf archive >xvOf.out 2>xvOf.err", testprog); assertEqualInt(r, 0); - /* TODO: Verify xvOf.out */ + /* Verify xvOf.out is the file contents */ + p = slurpfile(&s, "xvOf.out"); + assert(s = 3); + assertEqualMem(p, "abc", 3); /* TODO: Verify xvf.err */ /* 'xvf -' should generate list on stderr, empty stdout. */ @@ -119,6 +122,4 @@ DEFINE_TEST(test_stdio) assertEqualInt(r, 0); assertEmptyFile("xvf-.out"); /* TODO: Verify xvf-.err */ - - umask(oldumask); } diff --git a/archivers/libarchive/files/tar/test/test_strip_components.c b/archivers/libarchive/files/tar/test/test_strip_components.c new file mode 100644 index 00000000000..c9028a4d766 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_strip_components.c @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_strip_components.c,v 1.2 2008/11/10 05:24:13 kientzle Exp $"); + +static int +touch(const char *fn) +{ + FILE *f = fopen(fn, "w"); + failure("Couldn't create file '%s', errno=%d (%s)\n", + fn, errno, strerror(errno)); + if (!assert(f != NULL)) + return (0); /* Failure. */ + fclose(f); + return (1); /* Success */ +} + +DEFINE_TEST(test_strip_components) +{ + assertMakeDir("d0", 0755); + assertChdir("d0"); + assertMakeDir("d1", 0755); + assertMakeDir("d1/d2", 0755); + assertMakeDir("d1/d2/d3", 0755); + assertEqualInt(1, touch("d1/d2/f1")); + assertMakeHardlink("l1", "d1/d2/f1"); + assertMakeHardlink("d1/l2", "d1/d2/f1"); + if (canSymlink()) { + assertMakeSymlink("s1", "d1/d2/f1"); + assertMakeSymlink("d1/s2", "d2/f1"); + } + assertChdir(".."); + + assertEqualInt(0, systemf("%s -cf test.tar d0", testprog)); + + assertMakeDir("target", 0755); + assertEqualInt(0, systemf("%s -x -C target --strip-components 2 " + "-f test.tar", testprog)); + + failure("d0/ is too short and should not get restored"); + assertFileNotExists("target/d0"); + failure("d0/d1/ is too short and should not get restored"); + assertFileNotExists("target/d1"); + failure("d0/d1/s2 is a symlink to something that won't be extracted"); + /* If platform supports symlinks, target/s2 is a broken symlink. */ + /* If platform does not support symlink, target/s2 doesn't exist. */ + assertFileNotExists("target/s2"); + if (canSymlink()) + assertIsSymlink("target/s2", "d2/f1"); + failure("d0/d1/d2 should be extracted"); + assertIsDir("target/d2", -1); + + /* + * This next is a complicated case. d0/l1, d0/d1/l2, and + * d0/d1/d2/f1 are all hardlinks to the same file; d0/l1 can't + * be extracted with --strip-components=2 and the other two + * can. Remember that tar normally stores the first file with + * a body and the other as hardlink entries to the first + * appearance. So the final result depends on the order in + * which these three names get archived. If d0/l1 is first, + * none of the three can be restored. If either of the longer + * names are first, then the two longer ones can both be + * restored. + * + * The tree-walking code used by bsdtar always visits files + * before subdirectories, so bsdtar's behavior is fortunately + * deterministic: d0/l1 will always get stored first and the + * other two will be stored as hardlinks to d0/l1. Since + * d0/l1 can't be extracted, none of these three will be + * extracted. + * + * It may be worth extending this test to force a particular + * archiving order so as to exercise both of the cases described + * above. + * + * Of course, this is all totally different for cpio and newc + * formats because the hardlink management is different. + * TODO: Rename this to test_strip_components_tar and create + * parallel tests for cpio and newc formats. + */ + failure("d0/l1 is too short and should not get restored"); + assertFileNotExists("target/l1"); + failure("d0/d1/l2 is a hardlink to file whose name was too short"); + assertFileNotExists("target/l2"); + failure("d0/d1/d2/f1 is a hardlink to file whose name was too short"); + assertFileNotExists("target/d2/f1"); +} diff --git a/archivers/libarchive/files/tar/test/test_symlink_dir.c b/archivers/libarchive/files/tar/test/test_symlink_dir.c new file mode 100644 index 00000000000..aa80ba68e31 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_symlink_dir.c @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/test/test_symlink_dir.c,v 1.1 2008/09/14 02:16:04 kientzle Exp $"); + +/* + * tar -x -P should follow existing symlinks for dirs, but not other + * content. Plain tar -x should remove symlinks when they're in the + * way of a dir extraction. + */ + +static int +mkfile(const char *name, int mode, const char *contents, size_t size) +{ + FILE *f = fopen(name, "wb"); + size_t written; + + (void)mode; /* UNUSED */ + if (f == NULL) + return (-1); + written = fwrite(contents, 1, size, f); + fclose(f); + if (size != written) + return (-1); + return (0); +} + +DEFINE_TEST(test_symlink_dir) +{ + assertUmask(0); + + assertMakeDir("source", 0755); + assertEqualInt(0, mkfile("source/file", 0755, "a", 1)); + assertEqualInt(0, mkfile("source/file2", 0755, "ab", 2)); + assertMakeDir("source/dir", 0755); + assertMakeDir("source/dir/d", 0755); + assertEqualInt(0, mkfile("source/dir/f", 0755, "abc", 3)); + assertMakeDir("source/dir2", 0755); + assertMakeDir("source/dir2/d2", 0755); + assertEqualInt(0, mkfile("source/dir2/f2", 0755, "abcd", 4)); + assertMakeDir("source/dir3", 0755); + assertMakeDir("source/dir3/d3", 0755); + assertEqualInt(0, mkfile("source/dir3/f3", 0755, "abcde", 5)); + + assertEqualInt(0, + systemf("%s -cf test.tar -C source dir dir2 dir3 file file2", + testprog)); + + /* + * Extract with -x and without -P. + */ + assertMakeDir("dest1", 0755); + /* "dir" is a symlink to an existing "dest1/real_dir" */ + assertMakeDir("dest1/real_dir", 0755); + if (canSymlink()) { + assertMakeSymlink("dest1/dir", "real_dir"); + /* "dir2" is a symlink to a non-existing "real_dir2" */ + assertMakeSymlink("dest1/dir2", "real_dir2"); + } else { + skipping("some symlink checks"); + } + /* "dir3" is a symlink to an existing "non_dir3" */ + assertEqualInt(0, mkfile("dest1/non_dir3", 0755, "abcdef", 6)); + if (canSymlink()) + assertMakeSymlink("dest1/dir3", "non_dir3"); + /* "file" is a symlink to existing "real_file" */ + assertEqualInt(0, mkfile("dest1/real_file", 0755, "abcdefg", 7)); + if (canSymlink()) { + assertMakeSymlink("dest1/file", "real_file"); + /* "file2" is a symlink to non-existing "real_file2" */ + assertMakeSymlink("dest1/file2", "real_file2"); + } + assertEqualInt(0, systemf("%s -xf test.tar -C dest1", testprog)); + + /* dest1/dir symlink should be replaced */ + failure("symlink to dir was followed when it shouldn't be"); + assertIsDir("dest1/dir", -1); + /* dest1/dir2 symlink should be replaced */ + failure("Broken symlink wasn't replaced with dir"); + assertIsDir("dest1/dir2", -1); + /* dest1/dir3 symlink should be replaced */ + failure("Symlink to non-dir wasn't replaced with dir"); + assertIsDir("dest1/dir3", -1); + /* dest1/file symlink should be replaced */ + failure("Symlink to existing file should be replaced"); + assertIsReg("dest1/file", -1); + /* dest1/file2 symlink should be replaced */ + failure("Symlink to non-existing file should be replaced"); + assertIsReg("dest1/file2", -1); + + /* + * Extract with both -x and -P + */ + assertMakeDir("dest2", 0755); + /* "dir" is a symlink to existing "real_dir" */ + assertMakeDir("dest2/real_dir", 0755); + if (canSymlink()) + assertMakeSymlink("dest2/dir", "real_dir"); + /* "dir2" is a symlink to a non-existing "real_dir2" */ + if (canSymlink()) + assertMakeSymlink("dest2/dir2", "real_dir2"); + /* "dir3" is a symlink to an existing "non_dir3" */ + assertEqualInt(0, mkfile("dest2/non_dir3", 0755, "abcdefgh", 8)); + if (canSymlink()) + assertMakeSymlink("dest2/dir3", "non_dir3"); + /* "file" is a symlink to existing "real_file" */ + assertEqualInt(0, mkfile("dest2/real_file", 0755, "abcdefghi", 9)); + if (canSymlink()) + assertMakeSymlink("dest2/file", "real_file"); + /* "file2" is a symlink to non-existing "real_file2" */ + if (canSymlink()) + assertMakeSymlink("dest2/file2", "real_file2"); + assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog)); + + /* dest2/dir symlink should be followed */ + if (canSymlink()) { + assertIsSymlink("dest2/dir", "real_dir"); + assertIsDir("dest2/real_dir", -1); + } + + /* Contents of 'dir' should be restored */ + assertIsDir("dest2/dir/d", -1); + assertIsReg("dest2/dir/f", -1); + assertFileSize("dest2/dir/f", 3); + /* dest2/dir2 symlink should be removed */ + failure("Broken symlink wasn't replaced with dir"); + assertIsDir("dest2/dir2", -1); + /* dest2/dir3 symlink should be removed */ + failure("Symlink to non-dir wasn't replaced with dir"); + assertIsDir("dest2/dir3", -1); + /* dest2/file symlink should be removed; + * even -P shouldn't follow symlinks for files */ + failure("Symlink to existing file should be removed"); + assertIsReg("dest2/file", -1); + /* dest2/file2 symlink should be removed */ + failure("Symlink to non-existing file should be removed"); + assertIsReg("dest2/file2", -1); +} diff --git a/archivers/libarchive/files/tar/test/test_version.c b/archivers/libarchive/files/tar/test/test_version.c index 6ed656d8024..42472d1bc26 100644 --- a/archivers/libarchive/files/tar/test/test_version.c +++ b/archivers/libarchive/files/tar/test/test_version.c @@ -51,8 +51,9 @@ DEFINE_TEST(test_version) q = p = slurpfile(&s, "version.stdout"); /* Version message should start with name of program, then space. */ assert(s > 6); - failure("Version: %s", p); - assertEqualMem(q, "bsdtar ", 7); + failure("Version must start with 'bsdtar': ``%s''", p); + if (!assertEqualMem(q, "bsdtar ", 7)) + return; q += 7; s -= 7; /* Version number is a series of digits and periods. */ while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) { @@ -60,22 +61,22 @@ DEFINE_TEST(test_version) --s; } /* Version number terminated by space. */ - failure("Version: %s", p); + 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("Version: %s", p); + failure("No space after bsdtar version: ``%s''", p); assert(*q == ' '); ++q; --s; /* Separator. */ - failure("Version: %s", p); + failure("No `-' between bsdtar and libarchive versions: ``%s''", p); assertEqualMem(q, "- ", 2); q += 2; s -= 2; /* libarchive name and version number */ - failure("Version: %s", p); + failure("Not long enough for libarchive version: ``%s''", p); assert(s > 11); - failure("Version: %s", p); + 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. */ @@ -86,8 +87,11 @@ DEFINE_TEST(test_version) /* Skip a single trailing a,b,c, or d. */ if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd') ++q; - /* All terminated by a newline. */ + /* 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); } diff --git a/archivers/libarchive/files/tar/test/test_windows.c b/archivers/libarchive/files/tar/test/test_windows.c new file mode 100644 index 00000000000..a2d0c214b95 --- /dev/null +++ b/archivers/libarchive/files/tar/test/test_windows.c @@ -0,0 +1,323 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * 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" + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include <windows.h> + +static void +mkfile(const char *name) +{ + FILE *f; + + f = fopen(name, "wb"); + assert(f != NULL); + assertEqualInt(5, fwrite("01234", 1, 5, f)); + fclose(f); +} + +static void +mkfullpath(char **path1, char **path2, const char *tpath, int type) +{ + char *fp1 = NULL, *fp2 = NULL, *p1 = NULL, *p2 = NULL; + size_t l; + + /* + * Get full path name of "tpath" + */ + l = GetFullPathNameA(tpath, 0, NULL, NULL); + assert(0 != l); + fp1 = malloc(l); + assert(NULL != fp1); + fp2 = malloc(l*2); + assert(NULL != fp2); + l = GetFullPathNameA(tpath, l, fp1, NULL); + if ((type & 0x01) == 0) { + for (p1 = fp1; *p1 != '\0'; p1++) + if (*p1 == '\\') + *p1 = '/'; + } + + switch(type) { + case 0: /* start with "/" */ + case 1: /* start with "\" */ + /* strip "c:" */ + memmove(fp1, fp1 + 2, l - 2); + fp1[l -2] = '\0'; + p1 = fp1 + 1; + break; + case 2: /* start with "c:/" */ + case 3: /* start with "c:\" */ + p1 = fp1 + 3; + break; + case 4: /* start with "//./c:/" */ + case 5: /* start with "\\.\c:\" */ + case 6: /* start with "//?/c:/" */ + case 7: /* start with "\\?\c:\" */ + p1 = malloc(l + 4 + 1); + assert(NULL != p1); + if (type & 0x1) + memcpy(p1, "\\\\.\\", 4); + else + memcpy(p1, "//./", 4); + if (type == 6 || type == 7) + p1[2] = '?'; + memcpy(p1 + 4, fp1, l); + p1[l + 4] = '\0'; + free(fp1); + fp1 = p1; + p1 = fp1 + 7; + break; + } + + /* + * Strip leading drive names and converting "\" to "\\" + */ + p2 = fp2; + while (*p1 != '\0') { + if (*p1 == '\\') + *p2 = '/'; + else + *p2 = *p1; + ++p1; + ++p2; + } + *p2++ = '\r'; + *p2++ = '\n'; + *p2 = '\0'; + + *path1 = fp1; + *path2 = fp2; +} + +static const char *list1[] = {"aaa/", "aaa/file1", "aaa/xxa/", "aaa/xxb/", + "aaa/zzc/", "aaa/zzc/file1", "aaa/xxb/file1", "aaa/xxa/file1", + "aab/", "aac/", "abb/", "abc/", "abd/", NULL}; +static const char *list2[] = {"bbb/", "bbb/file1", "bbb/xxa/", "bbb/xxb/", + "bbb/zzc/", "bbb/zzc/file1", "bbb/xxb/file1", "bbb/xxa/file1", "bbc/", + "bbd/", "bcc/", "bcd/", "bce/", NULL}; +static const char *list3[] = {"aac/", "abc/", "bbc/", "bcc/", "ccc/", NULL}; +static const char *list4[] = {"fff/abca", "fff/acca", NULL}; +static const char *list5[] = {"aaa/file1", "aaa/xxa/", "aaa/xxa/file1", + "aaa/xxb/", "aaa/xxb/file1", "aaa/zzc/", "aaa/zzc/file1", NULL}; +static const char *list6[] = {"fff/abca", "fff/acca", "aaa/xxa/", + "aaa/xxa/file1", "aaa/xxb/", "aaa/xxb/file1", NULL}; +#endif /* _WIN32 && !__CYGWIN__ */ + +DEFINE_TEST(test_windows) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char *fp1, *fp2; + + /* + * Preparre tests. + * Create directories and files. + */ + assertMakeDir("tmp", 0775); + assertChdir("tmp"); + + assertMakeDir("aaa", 0775); + assertMakeDir("aaa/xxa", 0775); + assertMakeDir("aaa/xxb", 0775); + assertMakeDir("aaa/zzc", 0775); + mkfile("aaa/file1"); + mkfile("aaa/xxa/file1"); + mkfile("aaa/xxb/file1"); + mkfile("aaa/zzc/file1"); + assertMakeDir("aab", 0775); + assertMakeDir("aac", 0775); + assertMakeDir("abb", 0775); + assertMakeDir("abc", 0775); + assertMakeDir("abd", 0775); + assertMakeDir("bbb", 0775); + assertMakeDir("bbb/xxa", 0775); + assertMakeDir("bbb/xxb", 0775); + assertMakeDir("bbb/zzc", 0775); + mkfile("bbb/file1"); + mkfile("bbb/xxa/file1"); + mkfile("bbb/xxb/file1"); + mkfile("bbb/zzc/file1"); + assertMakeDir("bbc", 0775); + assertMakeDir("bbd", 0775); + assertMakeDir("bcc", 0775); + assertMakeDir("bcd", 0775); + assertEqualInt(0, _mkdir("bce")); + assertEqualInt(0, _mkdir("ccc")); + assertEqualInt(0, _mkdir("fff")); + mkfile("fff/aaaa"); + mkfile("fff/abba"); + mkfile("fff/abca"); + mkfile("fff/acba"); + mkfile("fff/acca"); + + /* + * Test1: Command line pattern matching. + */ + assertEqualInt(0, + systemf("%s -cf ../archive1.tar a*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive1.tar > ../list1", testprog)); + assertFileContainsLinesAnyOrder("../list1", list1); + + assertEqualInt(0, + systemf("%s -cf ../archive2.tar b*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive2.tar > ../list2", testprog)); + assertFileContainsLinesAnyOrder("../list2", list2); + + assertEqualInt(0, + systemf("%s -cf ../archive3.tar ??c", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive3.tar > ../list3", testprog)); + assertFileContainsLinesAnyOrder("../list3", list3); + + assertEqualInt(0, + systemf("%s -cf ../archive3b.tar *c", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive3b.tar > ../list3b", testprog)); + assertFileContainsLinesAnyOrder("../list3b", list3); + + assertEqualInt(0, + systemf("%s -cf ../archive4.tar fff/a?ca", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive4.tar > ../list4", testprog)); + assertFileContainsLinesAnyOrder("../list4", list4); + + assertEqualInt(0, + systemf("%s -cf ../archive5.tar aaa\\*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive5.tar > ../list5", testprog)); + assertFileContainsLinesAnyOrder("../list5", list5); + + assertEqualInt(0, + systemf("%s -cf ../archive6.tar fff\\a?ca aaa\\xx*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive6.tar > ../list6", testprog)); + assertFileContainsLinesAnyOrder("../list6", list6); + + /* + * Test2: Archive the file start with drive letters. + */ + /* Test2a: start with "/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 0); + assertEqualInt(0, + systemf("%s -cf ../archive10.tar %s > ../out10 2> ../err10", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive10.tar > ../list10", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list10"); + free(fp1); + free(fp2); + + /* Test2b: start with "\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 1); + assertEqualInt(0, + systemf("%s -cf ../archive11.tar %s > ../out11 2> ../err11", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive11.tar > ../list11", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list11"); + free(fp1); + free(fp2); + + /* Test2c: start with "c:/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 2); + assertEqualInt(0, + systemf("%s -cf ../archive12.tar %s > ../out12 2> ../err12", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive12.tar > ../list12", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list12"); + free(fp1); + free(fp2); + + /* Test2d: start with "c:\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 3); + assertEqualInt(0, + systemf("%s -cf ../archive13.tar %s > ../out13 2> ../err13", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive13.tar > ../list13", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list13"); + free(fp1); + free(fp2); + + /* Test2e: start with "//./c:/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 4); + assertEqualInt(0, + systemf("%s -cf ../archive14.tar %s > ../out14 2> ../err14", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive14.tar > ../list14", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list14"); + free(fp1); + free(fp2); + + /* Test2f: start with "\\.\c:\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 5); + assertEqualInt(0, + systemf("%s -cf ../archive15.tar %s > ../out15 2> ../err15", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive15.tar > ../list15", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list15"); + free(fp1); + free(fp2); + + /* Test2g: start with "//?/c:/" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 6); + failure("fp1=%s, fp2=%s", fp1, fp2); + assertEqualInt(0, + systemf("%s -cf ../archive16.tar %s > ../out16 2> ../err16", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive16.tar > ../list16", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list16"); + free(fp1); + free(fp2); + + /* Test2h: start with "\\?\c:\" */ + mkfullpath(&fp1, &fp2, "aaa/file1", 7); + failure("fp1=%s, fp2=%s", fp1, fp2); + assertEqualInt(0, + systemf("%s -cf ../archive17.tar %s > ../out17 2> ../err17", + testprog, fp1)); + assertEqualInt(0, + systemf("%s -tf ../archive17.tar > ../list17", testprog)); + /* Check drive letters have been stripped. */ + assertFileContents(fp2, strlen(fp2), "../list17"); + free(fp1); + free(fp2); +#else + skipping("Windows specific test"); +#endif /* _WIN32 && !__CYGWIN__ */ +} |