diff options
Diffstat (limited to 'Utilities/cmlibarchive/tar/test')
21 files changed, 5758 insertions, 0 deletions
diff --git a/Utilities/cmlibarchive/tar/test/CMakeLists.txt b/Utilities/cmlibarchive/tar/test/CMakeLists.txt new file mode 100644 index 0000000..81870c4 --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/CMakeLists.txt @@ -0,0 +1,62 @@ +############################################ +# +# 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_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) + + # + # Generate the list.h + # + 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}) + # + # Register target + # + ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES}) + SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H) + + # ADD_TEST() for each separate test + SET(num 0) + FOREACH(test ${bsdtar_test_SOURCES}) + IF(test MATCHES "^test_[^/]+[.]c$") + STRING(REGEX REPLACE "^(test_[^/]+)[.]c$" "\\1" testname ${test}) + ADD_TEST("bsdtar_${testname}" bsdtar_test + -q -v -p ${BSDTAR} -r ${CMAKE_CURRENT_SOURCE_DIR} ${num}) + MATH(EXPR num "${num} + 1") + ENDIF(test MATCHES "^test_[^/]+[.]c$") + ENDFOREACH(test) + + # 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/Utilities/cmlibarchive/tar/test/main.c b/Utilities/cmlibarchive/tar/test/main.c new file mode 100644 index 0000000..9815a85 --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/main.c @@ -0,0 +1,2057 @@ +/* + * 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 <errno.h> +#include <locale.h> +#include <stdarg.h> +#include <time.h> +#include "test.h" + +/* + * This same file is used pretty much verbatim for all test harnesses. + * + * The next few lines are the only differences. + * TODO: Move this into a separate configuration header, have all test + * suites share one copy of this file. + */ +__FBSDID("$FreeBSD: src/usr.bin/tar/test/main.c,v 1.6 2008/11/05 06:40:53 kientzle Exp $"); +#define KNOWNREF "test_patterns_2.tar.uu" +#define ENVBASE "BSDTAR" /* Prefix for environment variables. */ +#define PROGRAM "bsdtar" /* Name of program being tested. */ +#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) ? "" : "") + +/* + * + * Windows support routines + * + * Note: Configuration is a tricky issue. Using HAVE_* feature macros + * in the test harness is dangerous because they cover up + * configuration errors. The classic example of this is omitting a + * configure check. If libarchive and libarchive_test both look for + * the same feature macro, such errors are hard to detect. Platform + * macros (e.g., _WIN32 or __GNUC__) are a little better, but can + * easily lead to very messy code. It's best to limit yourself + * to only the most generic programming techniques in the test harness + * and thus avoid conditionals altogether. Where that's not possible, + * try to minimize conditionals by grouping platform-specific tests in + * one place (e.g., test_acl_freebsd) or by adding new assert() + * functions (e.g., assertMakeHardlink()) to cover up platform + * differences. Platform-specific coding in libarchive_test is often + * a symptom that some capability is missing from libarchive itself. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) +#if !defined(__GNUC__) +#include <crtdbg.h> +#endif +#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 +#define access _access +#ifndef fileno +#define fileno _fileno +#endif +/*#define fstat _fstat64*/ +#define getcwd _getcwd +#define lstat stat +/*#define lstat _stat64*/ +/*#define stat _stat64*/ +#define rmdir _rmdir +#define strdup _strdup +#define umask _umask +#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; + + 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 + +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__) +static void +invalid_parameter_handler(const wchar_t * expression, + const wchar_t * function, const wchar_t * file, + unsigned int line, uintptr_t pReserved) +{ + /* nop */ +} +#endif + +/* + * + * OPTIONS FLAGS + * + */ + +/* Enable core dump on failure. */ +static int dump_on_failure = 0; +/* Default is to remove temp dirs and log data for successful tests. */ +static int keep_temp_files = 0; +/* Default is to just report pass/fail for each test. */ +static int verbosity = 0; +#define VERBOSITY_SUMMARY_ONLY -1 /* -q */ +#define VERBOSITY_PASSFAIL 0 /* Default */ +#define VERBOSITY_LIGHT_REPORT 1 /* -v */ +#define VERBOSITY_FULL 2 /* -vv */ +/* A few places generate even more output for verbosity > VERBOSITY_FULL, + * mostly for debugging the test harness itself. */ +/* Cumulative count of assertion failures. */ +static int failures = 0; +/* Cumulative count of reported skips. */ +static int skips = 0; +/* Cumulative count of assertions checked. */ +static int assertions = 0; + +/* Directory where uuencoded reference files can be found. */ +static const char *refdir; + +/* + * Report log information selectively to console and/or disk log. + */ +static int log_console = 0; +static FILE *logfile; +static void +vlogprintf(const char *fmt, va_list ap) +{ + if (log_console) + vfprintf(stdout, fmt, ap); + if (logfile != NULL) + vfprintf(logfile, fmt, ap); +} + +static void +logprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vlogprintf(fmt, ap); + va_end(ap); +} + +/* Set up a message to display only if next assertion fails. */ +static char msgbuff[4096]; +static const char *msg, *nextmsg; +void +failure(const char *fmt, ...) +{ + va_list ap; + 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 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); */ +} + +/* + * For each test source file, we remember how many times each + * assertion was reported. Cleared before each new test, + * used by test_summarize(). + */ +static struct line { + int count; + int skip; +} failed_lines[10000]; + +/* Count this failure, setup up log destination and handle initial report. */ +static void +failure_start(const char *filename, int line, const char *fmt, ...) +{ + va_list ap; + + /* Record another failure for this line. */ + ++failures; + /* 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); +#if _MSC_VER + logprintf("%s(%d): ", filename, line); +#else + logprintf("%s:%d: ", filename, line); +#endif + vlogprintf(fmt, ap); + va_end(ap); + logprintf("\n"); + + if (msg != NULL && msg[0] != '\0') { + logprintf(" Description: %s\n", msg); + msg = NULL; + } + + /* Determine whether to log details to console. */ + if (verbosity == VERBOSITY_LIGHT_REPORT) + log_console = 0; +} + +/* Complete reporting of failed tests. */ +/* + * The 'extra' hook here is used by libarchive to include libarchive + * error messages with assertion failures. It could also be used + * to add strerror() output, for example. Just define the EXTRA_DUMP() + * macro appropriately. + */ +static void +failure_finish(void *extra) +{ + (void)extra; /* UNUSED (maybe) */ +#ifdef EXTRA_DUMP + if (extra != NULL) + logprintf(" detail: %s\n", EXTRA_DUMP(extra)); +#endif + + if (dump_on_failure) { + fprintf(stderr, + " *** forcing core dump so failure can be debugged ***\n"); + *(char *)(NULL) = 0; + exit(1); + } +} + +/* Inform user that we're skipping some checks. */ +void +test_skipping(const char *fmt, ...) +{ + char buff[1024]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + /* 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 +assertion_assert(const char *file, int line, int value, + const char *condition, void *extra) +{ + assertion_count(file, line); + if (!value) { + failure_start(file, line, "Assertion failed: %s", condition); + failure_finish(extra); + } + return (value); +} + +/* chdir() and report any errors */ +int +assertion_chdir(const char *file, int line, const char *pathname) +{ + assertion_count(file, line); + if (chdir(pathname) == 0) + return (1); + failure_start(file, line, "chdir(\"%s\")", pathname); + failure_finish(NULL); + return (0); + +} + +/* Verify two integers are equal. */ +int +assertion_equal_int(const char *file, int line, + long long v1, const char *e1, long long v2, const char *e2, void *extra) +{ + assertion_count(file, line); + if (v1 == v2) + return (1); + failure_start(file, line, "%s != %s", e1, e2); + logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1); + logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2); + failure_finish(extra); + return (0); +} + +static void strdump(const char *e, const char *p) +{ + const char *q = p; + + logprintf(" %s = ", e); + if (p == NULL) { + logprintf("NULL"); + return; + } + logprintf("\""); + while (*p != '\0') { + unsigned int c = 0xff & *p++; + switch (c) { + 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) + logprintf("%c", c); + else + logprintf("\\x%02X", c); + } + } + logprintf("\""); + logprintf(" (length %d)\n", q == NULL ? -1 : (int)strlen(q)); +} + +/* Verify two strings are equal, dump them if not. */ +int +assertion_equal_string(const char *file, int line, + const char *v1, const char *e1, + const char *v2, const char *e2, + void *extra) +{ + assertion_count(file, line); + if (v1 == v2 || strcmp(v1, v2) == 0) + return (1); + failure_start(file, line, "%s != %s", e1, e2); + strdump(e1, v1); + strdump(e2, v2); + failure_finish(extra); + return (0); +} + +static void +wcsdump(const char *e, const wchar_t *w) +{ + logprintf(" %s = ", e); + if (w == NULL) { + logprintf("(null)"); + return; + } + logprintf("\""); + while (*w != L'\0') { + unsigned int c = *w++; + if (c >= 32 && c < 127) + logprintf("%c", c); + else if (c < 256) + logprintf("\\x%02X", c); + else if (c < 0x10000) + logprintf("\\u%04X", c); + else + logprintf("\\U%08X", c); + } + logprintf("\"\n"); +} + +/* Verify that two wide strings are equal, dump them if not. */ +int +assertion_equal_wstring(const char *file, int line, + const wchar_t *v1, const char *e1, + const wchar_t *v2, const char *e2, + void *extra) +{ + assertion_count(file, line); + if (v1 == v2 || wcscmp(v1, v2) == 0) + return (1); + failure_start(file, line, "%s != %s", e1, e2); + wcsdump(e1, v1); + wcsdump(e2, v2); + failure_finish(extra); + return (0); +} + +/* + * Pretty standard hexdump routine. As a bonus, if ref != NULL, then + * any bytes in p that differ from ref will be highlighted with '_' + * before and after the hex value. + */ +static void +hexdump(const char *p, const char *ref, size_t l, size_t offset) +{ + size_t i, j; + char sep; + + for(i=0; i < l; i+=16) { + logprintf("%04x", (unsigned)(i + offset)); + sep = ' '; + for (j = 0; j < 16 && i + j < l; j++) { + if (ref != NULL && p[i + j] != ref[i + j]) + sep = '_'; + logprintf("%c%02x", sep, 0xff & (int)p[i+j]); + if (ref != NULL && p[i + j] == ref[i + j]) + sep = ' '; + } + for (; j < 16; j++) { + logprintf("%c ", sep); + sep = ' '; + } + logprintf("%c", sep); + for (j=0; j < 16 && i + j < l; j++) { + int c = p[i + j]; + if (c >= ' ' && c <= 126) + logprintf("%c", c); + else + logprintf("."); + } + logprintf("\n"); + } +} + +/* Verify that two blocks of memory are the same, display the first + * block of differences if they're not. */ +int +assertion_equal_mem(const char *file, int line, + const void *_v1, const char *e1, + const void *_v2, const char *e2, + size_t l, const char *ld, void *extra) +{ + const char *v1 = (const char *)_v1; + const char *v2 = (const char *)_v2; + size_t offset; + + assertion_count(file, line); + if (v1 == v2 || 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; + } + 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 +assertion_empty_file(const char *f1fmt, ...) +{ + char buff[1024]; + char f1[1024]; + struct stat st; + va_list ap; + ssize_t s; + FILE *f; + + 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) + return (1); + + 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 = ((off_t)sizeof(buff) < st.st_size) ? + (ssize_t)sizeof(buff) : (ssize_t)st.st_size; + s = fread(buff, 1, s, f); + hexdump(buff, NULL, s, 0); + fclose(f); + } + failure_finish(NULL); + return (0); +} + +/* Verify that the named file exists and is not empty. */ +int +assertion_non_empty_file(const char *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 +assertion_equal_file(const char *fn1, const char *f2pattern, ...) +{ + char fn2[1024]; + va_list ap; + char buff1[1024]; + char buff2[1024]; + FILE *f1, *f2; + int n1, n2; + + assertion_count(test_filename, test_line); + va_start(ap, f2pattern); + vsprintf(fn2, f2pattern, ap); + va_end(ap); + + f1 = fopen(fn1, "rb"); + f2 = fopen(fn2, "rb"); + for (;;) { + n1 = fread(buff1, 1, sizeof(buff1), f1); + n2 = fread(buff2, 1, sizeof(buff2), f2); + if (n1 != n2) + break; + if (n1 == 0 && n2 == 0) { + fclose(f1); + fclose(f2); + return (1); + } + if (memcmp(buff1, buff2, n1) != 0) + break; + } + fclose(f1); + fclose(f2); + failure_start(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 +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); +#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 +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); +#endif + failure_start(test_filename, test_line, "File should not exist: %s", f); + failure_finish(test_extra); + return (0); +} + +/* Compare the contents of a file to a block of memory. */ +int +assertion_file_contents(const void *buff, int s, const char *fpattern, ...) +{ + char fn[1024]; + va_list ap; + char *contents; + FILE *f; + int n; + + assertion_count(test_filename, test_line); + va_start(ap, fpattern); + vsprintf(fn, fpattern, ap); + va_end(ap); + + 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 = fread(contents, 1, s * 2, f); + fclose(f); + if (n == s && memcmp(buff, contents, s) == 0) { + free(contents); + return (1); + } + 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 : n, 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; + } + 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); +} + +/* 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.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 */ +#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 == 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) +{ + struct stat st; + int r; + + assertion_count(file, line); + r = lstat(pathname, &st); + if (r == 0 && st.st_size == size) + return (1); + failure_start(file, line, "File %s has size %ld, expected %ld", + pathname, (long)st.st_size, (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; + + 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; + + 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__) + 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__) + 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; + 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. + */ +int +systemf(const char *fmt, ...) +{ + char buff[8192]; + va_list ap; + int r; + + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + if (verbosity > VERBOSITY_FULL) + logprintf("Cmd: %s\n", buff); + r = system(buff); + va_end(ap); + return (r); +} + +/* + * Slurp a file into memory for ease of comparison and testing. + * Returns size of file in 'sizep' if non-NULL, null-terminates + * data in memory for ease of use. + */ +char * +slurpfile(size_t * sizep, const char *fmt, ...) +{ + char filename[8192]; + struct stat st; + va_list ap; + char *p; + ssize_t bytes_read; + FILE *f; + int r; + + va_start(ap, fmt); + vsprintf(filename, fmt, ap); + va_end(ap); + + f = fopen(filename, "rb"); + if (f == NULL) { + /* Note: No error; non-existent file is okay here. */ + return (NULL); + } + r = fstat(fileno(f), &st); + if (r != 0) { + logprintf("Can't stat file %s\n", filename); + fclose(f); + return (NULL); + } + p = malloc((size_t)st.st_size + 1); + if (p == NULL) { + logprintf("Can't allocate %ld bytes of memory to read file %s\n", + (long int)st.st_size, filename); + fclose(f); + return (NULL); + } + bytes_read = fread(p, 1, (size_t)st.st_size, f); + if (bytes_read < st.st_size) { + logprintf("Can't read file %s\n", filename); + fclose(f); + free(p); + return (NULL); + } + p[st.st_size] = '\0'; + if (sizep != NULL) + *sizep = (size_t)st.st_size; + fclose(f); + return (p); +} + +/* 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); +} + +/* + * + * TEST management + * + */ + +/* + * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has + * a line like + * DEFINE_TEST(test_function) + * for each test. + */ + +/* Use "list.h" to declare all of the test functions. */ +#undef DEFINE_TEST +#define DEFINE_TEST(name) void name(void); +#include "list.h" + +/* Use "list.h" to create a list of all tests (functions and names). */ +#undef DEFINE_TEST +#define DEFINE_TEST(n) { n, #n, 0 }, +struct { void (*func)(void); const char *name; int failures; } tests[] = { + #include "list.h" +}; + +/* + * Summarize repeated failures in the just-completed test. + */ +static void +test_summarize(const char *filename, int failed) +{ + unsigned int i; + + switch (verbosity) { + case VERBOSITY_SUMMARY_ONLY: + printf(failed ? "E" : "."); + fflush(stdout); + break; + case VERBOSITY_PASSFAIL: + printf(failed ? "FAIL\n" : "ok\n"); + break; + } + + log_console = (verbosity == VERBOSITY_LIGHT_REPORT); + + for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { + if (failed_lines[i].count > 1 && !failed_lines[i].skip) + logprintf("%s:%d: Summary: Failed %d times\n", + filename, i, failed_lines[i].count); + } + /* 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: Can't chdir to top work dir %s\n", tmpdir); + exit(1); + } + /* Create a log file for this test. */ + sprintf(logfilename, "%s.log", tests[i].name); + logfile = fopen(logfilename, "w"); + fprintf(logfile, "%s\n\n", tests[i].name); + /* Chdir() to a work dir for this specific test. */ + if (!assertMakeDir(tests[i].name, 0755) + || !assertChdir(tests[i].name)) { + fprintf(stderr, + "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"); + /* Record the umask before we run the test. */ + umask(oldumask = umask(0)); + /* + * Run the actual test. + */ + (*tests[i].func)(); + /* + * 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__) + systemf("rmdir /S /Q %s", tests[i].name); + systemf("del %s", logfilename); +#else + systemf("rm -rf %s", tests[i].name); + systemf("rm %s", logfilename); +#endif + } + } + /* Return appropriate status. */ + return (tests[i].failures); +} + +/* + * + * + * MAIN and support routines. + * + * + */ + +static void +usage(const char *program) +{ + static const int limit = sizeof(tests) / sizeof(tests[0]); + int i; + + printf("Usage: %s [options] <test> <test> ...\n", program); + printf("Default is to run all tests.\n"); + printf("Otherwise, specify the numbers of the tests you wish to run.\n"); + printf("Options:\n"); + printf(" -d Dump core after any failure, for debugging.\n"); + printf(" -k Keep all temp files.\n"); + printf(" Default: temp files for successful tests deleted.\n"); +#ifdef PROGRAM + printf(" -p <path> Path to executable to be tested.\n"); + printf(" Default: path taken from " ENVBASE " environment variable.\n"); +#endif + printf(" -q Quiet.\n"); + printf(" -r <dir> Path to dir containing reference files.\n"); + printf(" Default: Current directory.\n"); + printf(" -v Verbose.\n"); + printf("Available tests:\n"); + for (i = 0; i < limit; i++) + printf(" %d: %s\n", i, tests[i].name); + exit(1); +} + +static char * +get_refdir(const char *d) +{ + 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; + } + + /* 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); + } + +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); + +success: + free(p); + free(pwd); + return strdup(buff); +} + +int +main(int argc, char **argv) +{ + static const int limit = sizeof(tests) / sizeof(tests[0]); + int i, tests_run = 0, tests_failed = 0, option; + time_t now; + char *refdir_alloc = NULL; + const char *progname; + const char *tmp, *option_arg, *p; + char tmpdir[256]; + char tmpdir_timestamp[256]; + + (void)argc; /* UNUSED */ + +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__) + /* 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') { + /* Support \ or / dir separators for Windows compat. */ + if (*p == '/' || *p == '\\') + progname = p + 1; + ++p; + } + +#ifdef PROGRAM + /* Get the target program from environment, if available. */ + testprogfile = getenv(ENVBASE); +#endif + + if (getenv("TMPDIR") != NULL) + tmp = getenv("TMPDIR"); + else if (getenv("TMP") != NULL) + tmp = getenv("TMP"); + else if (getenv("TEMP") != NULL) + tmp = getenv("TEMP"); + else if (getenv("TEMPDIR") != NULL) + tmp = getenv("TEMPDIR"); + else + tmp = "/tmp"; + + /* Allow -d to be controlled through the environment. */ + if (getenv(ENVBASE "_DEBUG") != NULL) + dump_on_failure = 1; + + /* Get the directory holding test files from environment. */ + refdir = getenv(ENVBASE "_TEST_FILES"); + + /* + * Parse options, without using getopt(), which isn't available + * on all platforms. + */ + ++argv; /* Skip program name */ + while (*argv != NULL) { + if (**argv != '-') + break; + p = *argv++; + ++p; /* Skip '-' */ + while (*p != '\0') { + option = *p++; + option_arg = NULL; + /* If 'opt' takes an argument, parse that. */ + if (option == 'p' || option == 'r') { + if (*p != '\0') + option_arg = p; + else if (*argv == NULL) { + fprintf(stderr, + "Option -%c requires argument.\n", + option); + usage(progname); + } else + option_arg = *argv++; + p = ""; /* End of this option word. */ + } + + /* Now, handle the option. */ + switch (option) { + case 'd': + dump_on_failure = 1; + break; + case 'k': + keep_temp_files = 1; + break; + case 'p': +#ifdef PROGRAM + testprogfile = option_arg; +#else + usage(progname); +#endif + break; + case 'q': + verbosity--; + break; + case 'r': + refdir = option_arg; + break; + case 'v': + verbosity++; + break; + default: + usage(progname); + } + } + } + + /* + * Sanity-check that our options make sense. + */ +#ifdef PROGRAM + if (testprogfile == NULL) + 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 + + /* + * Create a temp directory for the following tests. + * Include the time the tests started as part of the name, + * to make it easier to track the results of multiple tests. + */ + now = time(NULL); + for (i = 0; ; i++) { + strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp), + "%Y-%m-%dT%H.%M.%S", + localtime(&now)); + sprintf(tmpdir, "%s/%s.%s-%03d", tmp, progname, + tmpdir_timestamp, i); + if (assertMakeDir(tmpdir,0755)) + break; + if (i >= 999) { + fprintf(stderr, + "ERROR: Unable to create temp directory %s\n", + tmpdir); + exit(1); + } + } + + /* + * If the user didn't specify a directory for locating + * reference files, try to find the reference files in + * the "usual places." + */ + refdir = refdir_alloc = get_refdir(refdir); + + /* + * Banner with basic information. + */ + printf("\n"); + printf("If tests fail or crash, details will be in:\n"); + printf(" %s\n", tmpdir); + printf("\n"); + if (verbosity > VERBOSITY_SUMMARY_ONLY) { + printf("Reference files will be read from: %s\n", refdir); +#ifdef PROGRAM + printf("Running tests on: %s\n", testprog); +#endif + printf("Exercising: "); + fflush(stdout); + printf("%s\n", EXTRA_VERSION); + } else { + printf("Running "); + fflush(stdout); + } + + /* + * Run some or all of the individual tests. + */ + if (*argv == NULL) { + /* Default: Run all tests. */ + for (i = 0; i < limit; i++) { + if (test_run(i, tmpdir)) + tests_failed++; + tests_run++; + } + } else { + while (*(argv) != NULL) { + 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 { + 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++; + } + } + + /* + * Report summary statistics. + */ + if (verbosity > VERBOSITY_SUMMARY_ONLY) { + printf("\n"); + printf("Totals:\n"); + printf(" Tests run: %8d\n", tests_run); + printf(" Tests failed: %8d\n", tests_failed); + printf(" Assertions checked:%8d\n", assertions); + printf(" Assertions failed: %8d\n", failures); + printf(" Skips reported: %8d\n", skips); + } + if (failures) { + printf("\n"); + printf("Failing tests:\n"); + for (i = 0; i < limit; ++i) { + if (tests[i].failures) + printf(" %d: %s (%d failures)\n", i, + tests[i].name, tests[i].failures); + } + printf("\n"); + printf("Details for failing tests: %s\n", tmpdir); + printf("\n"); + } else { + if (verbosity == VERBOSITY_SUMMARY_ONLY) + printf("\n"); + printf("%d tests passed, no failures\n", tests_run); + } + + free(refdir_alloc); + + /* If the final tmpdir is empty, we can remove it. */ + /* This should be the usual case when all tests succeed. */ + assertChdir(".."); + rmdir(tmpdir); + + return (tests_failed ? 1 : 0); +} diff --git a/Utilities/cmlibarchive/tar/test/test.h b/Utilities/cmlibarchive/tar/test/test.h new file mode 100644 index 0000000..814da13 --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2003-2006 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: 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. */ + +/* + * The goal of this file (and the matching test.c) is to + * simplify the very repetitive test-*.c test programs. + */ +#if defined(HAVE_CONFIG_H) +/* Most POSIX platforms use the 'configure' script to build config.h */ +#include "config.h" +#elif defined(__FreeBSD__) +/* Building as part of FreeBSD system requires a pre-built config.h. */ +#include "config_freebsd.h" +#elif defined(_WIN32) && !defined(__CYGWIN__) +/* Win32 can't run the 'configure' script. */ +#include "config_windows.h" +#else +/* Warn if the library hasn't been (automatically or manually) configured. */ +#error Oops: No config.h and no pre-built configuration in test.h. +#endif + +#include <sys/types.h> /* Windows requires this before sys/stat.h */ +#include <sys/stat.h> + +#ifdef USE_DMALLOC +#include <dmalloc.h> +#endif +#if HAVE_DIRENT_H +#include <dirent.h> +#else +#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 <time.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <wchar.h> +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif + +/* + * System-specific tweaks. We really want to minimize these + * as much as possible, since they make it harder to understand + * the mainline code. + */ + +/* Windows (including Visual Studio and MinGW but not Cygwin) */ +#if defined(_WIN32) && !defined(__CYGWIN__) +#include "../bsdtar_windows.h" +#define strdup _strdup +#define LOCALE_DE "deu" +#else +#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 + +/* FreeBSD */ +#ifdef __FreeBSD__ +#include <sys/cdefs.h> /* For __FBSDID */ +#else +/* Surprisingly, some non-FreeBSD platforms define __FBSDID. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif +#endif + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +/* + * Redefine DEFINE_TEST for use in defining the test functions. + */ +#undef DEFINE_TEST +#define DEFINE_TEST(name) void name(void); void name(void) + +/* An implementation of the standard assert() macro */ +#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL) +/* chdir() and error if it fails */ +#define assertChdir(path) \ + assertion_chdir(__FILE__, __LINE__, path) +/* Assert two integers are the same. Reports value of each one if not. */ +#define assertEqualInt(v1,v2) \ + assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) +/* Assert two strings are the same. Reports value of each one if not. */ +#define assertEqualString(v1,v2) \ + assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) +/* As above, but v1 and v2 are wchar_t * */ +#define assertEqualWString(v1,v2) \ + assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) +/* As above, but raw blocks of bytes. */ +#define assertEqualMem(v1, v2, l) \ + assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL) +/* Assert two files are the same; allow printf-style expansion of second name. + * See below for comments about variable arguments here... + */ +#define assertEqualFile \ + assertion_setup(__FILE__, __LINE__);assertion_equal_file +/* Assert that a file is empty; supports printf-style arguments. */ +#define assertEmptyFile \ + 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 \ + assertion_setup(__FILE__, __LINE__);assertion_file_exists +/* Assert that a file exists; supports printf-style arguments. */ +#define assertFileNotExists \ + assertion_setup(__FILE__, __LINE__);assertion_file_not_exists +/* Assert that file contents match a string; supports printf-style arguments. */ +#define assertFileContents \ + 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 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 + * require that. Instead, I insert a function call before each + * skipping() call to pass the file and line information down. Crude, + * but effective. + */ +#define skipping \ + assertion_setup(__FILE__, __LINE__);test_skipping + +/* Function declarations. These are defined in test_utility.c. */ +void failure(const char *fmt, ...); +int assertion_assert(const char *, int, int, const char *, void *); +int assertion_chdir(const char *, int, const char *); +int assertion_empty_file(const char *, ...); +int 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_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, ...); + +/* 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, ...); + +/* Extracts named reference file to the current directory. */ +void extract_reference_file(const char *); + +/* + * Special interfaces for program test harness. + */ + +/* Pathname of exe to be tested. */ +const char *testprogfile; +/* Name of exe to use in printf-formatted command strings. */ +/* On Windows, this includes leading/trailing quotes. */ +const char *testprog; diff --git a/Utilities/cmlibarchive/tar/test/test_0.c b/Utilities/cmlibarchive/tar/test/test_0.c new file mode 100644 index 0000000..34a225a --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_0.c @@ -0,0 +1,67 @@ +/*- + * 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_0.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +/* + * 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(testprogfile, &st))) + exit(1); + + failure("%s is not executable?!", testprog); + if (!assert((st.st_mode & 0111) != 0)) + exit(1); + + /* + * Try to succesfully run the program; this requires that + * we know some option that will succeed. + */ + if (0 == systemf("%s --version >" DEV_NULL, testprog)) { + /* This worked. */ + } else if (0 == systemf("%s -W version >" DEV_NULL, testprog)) { + /* This worked. */ + } else { + failure("Unable to successfully run any of the following:\n" + " * %s --version\n" + " * %s -W version\n", + testprog, testprog); + assert(0); + } + + /* TODO: Ensure that our reference files are available. */ +} diff --git a/Utilities/cmlibarchive/tar/test/test_basic.c b/Utilities/cmlibarchive/tar/test/test_basic.c new file mode 100644 index 0000000..ac392d6 --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_basic.c @@ -0,0 +1,115 @@ +/*- + * 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_basic.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + + +static void +basic_tar(const char *target, const char *pack_options, + const char *unpack_options, const char *flist) +{ + int r; + + assertMakeDir(target, 0775); + + /* Use the tar program to create an archive. */ + 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); + + assertChdir(target); + + /* Verify that nothing went to stderr. */ + assertEmptyFile("pack.err"); + + /* + * Use tar to unpack the archive into another directory. + */ + r = systemf("%s xf archive %s >unpack.out 2>unpack.err", testprog, unpack_options); + failure("Error invoking %s xf archive %s", testprog, unpack_options); + assertEqualInt(r, 0); + + /* Verify that nothing went to stderr. */ + assertEmptyFile("unpack.err"); + + /* + * Verify unpacked files. + */ + + /* Regular file with 2 links. */ + assertIsReg("file", -1); + assertFileSize("file", 10); + failure("%s", target); + assertFileNLinks("file", 2); + + /* Another name for the same file. */ + assertIsReg("linkfile", -1); + assertFileSize("linkfile", 10); + assertFileNLinks("linkfile", 2); + assertIsHardlink("file", "linkfile"); + + /* Symlink */ + if (canSymlink()) + assertIsSymlink("symlink", "file"); + + /* dir */ + assertIsDir("dir", 0775); + assertChdir(".."); +} + +DEFINE_TEST(test_basic) +{ + FILE *f; + const char *flist; + + assertUmask(0); + + /* File with 10 bytes content. */ + f = fopen("file", "wb"); + assert(f != NULL); + assertEqualInt(10, fwrite("123456789", 1, 10, f)); + fclose(f); + + /* hardlink to above file. */ + assertMakeHardlink("linkfile", "file"); + assertIsHardlink("file", "linkfile"); + + /* Symlink to above file. */ + if (canSymlink()) + assertMakeSymlink("symlink", "file"); + + /* Directory. */ + 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", "", "", flist); + /* tar doesn't handle cpio symlinks correctly */ + /* basic_tar("copy_odc", "--format=odc", ""); */ + basic_tar("copy_ustar", "--format=ustar", "", flist); +} diff --git a/Utilities/cmlibarchive/tar/test/test_copy.c b/Utilities/cmlibarchive/tar/test/test_copy.c new file mode 100644 index 0000000..b5e4a0b --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_copy.c @@ -0,0 +1,373 @@ +/*- + * 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_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) +{ + char buff[260]; + char buff2[260]; + int i; + int LOOP_MAX; + + compute_filenames(); + + /* Log that we'll be omitting some checks. */ + if (!canSymlink()) { + skipping("Symlink checks"); + } + + assertMakeDir("original", 0775); + 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. */ + sprintf(buff2, "l/%s", filenames[i]); + assertMakeHardlink(buff2, buff); + + /* Create a link named "m/abcdef..." to the above. */ + 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'; + failure("buff=\"%s\"", buff); + assertMakeDir(buff, 0775); + } + + chdir(".."); +} + +#define LIMIT_NONE 200 +#define LIMIT_USTAR 100 + +static void +verify_tree(size_t limit) +{ + char name1[260]; + char name2[260]; + size_t i, LOOP_MAX; + + 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..." */ + sprintf(name1, "f/%s", filenames[i]); + if (i <= limit) { + assertFileExists(name1); + assertFileContents(name1, strlen(name1), name1); + } + + sprintf(name2, "l/%s", filenames[i]); + if (i + 2 <= limit) { + /* Verify hardlink "l/abcdef..." */ + assertIsHardlink(name1, name2); + /* Verify hardlink "m/abcdef..." */ + name2[0] = 'm'; + assertIsHardlink(name1, name2); + } + + 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...". */ + 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. + */ + } + } + } + +#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) < limit); + assertEqualString(p, + filenames[strlen(p)]); + break; + case 'f': case 's': + failure("strlen(p)=%d", strlen(p)); + assert(strlen(p) < limit + 1); + assertEqualString(p, + filenames[strlen(p)]); + break; + default: + failure("File %s shouldn't be here", p); + assert(0); + } + } + closedir(d); + } + } +#endif +} + +static void +copy_basic(void) +{ + int r; + + /* 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")); + + /* + * Use the tar program to create an archive. + */ + r = systemf("%s cf archive -C ../original f d l m s >pack.out 2>pack.err", + testprog); + failure("Error invoking \"%s cf\"", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("pack.err"); + assertEmptyFile("pack.out"); + + /* + * Use tar to unpack the archive into another directory. + */ + r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog); + failure("Error invoking %s xf archive", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("unpack.err"); + assertEmptyFile("unpack.out"); + + verify_tree(LIMIT_NONE); + assertEqualInt(0, chdir("..")); +} + +static void +copy_ustar(void) +{ + const char *target = "ustar"; + int r; + + /* 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)); + + /* + * Use the tar program to create an archive. + */ + r = systemf("%s cf archive --format=ustar -C ../original f d l m s >pack.out 2>pack.err", + testprog); + failure("Error invoking \"%s cf archive --format=ustar\"", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout. */ + assertEmptyFile("pack.out"); + /* Stderr is non-empty, since there are a bunch of files + * with filenames too long to archive. */ + + /* + * Use tar to unpack the archive into another directory. + */ + r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog); + failure("Error invoking %s xf archive", testprog); + assertEqualInt(r, 0); + + /* Verify that nothing went to stdout or stderr. */ + assertEmptyFile("unpack.err"); + assertEmptyFile("unpack.out"); + + chdir("original"); + verify_tree(LIMIT_USTAR); + chdir("../.."); +} + +DEFINE_TEST(test_copy) +{ + assertUmask(0); + create_tree(); /* Create sample files in "original" dir. */ + + /* Test simple "tar -c | tar -x" pipeline copy. */ + copy_basic(); + + /* Same, but constrain to ustar format. */ + copy_ustar(); +} diff --git a/Utilities/cmlibarchive/tar/test/test_getdate.c b/Utilities/cmlibarchive/tar/test/test_getdate.c new file mode 100644 index 0000000..bd5afd0 --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_getdate.c @@ -0,0 +1,80 @@ +/*- + * 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_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(time_t, const char *); + +DEFINE_TEST(test_getdate) +{ + 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/Utilities/cmlibarchive/tar/test/test_help.c b/Utilities/cmlibarchive/tar/test/test_help.c new file mode 100644 index 0000000..6dcff44 --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_help.c @@ -0,0 +1,81 @@ +/*- + * 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_help.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +/* + * Test that "--help", "-h", and "-W help" options all work and + * generate reasonable output. + */ + +static int +in_first_line(const char *p, const char *substring) +{ + size_t l = strlen(substring); + + while (*p != '\0' && *p != '\n') { + if (memcmp(p, substring, l) == 0) + return (1); + ++p; + } + return (0); +} + +DEFINE_TEST(test_help) +{ + int r; + char *p; + size_t plen; + + /* Exercise --help option. */ + r = systemf("%s --help >help.stdout 2>help.stderr", testprog); + failure("--help should generate nothing to stderr."); + assertEmptyFile("help.stderr"); + /* Help message should start with name of program. */ + p = slurpfile(&plen, "help.stdout"); + failure("Help output should be long enough."); + assert(plen >= 6); + failure("First line of help output should contain 'bsdtar': %s", p); + assert(in_first_line(p, "bsdtar")); + /* + * TODO: Extend this check to further verify that --help output + * looks approximately right. + */ + free(p); + + /* -h option should generate the same output. */ + r = systemf("%s -h >h.stdout 2>h.stderr", testprog); + failure("-h should generate nothing to stderr."); + assertEmptyFile("h.stderr"); + failure("stdout should be same for -h and --help"); + assertEqualFile("h.stdout", "help.stdout"); + + /* -W help should be another synonym. */ + r = systemf("%s -W help >Whelp.stdout 2>Whelp.stderr", testprog); + failure("-W help should generate nothing to stderr."); + assertEmptyFile("Whelp.stderr"); + failure("stdout should be same for -W help and --help"); + assertEqualFile("Whelp.stdout", "help.stdout"); +} diff --git a/Utilities/cmlibarchive/tar/test/test_option_T_upper.c b/Utilities/cmlibarchive/tar/test/test_option_T_upper.c new file mode 100644 index 0000000..97f895d --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_option_q.c b/Utilities/cmlibarchive/tar/test/test_option_q.c new file mode 100644 index 0000000..0b99442 --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_option_r.c b/Utilities/cmlibarchive/tar/test/test_option_r.c new file mode 100644 index 0000000..b6d310a --- /dev/null +++ b/Utilities/cmlibarchive/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 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 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/Utilities/cmlibarchive/tar/test/test_option_s.c b/Utilities/cmlibarchive/tar/test/test_option_s.c new file mode 100644 index 0000000..3bddbcf --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_patterns.c b/Utilities/cmlibarchive/tar/test/test_patterns.c new file mode 100644 index 0000000..fb84f7a --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_patterns.c @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__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) +{ + 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 *p; + + /* + * 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 + */ + 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 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); +#if !defined(_WIN32) || defined(__CYGWIN__) + p = "/tmp/foo/bar/\n/tmp/foo/bar/baz\n"; +#else + p = "/tmp/foo/bar/\r\n/tmp/foo/bar/baz\r\n"; +#endif + assertFileContents(p, strlen(p), "tar2a.out"); + 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/Utilities/cmlibarchive/tar/test/test_patterns_2.tar.uu b/Utilities/cmlibarchive/tar/test/test_patterns_2.tar.uu new file mode 100644 index 0000000..eba2dae --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_patterns_3.tar.uu b/Utilities/cmlibarchive/tar/test/test_patterns_3.tar.uu new file mode 100644 index 0000000..de60b8d --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_patterns_4.tar.uu b/Utilities/cmlibarchive/tar/test/test_patterns_4.tar.uu new file mode 100644 index 0000000..240af20 --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_stdio.c b/Utilities/cmlibarchive/tar/test/test_stdio.c new file mode 100644 index 0000000..fb4b11c --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_stdio.c @@ -0,0 +1,128 @@ +/*- + * 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_stdio.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +DEFINE_TEST(test_stdio) +{ + FILE *f; + FILE *filelist; + char *p; + size_t s; + int r; + + assertUmask(0); + + /* + * Create a couple of files on disk. + */ + filelist = fopen("filelist", "w"); + assert(filelist != NULL); + /* File */ + f = fopen("f", "w"); + assert(f != NULL); + fprintf(f, "f\n"); + fclose(f); + fprintf(filelist, "f\n"); + /* Link to above file. */ + assertMakeHardlink("l", "f"); + fprintf(filelist, "l\n"); + fclose(filelist); + + /* + * Archive/dearchive with a variety of options, verifying + * stdio paths. + */ + + /* 'cf' should generate no output unless there's an error. */ + r = systemf("%s cf archive f l >cf.out 2>cf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("cf.out"); + assertEmptyFile("cf.err"); + + /* 'cvf' should generate file list on stderr, empty stdout. */ + r = systemf("%s cvf archive f l >cvf.out 2>cvf.err", testprog); + assertEqualInt(r, 0); + failure("'cv' writes filenames to stderr, nothing to stdout (SUSv2)\n" + "Note that GNU tar writes the file list to stdout by default."); + assertEmptyFile("cvf.out"); + /* TODO: Verify cvf.err has file list in SUSv2-prescribed format. */ + + /* 'cvf -' should generate file list on stderr, archive on stdout. */ + r = systemf("%s cvf - f l >cvf-.out 2>cvf-.err", testprog); + assertEqualInt(r, 0); + failure("cvf - should write archive to stdout"); + /* TODO: Verify cvf-.out has archive. */ + failure("cvf - should write file list to stderr (SUSv2)"); + /* TODO: Verify cvf-.err has verbose file list. */ + + /* 'tf' should generate file list on stdout, empty stderr. */ + r = systemf("%s tf archive >tf.out 2>tf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("tf.err"); + failure("'t' mode should write results to stdout"); + /* TODO: Verify tf.out has file list. */ + + /* 'tvf' should generate file list on stdout, empty stderr. */ + r = systemf("%s tvf archive >tvf.out 2>tvf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("tvf.err"); + failure("'tv' mode should write results to stdout"); + /* TODO: Verify tvf.out has file list. */ + + /* 'tvf -' uses stdin, file list on stdout, empty stderr. */ + r = systemf("%s tvf - < archive >tvf-.out 2>tvf-.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("tvf-.err"); + /* TODO: Verify tvf-.out has file list. */ + + /* Basic 'xf' should generate no output on stdout or stderr. */ + r = systemf("%s xf archive >xf.out 2>xf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("xf.err"); + assertEmptyFile("xf.out"); + + /* 'xvf' should generate list on stderr, empty stdout. */ + r = systemf("%s xvf archive >xvf.out 2>xvf.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("xvf.out"); + /* TODO: Verify xvf.err */ + + /* 'xvOf' should generate list on stderr, file contents on stdout. */ + r = systemf("%s xvOf archive >xvOf.out 2>xvOf.err", testprog); + assertEqualInt(r, 0); + /* Verify xvOf.out is the file contents */ + p = slurpfile(&s, "xvOf.out"); + assert(p != NULL); + assert(s = 2); + assertEqualMem(p, "f\n", 2); + /* TODO: Verify xvf.err */ + + /* 'xvf -' should generate list on stderr, empty stdout. */ + r = systemf("%s xvf - < archive >xvf-.out 2>xvf-.err", testprog); + assertEqualInt(r, 0); + assertEmptyFile("xvf-.out"); + /* TODO: Verify xvf-.err */ +} diff --git a/Utilities/cmlibarchive/tar/test/test_strip_components.c b/Utilities/cmlibarchive/tar/test/test_strip_components.c new file mode 100644 index 0000000..6d258e4 --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_symlink_dir.c b/Utilities/cmlibarchive/tar/test/test_symlink_dir.c new file mode 100644 index 0000000..04e0a4b --- /dev/null +++ b/Utilities/cmlibarchive/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/Utilities/cmlibarchive/tar/test/test_version.c b/Utilities/cmlibarchive/tar/test/test_version.c new file mode 100644 index 0000000..518dd41 --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_version.c @@ -0,0 +1,97 @@ +/*- + * 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_version.c,v 1.2 2008/05/26 17:10:10 kientzle Exp $"); + +/* + * Test that --version option works and generates reasonable output. + */ + +DEFINE_TEST(test_version) +{ + int r; + char *p, *q; + size_t s; + + + r = systemf("%s --version >version.stdout 2>version.stderr", testprog); + if (r != 0) + r = systemf("%s -W version >version.stdout 2>version.stderr", + testprog); + failure("Unable to run either %s --version or %s -W version", + testprog, testprog); + if (!assert(r == 0)) + return; + + /* --version should generate nothing to stdout. */ + assertEmptyFile("version.stderr"); + /* Verify format of version message. */ + q = p = slurpfile(&s, "version.stdout"); + /* Version message should start with name of program, then space. */ + assert(s > 6); + failure("Version must start with 'bsdtar': ``%s''", p); + if (!assertEqualMem(q, "bsdtar ", 7)) + return; + q += 7; s -= 7; + /* Version number is a series of digits and periods. */ + while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) { + ++q; + --s; + } + /* Version number terminated by space. */ + failure("No space after bsdtar version: ``%s''", p); + assert(s > 1); + /* Skip a single trailing a,b,c, or d. */ + if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd') + ++q; + failure("No space after bsdtar version: ``%s''", p); + assert(*q == ' '); + ++q; --s; + /* Separator. */ + failure("No `-' between bsdtar and libarchive versions: ``%s''", p); + assertEqualMem(q, "- ", 2); + q += 2; s -= 2; + /* libarchive name and version number */ + failure("Not long enough for libarchive version: ``%s''", p); + assert(s > 11); + failure("Libarchive version must start with `libarchive': ``%s''", p); + assertEqualMem(q, "libarchive ", 11); + q += 11; s -= 11; + /* Version number is a series of digits and periods. */ + while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) { + ++q; + --s; + } + /* Skip a single trailing a,b,c, or d. */ + if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd') + ++q; + /* 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/Utilities/cmlibarchive/tar/test/test_windows.c b/Utilities/cmlibarchive/tar/test/test_windows.c new file mode 100644 index 0000000..b0eefff --- /dev/null +++ b/Utilities/cmlibarchive/tar/test/test_windows.c @@ -0,0 +1,324 @@ +/*- + * 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++ = *p1; + *p2++ = *p1++; + } + *p2++ = '\r'; + *p2++ = '\n'; + *p2 = '\0'; + + *path1 = fp1; + *path2 = fp2; +} + +static const char list1[] = + "aaa/\r\naaa/file1\r\naaa/xxa/\r\naaa/xxb/\r\naaa/zzc/\r\n" + "aaa/zzc/file1\r\naaa/xxb/file1\r\naaa/xxa/file1\r\naab/\r\n" + "aac/\r\nabb/\r\nabc/\r\nabd/\r\n"; +static const char list2[] = + "bbb/\r\nbbb/file1\r\nbbb/xxa/\r\nbbb/xxb/\r\nbbb/zzc/\r\n" + "bbb/zzc/file1\r\nbbb/xxb/file1\r\nbbb/xxa/file1\r\nbbc/\r\n" + "bbd/\r\nbcc/\r\nbcd/\r\nbce/\r\n"; +static const char list3[] = + "aac/\r\nabc/\r\nbbc/\r\nbcc/\r\nccc/\r\n"; +static const char list4[] = + "fff/abca\r\nfff/acca\r\n"; +static const char list5[] = + "aaa/file1\r\naaa/xxa/\r\naaa/xxa/file1\r\naaa/xxb/\r\n" + "aaa/xxb/file1\r\naaa/zzc/\r\naaa/zzc/file1\r\n"; +static const char list6[] = + "fff/abca\r\nfff/acca\r\naaa/xxa/\r\naaa/xxa/file1\r\n" + "aaa/xxb/\r\naaa/xxb/file1\r\n"; +#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)); + assertFileContents(list1, strlen(list1), "../list1"); + + assertEqualInt(0, + systemf("%s -cf ../archive2.tar b*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive2.tar > ../list2", testprog)); + assertFileContents(list2, strlen(list2), "../list2"); + + assertEqualInt(0, + systemf("%s -cf ../archive3.tar ??c", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive3.tar > ../list3", testprog)); + assertFileContents(list3, strlen(list3), "../list3"); + + assertEqualInt(0, + systemf("%s -cf ../archive3b.tar *c", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive3b.tar > ../list3b", testprog)); + assertFileContents(list3, strlen(list3), "../list3b"); + + assertEqualInt(0, + systemf("%s -cf ../archive4.tar fff/a?ca", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive4.tar > ../list4", testprog)); + assertFileContents(list4, strlen(list4), "../list4"); + + assertEqualInt(0, + systemf("%s -cf ../archive5.tar aaa\\*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive5.tar > ../list5", testprog)); + assertFileContents(list5, strlen(list5), "../list5"); + + assertEqualInt(0, + systemf("%s -cf ../archive6.tar fff\\a?ca aaa\\xx*", testprog)); + assertEqualInt(0, + systemf("%s -tf ../archive6.tar > ../list6", testprog)); + assertFileContents(list6, strlen(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); + 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); + 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__ */ +} |