Index: stable/7/lib/libarchive/test/Makefile =================================================================== --- stable/7/lib/libarchive/test/Makefile (revision 179170) +++ stable/7/lib/libarchive/test/Makefile (revision 179171) @@ -1,132 +1,118 @@ # $FreeBSD$ # Where to find the libarchive sources LA_SRCDIR=${.CURDIR}/.. .PATH: ${LA_SRCDIR} # Get a list of all libarchive source files LA_SRCS!=make -f ${LA_SRCDIR}/Makefile -V SRCS -TESTFILES= \ - test_compat_gtar_1.tgz \ - test_compat_tar_hardlink_1.tar \ - test_compat_zip_1.zip \ - test_read_format_gtar_sparse_1_13.tgz \ - test_read_format_gtar_sparse_1_17.tgz \ - test_read_format_gtar_sparse_1_17_posix00.tgz \ - test_read_format_gtar_sparse_1_17_posix01.tgz \ - test_read_format_gtar_sparse_1_17_posix10.tgz \ - test_read_format_gtar_sparse_1_17_posix10_modified.tar - TESTS= \ test_acl_basic.c \ test_acl_pax.c \ test_archive_api_feature.c \ test_bad_fd.c \ test_compat_gtar.c \ test_compat_tar_hardlink.c \ test_compat_zip.c \ test_empty_write.c \ test_entry.c \ test_entry_strmode.c \ + test_pax_filename_encoding.c \ test_read_compress_program.c \ test_read_data_large.c \ test_read_extract.c \ test_read_format_ar.c \ test_read_format_cpio_bin.c \ test_read_format_cpio_bin_Z.c \ test_read_format_cpio_bin_bz2.c \ test_read_format_cpio_bin_gz.c \ test_read_format_cpio_odc.c \ test_read_format_cpio_svr4_gzip.c \ test_read_format_cpio_svr4c_Z.c \ test_read_format_empty.c \ test_read_format_gtar_gz.c \ test_read_format_gtar_sparse.c \ test_read_format_iso_gz.c \ test_read_format_isorr_bz2.c \ test_read_format_mtree.c \ test_read_format_pax_bz2.c \ test_read_format_tar.c \ test_read_format_tbz.c \ test_read_format_tgz.c \ test_read_format_tz.c \ test_read_format_zip.c \ test_read_large.c \ test_read_pax_truncated.c \ test_read_position.c \ test_read_truncated.c \ test_tar_filenames.c \ test_tar_large.c \ test_write_compress_program.c \ + test_write_compress.c \ test_write_disk.c \ test_write_disk_hardlink.c \ test_write_disk_perms.c \ test_write_disk_secure.c \ test_write_format_ar.c \ test_write_format_cpio.c \ test_write_format_cpio_odc.c \ test_write_format_cpio_newc.c \ test_write_format_cpio_empty.c \ test_write_format_shar_empty.c \ test_write_format_tar.c \ test_write_format_tar_empty.c \ test_write_open_memory.c # Build the test program using all libarchive sources + the test sources. SRCS= ${LA_SRCS} \ ${TESTS} \ list.h \ main.c \ read_open_memory.c CLEANFILES+= list.h archive.h NO_MAN=yes PROG=libarchive_test INTERNALPROG=yes # Don't install this; it's just for testing DPADD=${LIBBZ2} ${LIBZ} CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\" LDADD= -lz -lbz2 CFLAGS+= -static -g CFLAGS+= -I${.OBJDIR} CFLAGS+= -I${.CURDIR} CFLAGS+= -I${LA_SRCDIR} # Without this, libarchive source files find archive.h in LA_SRCDIR, # which may not be the same as archive.h in the test dir. CFLAGS+= -I- # Uncomment to link against dmalloc LDADD+= -L/usr/local/lib -ldmalloc CFLAGS+= -I/usr/local/include -DUSE_DMALLOC WARNS=6 # Build libarchive_test and run it. -check test: libarchive_test ${TESTFILES} - ./libarchive_test +check test: libarchive_test + ./libarchive_test -k -r ${.CURDIR} -.for f in ${TESTFILES} -${f}: ${f}.uu - uudecode -p ${.CURDIR}/${f}.uu >${f} -.endfor - INCS=archive.h list.h # Build archive.h, but in our .OBJDIR, not libarchive's # This keeps libarchive_test and libarchive builds completely separate. archive.h: ${LA_SRCDIR}/archive.h.in ${LA_SRCDIR}/Makefile cd ${LA_SRCDIR} && unset MAKEOBJDIRPREFIX && MAKEOBJDIR=${.OBJDIR} make archive.h # list.h is just a list of all tests, as indicated by DEFINE_TEST macro lines list.h: ${TESTS} Makefile (cd ${.CURDIR}; cat ${TESTS}) | grep DEFINE_TEST > list.h -CLEANFILES += *.out *.o *.core *~ list.h archive.h ${TESTFILES} +CLEANFILES += *.out *.o *.core *~ list.h archive.h cleantest: -chmod -R +w /tmp/libarchive_test.* rm -rf /tmp/libarchive_test.* .include Index: stable/7/lib/libarchive/test/main.c =================================================================== --- stable/7/lib/libarchive/test/main.c (revision 179170) +++ stable/7/lib/libarchive/test/main.c (revision 179171) @@ -1,713 +1,882 @@ /* * 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. */ /* - * This same file is used pretty much verbatim for all test harnesses. - * - * The next line is used to define various environment variables, etc. - * - * The tar and cpio test harnesses are identical except for this line; - * the libarchive test harness omits some code that is needed only for - * testing standalone executables. + * Various utility routines useful for test programs. + * Each test program is linked against this file. */ -#define PROGRAM "LIBARCHIVE" - #include #include #include #include #include "test.h" + +/* + * This same file is used pretty much verbatim for all test harnesses. + * + * The next few lines are the only differences. + */ +#undef PROGRAM /* Testing a library, not a program. */ +#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */ +#define EXTRA_DUMP(x) archive_error_string((struct archive *)(x)) +#define EXTRA_VERSION archive_version() __FBSDID("$FreeBSD$"); /* * "list.h" is simply created by "grep DEFINE_TEST"; it has * a line like * DEFINE_TEST(test_function) * for each test. * Include it here with a suitable DEFINE_TEST to declare all of the * test functions. */ #undef DEFINE_TEST -#define DEFINE_TEST(name) void name(void); +#define DEFINE_TEST(name) void name(void); #include "list.h" /* Interix doesn't define these in a standard header. */ #if __INTERIX__ extern char *optarg; extern int optind; #endif /* Default is to crash and try to force a core dump on failure. */ static int dump_on_failure = 1; /* Default is to print some basic information about each test. */ static int quiet_flag = 0; /* Cumulative count of component failures. */ static int failures = 0; /* Cumulative count of skipped component tests. */ static int skips = 0; /* Cumulative count of assertions. */ static int assertions = 0; +/* Directory where uuencoded reference files can be found. */ +static char *refdir; + /* * My own implementation of the standard assert() macro emits the * message in the same format as GCC (file:line: message). * It also includes some additional useful information. * This makes it a lot easier to skim through test failures in * Emacs. ;-) * * It also supports a few special features specifically to simplify * test harnesses: * failure(fmt, args) -- Stores a text string that gets * printed if the following assertion fails, good for * explaining subtle tests. */ static char msg[4096]; /* * For each test source file, we remember how many times each * failure was reported. */ -static const char *failed_filename; +static const char *failed_filename = NULL; static struct line { int line; int count; } failed_lines[1000]; /* * Count this failure; return the number of previous failures. */ static int previous_failures(const char *filename, int line) { unsigned int i; int count; if (failed_filename == NULL || strcmp(failed_filename, filename) != 0) memset(failed_lines, 0, sizeof(failed_lines)); failed_filename = filename; for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { if (failed_lines[i].line == line) { count = failed_lines[i].count; failed_lines[i].count++; return (count); } if (failed_lines[i].line == 0) { failed_lines[i].line = line; failed_lines[i].count = 1; return (0); } } return (0); } /* * Copy arguments into file-local variables. */ static const char *test_filename; static int test_line; static void *test_extra; void test_setup(const char *filename, int line) { test_filename = filename; test_line = line; } /* * Inform user that we're skipping a test. */ void test_skipping(const char *fmt, ...) { va_list ap; if (previous_failures(test_filename, test_line)) return; va_start(ap, fmt); fprintf(stderr, " *** SKIPPING: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); ++skips; } /* Common handling of failed tests. */ static void report_failure(void *extra) { if (msg[0] != '\0') { fprintf(stderr, " Description: %s\n", msg); msg[0] = '\0'; } - if (extra != NULL) { - fprintf(stderr, " archive error: %s\n", archive_error_string((struct archive *)extra)); - } +#ifdef EXTRA_DUMP + if (extra != NULL) + fprintf(stderr, " detail: %s\n", EXTRA_DUMP(extra)); +#else + (void)extra; /* UNUSED */ +#endif + if (dump_on_failure) { fprintf(stderr, " *** forcing core dump so failure can be debugged ***\n"); *(char *)(NULL) = 0; exit(1); } } /* * Summarize repeated failures in the just-completed test file. * The reports above suppress multiple failures from the same source * line; this reports on any tests that did fail multiple times. */ static int summarize_comparator(const void *a0, const void *b0) { const struct line *a = a0, *b = b0; if (a->line == 0 && b->line == 0) return (0); if (a->line == 0) return (1); if (b->line == 0) return (-1); return (a->line - b->line); } static void summarize(void) { unsigned int i; qsort(failed_lines, sizeof(failed_lines)/sizeof(failed_lines[0]), sizeof(failed_lines[0]), summarize_comparator); for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { if (failed_lines[i].line == 0) break; if (failed_lines[i].count > 1) fprintf(stderr, "%s:%d: Failed %d times\n", failed_filename, failed_lines[i].line, failed_lines[i].count); } /* Clear the failure history for the next file. */ memset(failed_lines, 0, sizeof(failed_lines)); } /* Set up a message to display only after a test fails. */ void failure(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsprintf(msg, fmt, ap); va_end(ap); } /* Generic assert() just displays the failed condition. */ int test_assert(const char *file, int line, int value, const char *condition, void *extra) { ++assertions; if (value) { msg[0] = '\0'; return (value); } failures ++; if (previous_failures(file, line)) return (value); fprintf(stderr, "%s:%d: Assertion failed\n", file, line); fprintf(stderr, " Condition: %s\n", condition); report_failure(extra); return (value); } /* assertEqualInt() displays the values of the two integers. */ -void +int test_assert_equal_int(const char *file, int line, int v1, const char *e1, int v2, const char *e2, void *extra) { ++assertions; if (v1 == v2) { msg[0] = '\0'; - return; + return (1); } failures ++; if (previous_failures(file, line)) - return; + return (0); fprintf(stderr, "%s:%d: Assertion failed: Ints not equal\n", file, line); fprintf(stderr, " %s=%d\n", e1, v1); fprintf(stderr, " %s=%d\n", e2, v2); report_failure(extra); + return (0); } /* assertEqualString() displays the values of the two strings. */ -void +int test_assert_equal_string(const char *file, int line, const char *v1, const char *e1, const char *v2, const char *e2, void *extra) { ++assertions; if (v1 == NULL || v2 == NULL) { if (v1 == v2) { msg[0] = '\0'; - return; + return (1); } } else if (strcmp(v1, v2) == 0) { msg[0] = '\0'; - return; + return (1); } failures ++; if (previous_failures(file, line)) - return; + return (0); fprintf(stderr, "%s:%d: Assertion failed: Strings not equal\n", file, line); fprintf(stderr, " %s = \"%s\"\n", e1, v1); fprintf(stderr, " %s = \"%s\"\n", e2, v2); report_failure(extra); + return (0); } /* assertEqualWString() displays the values of the two strings. */ -void +int test_assert_equal_wstring(const char *file, int line, const wchar_t *v1, const char *e1, const wchar_t *v2, const char *e2, void *extra) { ++assertions; if (wcscmp(v1, v2) == 0) { msg[0] = '\0'; - return; + return (1); } failures ++; if (previous_failures(file, line)) - return; + return (0); fprintf(stderr, "%s:%d: Assertion failed: Unicode strings not equal\n", file, line); fwprintf(stderr, L" %s = \"%ls\"\n", e1, v1); fwprintf(stderr, L" %s = \"%ls\"\n", e2, v2); report_failure(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) { fprintf(stderr, "%04x", i + offset); sep = ' '; for (j = 0; j < 16 && i + j < l; j++) { if (ref != NULL && p[i + j] != ref[i + j]) sep = '_'; - fprintf(stderr, "%c%02x", sep, p[i+j]); + fprintf(stderr, "%c%02x", sep, 0xff & (int)p[i+j]); if (ref != NULL && p[i + j] == ref[i + j]) sep = ' '; } for (; j < 16; j++) { fprintf(stderr, "%c ", sep); sep = ' '; } fprintf(stderr, "%c", sep); for (j=0; j < 16 && i + j < l; j++) { int c = p[i + j]; if (c >= ' ' && c <= 126) fprintf(stderr, "%c", c); else fprintf(stderr, "."); } fprintf(stderr, "\n"); } } /* assertEqualMem() displays the values of the two memory blocks. */ /* TODO: For long blocks, hexdump the first bytes that actually differ. */ -void +int test_assert_equal_mem(const char *file, int line, const char *v1, const char *e1, const char *v2, const char *e2, size_t l, const char *ld, void *extra) { ++assertions; if (v1 == NULL || v2 == NULL) { if (v1 == v2) { msg[0] = '\0'; - return; + return (1); } } else if (memcmp(v1, v2, l) == 0) { msg[0] = '\0'; - return; + return (1); } failures ++; if (previous_failures(file, line)) - return; + return (0); fprintf(stderr, "%s:%d: Assertion failed: memory not equal\n", file, line); fprintf(stderr, " size %s = %d\n", ld, (int)l); fprintf(stderr, " Dump of %s\n", e1); hexdump(v1, v2, l < 32 ? l : 32, 0); fprintf(stderr, " Dump of %s\n", e2); hexdump(v2, v1, l < 32 ? l : 32, 0); fprintf(stderr, "\n"); report_failure(extra); + return (0); } -void +int test_assert_empty_file(const char *f1fmt, ...) { + char buff[1024]; char f1[1024]; struct stat st; va_list ap; + ssize_t s; + int fd; + va_start(ap, f1fmt); vsprintf(f1, f1fmt, ap); va_end(ap); if (stat(f1, &st) != 0) { fprintf(stderr, "%s:%d: Could not stat: %s\n", test_filename, test_line, f1); report_failure(NULL); - } else if (st.st_size > 0) { - fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1); - fprintf(stderr, " File size: %d\n", (int)st.st_size); - report_failure(NULL); } + if (st.st_size == 0) + return (1); + + failures ++; + if (previous_failures(test_filename, test_line)) + return (0); + + fprintf(stderr, "%s:%d: File not empty: %s\n", test_filename, test_line, f1); + fprintf(stderr, " File size: %d\n", (int)st.st_size); + fprintf(stderr, " Contents:\n"); + fd = open(f1, O_RDONLY); + if (fd < 0) { + fprintf(stderr, " Unable to open %s\n", f1); + } else { + s = sizeof(buff) < st.st_size ? sizeof(buff) : st.st_size; + s = read(fd, buff, s); + hexdump(buff, NULL, s, 0); + } + report_failure(NULL); + return (0); } /* assertEqualFile() asserts that two files have the same contents. */ /* TODO: hexdump the first bytes that actually differ. */ -void +int test_assert_equal_file(const char *f1, const char *f2pattern, ...) { char f2[1024]; va_list ap; char buff1[1024]; char buff2[1024]; int fd1, fd2; int n1, n2; va_start(ap, f2pattern); vsprintf(f2, f2pattern, ap); va_end(ap); fd1 = open(f1, O_RDONLY); fd2 = open(f2, O_RDONLY); for (;;) { n1 = read(fd1, buff1, sizeof(buff1)); n2 = read(fd2, buff2, sizeof(buff2)); if (n1 != n2) break; if (n1 == 0 && n2 == 0) - return; + return (1); if (memcmp(buff1, buff2, n1) != 0) break; } - fprintf(stderr, "%s:%d: Files are not identical\n", test_filename, test_line); + failures ++; + if (previous_failures(test_filename, test_line)) + return (0); + fprintf(stderr, "%s:%d: Files are not identical\n", + test_filename, test_line); fprintf(stderr, " file1=\"%s\"\n", f1); fprintf(stderr, " file2=\"%s\"\n", f2); report_failure(test_extra); + return (0); } +/* assertFileContents() asserts the contents of a file. */ +int +test_assert_file_contents(const void *buff, int s, const char *fpattern, ...) +{ + char f[1024]; + va_list ap; + char *contents; + int fd; + int n; + va_start(ap, fpattern); + vsprintf(f, fpattern, ap); + va_end(ap); + + fd = open(f, O_RDONLY); + contents = malloc(s * 2); + n = read(fd, contents, s * 2); + if (n == s && memcmp(buff, contents, s) == 0) { + free(contents); + return (1); + } + failures ++; + if (!previous_failures(test_filename, test_line)) { + fprintf(stderr, "%s:%d: File contents don't match\n", + test_filename, test_line); + fprintf(stderr, " file=\"%s\"\n", f); + if (n > 0) + hexdump(contents, buff, n, 0); + else { + fprintf(stderr, " File empty, contents should be:\n"); + hexdump(buff, NULL, s, 0); + } + report_failure(test_extra); + } + free(contents); + return (0); +} + /* * 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); 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; int fd; int r; va_start(ap, fmt); vsprintf(filename, fmt, ap); va_end(ap); fd = open(filename, O_RDONLY); if (fd < 0) { /* Note: No error; non-existent file is okay here. */ return (NULL); } r = fstat(fd, &st); if (r != 0) { fprintf(stderr, "Can't stat file %s\n", filename); close(fd); return (NULL); } p = malloc(st.st_size + 1); if (p == NULL) { fprintf(stderr, "Can't allocate %ld bytes of memory to read file %s\n", (long int)st.st_size, filename); close(fd); return (NULL); } bytes_read = read(fd, p, st.st_size); if (bytes_read < st.st_size) { fprintf(stderr, "Can't read file %s\n", filename); close(fd); free(p); return (NULL); } p[st.st_size] = '\0'; if (sizep != NULL) *sizep = (size_t)st.st_size; close(fd); return (p); } /* * "list.h" is automatically generated; it just has a lot of lines like: * DEFINE_TEST(function_name) * It's used above to declare all of the test functions. * We reuse it here to define a list of all tests (functions and names). */ #undef DEFINE_TEST -#define DEFINE_TEST(n) { n, #n }, +#define DEFINE_TEST(n) { n, #n }, struct { void (*func)(void); const char *name; } tests[] = { #include "list.h" }; /* * Each test is run in a private work dir. Those work dirs * do have consistent and predictable names, in case a group * of tests need to collaborate. However, there is no provision * for requiring that tests run in a certain order. */ static int test_run(int i, const char *tmpdir) { int failures_before = failures; if (!quiet_flag) printf("%d: %s\n", i, tests[i].name); /* * Always explicitly chdir() in case the last test moved us to * a strange place. */ if (chdir(tmpdir)) { fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n", tmpdir); exit(1); } /* Create a temp directory for this specific test. */ if (mkdir(tests[i].name, 0755)) { fprintf(stderr, "ERROR: Couldn't create temp dir ``%s''\n", tests[i].name); exit(1); } /* Chdir() to that work directory. */ if (chdir(tests[i].name)) { fprintf(stderr, "ERROR: Couldn't chdir to temp dir ``%s''\n", tests[i].name); exit(1); } /* Explicitly reset the locale before each test. */ setlocale(LC_ALL, "C"); /* Run the actual test. */ (*tests[i].func)(); /* Summarize the results of this test. */ summarize(); /* Return appropriate status. */ return (failures == failures_before ? 0 : 1); } static void usage(const char *program) { static const int limit = sizeof(tests) / sizeof(tests[0]); int i; printf("Usage: %s [options] ...\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(" -k Keep running after failures.\n"); printf(" Default: Core dump after any failure.\n"); +#ifdef PROGRAM + printf(" -p Path to executable to be tested.\n"); + printf(" Default: path taken from " ENVBASE " environment variable.\n"); +#endif printf(" -q Quiet.\n"); printf(" -r Path to dir containing reference files.\n"); printf(" Default: Current directory.\n"); printf("Available tests:\n"); for (i = 0; i < limit; i++) printf(" %d: %s\n", i, tests[i].name); exit(1); } +#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, "w"); + 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); +} + + int main(int argc, char **argv) { static const int limit = sizeof(tests) / sizeof(tests[0]); int i, tests_run = 0, tests_failed = 0, opt; time_t now; char *refdir_alloc = NULL; char *progname, *p; char tmpdir[256]; char tmpdir_timestamp[256]; /* * Name of this program, used to build root of our temp directory * tree. */ progname = p = argv[0]; while (*p != '\0') { if (*p == '/') progname = p + 1; ++p; } +#ifdef PROGRAM + /* Get the target program from environment, if available. */ + testprog = getenv(ENVBASE); +#endif + + /* Allow -k to be controlled through the environment. */ + if (getenv(ENVBASE "_KEEP_GOING") != NULL) + dump_on_failure = 0; + /* Get the directory holding test files from environment. */ - refdir = getenv(PROGRAM "_TEST_FILES"); + refdir = getenv(ENVBASE "_TEST_FILES"); /* * Parse options. */ - while ((opt = getopt(argc, argv, "kqr:")) != -1) { + while ((opt = getopt(argc, argv, "kp:qr:")) != -1) { switch (opt) { case 'k': dump_on_failure = 0; break; + case 'p': +#ifdef PROGRAM + testprog = optarg; +#else + usage(progname); +#endif + break; case 'q': quiet_flag++; break; case 'r': refdir = optarg; break; case '?': default: usage(progname); } } argc -= optind; argv += optind; /* + * Sanity-check that our options make sense. + */ +#ifdef PROGRAM + if (testprog == NULL) + usage(progname); +#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 < 1000; i++) { strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp), "%Y-%m-%dT%H.%M.%S", localtime(&now)); sprintf(tmpdir, "/tmp/%s.%s-%03d", progname, tmpdir_timestamp, i); if (mkdir(tmpdir,0755) == 0) break; if (errno == EEXIST) continue; fprintf(stderr, "ERROR: Unable to create temp directory %s\n", tmpdir); exit(1); } /* * If the user didn't specify a directory for locating * reference files, use the current directory for that. */ if (refdir == NULL) { systemf("/bin/pwd > %s/refdir", tmpdir); refdir = refdir_alloc = slurpfile(NULL, "%s/refdir", tmpdir); p = refdir + strlen(refdir); while (p[-1] == '\n') { --p; *p = '\0'; } } /* * Banner with basic information. */ if (!quiet_flag) { printf("Running tests in: %s\n", tmpdir); printf("Reference files will be read from: %s\n", refdir); - printf("Exercising %s\n", archive_version()); +#ifdef PROGRAM + printf("Running tests on: %s\n", testprog); +#endif + printf("Exercising: "); + fflush(stdout); + printf("%s\n", EXTRA_VERSION); } /* * Run some or all of the individual tests. */ if (argc == 0) { /* Default: Run all tests. */ for (i = 0; i < limit; i++) { if (test_run(i, tmpdir)) tests_failed++; tests_run++; } } else { while (*(argv) != NULL) { i = atoi(*argv); if (**argv < '0' || **argv > '9' || i < 0 || i >= limit) { printf("*** INVALID Test %s\n", *argv); usage(progname); } else { if (test_run(i, tmpdir)) tests_failed++; tests_run++; } argv++; } } /* * Report summary statistics. */ if (!quiet_flag) { printf("\n"); printf("%d of %d tests reported failures\n", tests_failed, tests_run); printf(" Total of %d assertions checked.\n", assertions); printf(" Total of %d assertions failed.\n", failures); printf(" Total of %d assertions skipped.\n", skips); } free(refdir_alloc); return (tests_failed); } Index: stable/7/lib/libarchive/test/test.h =================================================================== --- stable/7/lib/libarchive/test/test.h (revision 179170) +++ stable/7/lib/libarchive/test/test.h (revision 179171) @@ -1,166 +1,164 @@ /* * 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$ */ /* 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. */ #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif +#include #include #include #include #include #include #include #ifndef _WIN32 #include #endif #include #ifdef USE_DMALLOC #include #endif #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) /* 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 /* No non-FreeBSD platform will have __FBSDID, so just define it here. */ #ifdef __FreeBSD__ #include /* For __FBSDID */ #else #define __FBSDID(a) /* null */ #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) test_assert(__FILE__, __LINE__, (e), #e, NULL) /* Assert two integers are the same. Reports value of each one if not. */ #define assertEqualInt(v1,v2) \ test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) /* Assert two strings are the same. Reports value of each one if not. */ #define assertEqualString(v1,v2) \ test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) /* As above, but v1 and v2 are wchar_t * */ #define assertEqualWString(v1,v2) \ test_assert_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) /* As above, but raw blocks of bytes. */ #define assertEqualMem(v1, v2, l) \ test_assert_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL) /* Assert two files are the same; allow printf-style expansion of second name. * See below for comments about variable arguments here... */ #define assertEqualFile \ test_setup(__FILE__, __LINE__);test_assert_equal_file /* Assert that a file is empty; supports printf-style arguments. */ #define assertEmptyFile \ test_setup(__FILE__, __LINE__);test_assert_empty_file /* * 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 \ test_setup(__FILE__, __LINE__);test_skipping /* Function declarations. These are defined in test_utility.c. */ void failure(const char *fmt, ...); void test_setup(const char *, int); void test_skipping(const char *fmt, ...); int test_assert(const char *, int, int, const char *, void *); -void test_assert_empty_file(const char *, ...); -void test_assert_equal_file(const char *, const char *, ...); -void test_assert_equal_int(const char *, int, int, const char *, int, const char *, void *); -void test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *); -void test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *); -void test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *); +int test_assert_empty_file(const char *, ...); +int test_assert_equal_file(const char *, const char *, ...); +int test_assert_equal_int(const char *, int, int, const char *, int, const char *, void *); +int test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *); +int test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *); +int test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *); +int test_assert_file_contents(const void *, int, const char *, ...); /* Like sprintf, then system() */ int systemf(const char * fmt, ...); /* 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, ...); -/* - * Global vars - */ - -/* Directory holding reference files. */ -char *refdir; +/* Extracts named reference file to the current directory. */ +void extract_reference_file(const char *); /* * Special interfaces for libarchive test harness. */ #include "archive.h" #include "archive_entry.h" /* Special customized read-from-memory interface. */ int read_open_memory(struct archive *, void *, size_t, size_t); /* * ARCHIVE_VERSION_STAMP first appeared in 1.9 and libarchive 2.2.4. * We can approximate it for earlier versions, though. * This is used to disable tests of features not present in the current * version. */ #ifndef ARCHIVE_VERSION_STAMP #define ARCHIVE_VERSION_STAMP \ (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000) #endif /* Versions of above that accept an archive argument for additional info. */ #define assertA(e) test_assert(__FILE__, __LINE__, (e), #e, (a)) #define assertEqualIntA(a,v1,v2) \ test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a)) #define assertEqualStringA(a,v1,v2) \ test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a)) Index: stable/7/lib/libarchive/test/test_archive_api_feature.c =================================================================== --- stable/7/lib/libarchive/test/test_archive_api_feature.c (revision 179170) +++ stable/7/lib/libarchive/test/test_archive_api_feature.c (revision 179171) @@ -1,51 +1,65 @@ /*- * 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$"); DEFINE_TEST(test_archive_api_feature) { + char buff[128]; + + /* This is the (hopefully) final versioning API. */ + assertEqualInt(ARCHIVE_VERSION_NUMBER, archive_version_number()); + sprintf(buff, "libarchive %d.%d.%d", + archive_version_number() / 1000000, + (archive_version_number() / 1000) % 1000, + archive_version_number() % 1000); + assertEqualString(buff, archive_version_string()); + +/* This is all scheduled to disappear in libarchive 3.0 */ +#if ARCHIVE_VERSION_NUMBER < 3000000 + assertEqualInt(ARCHIVE_VERSION_STAMP, ARCHIVE_VERSION_NUMBER); assertEqualInt(ARCHIVE_API_FEATURE, archive_api_feature()); assertEqualInt(ARCHIVE_API_VERSION, archive_api_version()); /* * Even though ARCHIVE_VERSION_STAMP only appears in * archive.h after 1.9.0 and 2.2.3, the macro is synthesized * in test.h, so this test is always valid. */ assertEqualInt(ARCHIVE_VERSION_STAMP / 1000, ARCHIVE_API_VERSION * 1000 + ARCHIVE_API_FEATURE); /* * The function, however, isn't always available. It appeared * sometime in the middle of 2.2.3, but the synthesized value * never has a release version, so the following conditional * exactly determines whether the current library has the * function. */ #if ARCHIVE_VERSION_STAMP / 1000 == 1009 || ARCHIVE_VERSION_STAMP > 2002000 assertEqualInt(ARCHIVE_VERSION_STAMP, archive_version_stamp()); #else skipping("archive_version_stamp()"); #endif assertEqualString(ARCHIVE_LIBRARY_VERSION, archive_version()); +#endif } Index: stable/7/lib/libarchive/test/test_compat_gtar.c =================================================================== --- stable/7/lib/libarchive/test/test_compat_gtar.c (revision 179170) +++ stable/7/lib/libarchive/test/test_compat_gtar.c (revision 179171) @@ -1,110 +1,110 @@ /*- * 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$"); /* * Verify our ability to read sample files created by GNU tar. * It should be easy to add any new sample files sent in by users * to this collection of tests. */ /* Copy this function for each test file and adjust it accordingly. */ /* * test_compat_gtar_1.tgz exercises reading long filenames and * symlink targets stored in the GNU tar format. */ static void test_compat_gtar_1(void) { - char name[1024]; + char name[] = "test_compat_gtar_1.tgz"; struct archive_entry *ae; struct archive *a; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - sprintf(name, "%s/test_compat_gtar_1.tgz", refdir); + extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString( "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890", archive_entry_pathname(ae)); assertEqualInt(1197179003, archive_entry_mtime(ae)); assertEqualInt(1000, archive_entry_uid(ae)); assertEqualString("tim", archive_entry_uname(ae)); assertEqualInt(1000, archive_entry_gid(ae)); assertEqualString("tim", archive_entry_gname(ae)); assertEqualInt(0100644, archive_entry_mode(ae)); /* Read second entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString( "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij" "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij" "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij" "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij", archive_entry_pathname(ae)); assertEqualString( "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890", archive_entry_symlink(ae)); assertEqualInt(1197179043, archive_entry_mtime(ae)); assertEqualInt(1000, archive_entry_uid(ae)); assertEqualString("tim", archive_entry_uname(ae)); assertEqualInt(1000, archive_entry_gid(ae)); assertEqualString("tim", archive_entry_gname(ae)); assertEqualInt(0120755, archive_entry_mode(ae)); /* Verify the end-of-archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify that the format detection worked. */ assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_GZIP); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); #if ARCHIVE_API_VERSION > 1 assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); #else archive_read_finish(a); #endif } DEFINE_TEST(test_compat_gtar) { test_compat_gtar_1(); } Index: stable/7/lib/libarchive/test/test_compat_tar_hardlink.c =================================================================== --- stable/7/lib/libarchive/test/test_compat_tar_hardlink.c (revision 179170) +++ stable/7/lib/libarchive/test/test_compat_tar_hardlink.c (revision 179171) @@ -1,104 +1,104 @@ /*- * 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$"); /* * Background: There are two written standards for the tar file format. * The first is the POSIX 1988 "ustar" format, the second is the 2001 * "pax extended" format that builds on the "ustar" format by adding * support for generic additional attributes. Buried in the details * is one frustrating incompatibility: The 1988 standard says that * tar readers MUST ignore the size field on hardlink entries; the * 2001 standard says that tar readers MUST obey the size field on * hardlink entries. libarchive tries to navigate this particular * minefield by using auto-detect logic to guess whether it should * or should not obey the size field. * * This test tries to probe the boundaries of such handling; the test * archives here were adapted from real archives created by real * tar implementations that are (as of early 2008) apparently still * in use. */ static void test_compat_tar_hardlink_1(void) { - char name[1024]; + char name[] = "test_compat_tar_hardlink_1.tar"; struct archive_entry *ae; struct archive *a; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - sprintf(name, "%s/test_compat_tar_hardlink_1.tar", refdir); + extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry, which is a regular file. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("xmcd-3.3.2/docs_d/READMf", archive_entry_pathname(ae)); assertEqualString(NULL, archive_entry_hardlink(ae)); assertEqualInt(321, archive_entry_size(ae)); assertEqualInt(1082575645, archive_entry_mtime(ae)); assertEqualInt(1851, archive_entry_uid(ae)); assertEqualInt(3, archive_entry_gid(ae)); assertEqualInt(0100444, archive_entry_mode(ae)); /* Read second entry, which is a hard link at the end of archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("xmcd-3.3.2/README", archive_entry_pathname(ae)); assertEqualString( "xmcd-3.3.2/docs_d/READMf", archive_entry_hardlink(ae)); assertEqualInt(0, archive_entry_size(ae)); assertEqualInt(1082575645, archive_entry_mtime(ae)); assertEqualInt(1851, archive_entry_uid(ae)); assertEqualInt(3, archive_entry_gid(ae)); assertEqualInt(0100444, archive_entry_mode(ae)); /* Verify the end-of-archive. */ /* * This failed in libarchive 2.4.12 because the tar reader * tried to obey the size field for the hard link and ended * up running past the end of the file. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify that the format detection worked. */ assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); } DEFINE_TEST(test_compat_tar_hardlink) { test_compat_tar_hardlink_1(); } Index: stable/7/lib/libarchive/test/test_compat_zip.c =================================================================== --- stable/7/lib/libarchive/test/test_compat_zip.c (revision 179170) +++ stable/7/lib/libarchive/test/test_compat_zip.c (revision 179171) @@ -1,69 +1,69 @@ /*- * 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$"); /* Copy this function for each test file and adjust it accordingly. */ static void test_compat_zip_1(void) { - char name[1024]; + char name[] = "test_compat_zip_1.zip"; struct archive_entry *ae; struct archive *a; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - sprintf(name, "%s/test_compat_zip_1.zip", refdir); + extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("META-INF/MANIFEST.MF", archive_entry_pathname(ae)); /* Read second entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("tmp.class", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); #if ARCHIVE_API_VERSION > 1 assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); #else archive_read_finish(a); #endif } DEFINE_TEST(test_compat_zip) { test_compat_zip_1(); } Index: stable/7/lib/libarchive/test/test_empty_write.c =================================================================== --- stable/7/lib/libarchive/test/test_empty_write.c (revision 179170) +++ stable/7/lib/libarchive/test/test_empty_write.c (revision 179171) @@ -1,118 +1,121 @@ /*- * 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$"); DEFINE_TEST(test_empty_write) { char buff[32768]; struct archive_entry *ae; struct archive *a; size_t used; /* * Exercise a zero-byte write to a gzip-compressed archive. */ /* Create a new archive in memory. */ assert((a = archive_write_new()) != NULL); assertA(0 == archive_write_set_format_ustar(a)); assertA(0 == archive_write_set_compression_gzip(a)); assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); /* Write a file to it. */ assert((ae = archive_entry_new()) != NULL); archive_entry_copy_pathname(ae, "file"); archive_entry_set_mode(ae, S_IFREG | 0755); archive_entry_set_size(ae, 0); assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); /* THE TEST: write zero bytes to this entry. */ /* This used to crash. */ assertEqualIntA(a, 0, archive_write_data(a, "", 0)); /* Close out the archive. */ assertA(0 == archive_write_close(a)); #if ARCHIVE_API_VERSION > 1 assertA(0 == archive_write_finish(a)); #else archive_write_finish(a); #endif /* * Again, with bzip2 compression. */ /* Create a new archive in memory. */ assert((a = archive_write_new()) != NULL); assertA(0 == archive_write_set_format_ustar(a)); assertA(0 == archive_write_set_compression_bzip2(a)); assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); /* Write a file to it. */ assert((ae = archive_entry_new()) != NULL); archive_entry_copy_pathname(ae, "file"); archive_entry_set_mode(ae, S_IFREG | 0755); archive_entry_set_size(ae, 0); assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); /* THE TEST: write zero bytes to this entry. */ assertEqualIntA(a, 0, archive_write_data(a, "", 0)); /* Close out the archive. */ assertA(0 == archive_write_close(a)); #if ARCHIVE_API_VERSION > 1 assertA(0 == archive_write_finish(a)); #else archive_write_finish(a); #endif /* * For good measure, one more time with no compression. */ /* Create a new archive in memory. */ assert((a = archive_write_new()) != NULL); assertA(0 == archive_write_set_format_ustar(a)); assertA(0 == archive_write_set_compression_none(a)); assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); /* Write a file to it. */ assert((ae = archive_entry_new()) != NULL); archive_entry_copy_pathname(ae, "file"); archive_entry_set_mode(ae, S_IFREG | 0755); archive_entry_set_size(ae, 0); assertA(0 == archive_write_header(a, ae)); + archive_entry_free(ae); /* THE TEST: write zero bytes to this entry. */ assertEqualIntA(a, 0, archive_write_data(a, "", 0)); /* Close out the archive. */ assertA(0 == archive_write_close(a)); #if ARCHIVE_API_VERSION > 1 assertA(0 == archive_write_finish(a)); #else archive_write_finish(a); #endif } Index: stable/7/lib/libarchive/test/test_entry.c =================================================================== --- stable/7/lib/libarchive/test/test_entry.c (revision 179170) +++ stable/7/lib/libarchive/test/test_entry.c (revision 179171) @@ -1,675 +1,761 @@ /*- * 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$"); +#include + /* * Most of these tests are system-independent, though a few depend on * features of the local system. Such tests are conditionalized on * the platform name. On unsupported platforms, only the * system-independent features will be tested. * * No, I don't want to use config.h in the test files because I want * the tests to also serve as a check on the correctness of config.h. * A mis-configured library build should cause tests to fail. */ DEFINE_TEST(test_entry) { char buff[128]; wchar_t wbuff[128]; struct stat st; struct archive_entry *e, *e2; const struct stat *pst; unsigned long set, clear; /* For fflag testing. */ int type, permset, tag, qual; /* For ACL testing. */ const char *name; /* For ACL testing. */ const char *xname; /* For xattr tests. */ const void *xval; /* For xattr tests. */ size_t xsize; /* For xattr tests. */ int c; assert((e = archive_entry_new()) != NULL); /* * Basic set/read tests for all fields. * We should be able to set any field and read * back the same value. * * For methods that "copy" a string, we should be able * to overwrite the original passed-in string without * changing the value in the entry. * * The following tests are ordered alphabetically by the * name of the field. */ /* atime */ archive_entry_set_atime(e, 13579, 24680); assertEqualInt(archive_entry_atime(e), 13579); assertEqualInt(archive_entry_atime_nsec(e), 24680); /* ctime */ archive_entry_set_ctime(e, 13580, 24681); assertEqualInt(archive_entry_ctime(e), 13580); assertEqualInt(archive_entry_ctime_nsec(e), 24681); #if ARCHIVE_VERSION_STAMP >= 1009000 /* dev */ archive_entry_set_dev(e, 235); assertEqualInt(archive_entry_dev(e), 235); #else skipping("archive_entry_dev()"); #endif /* devmajor/devminor are tested specially below. */ #if ARCHIVE_VERSION_STAMP >= 1009000 /* filetype */ archive_entry_set_filetype(e, AE_IFREG); assertEqualInt(archive_entry_filetype(e), AE_IFREG); #else skipping("archive_entry_filetype()"); #endif /* fflags are tested specially below */ /* gid */ archive_entry_set_gid(e, 204); assertEqualInt(archive_entry_gid(e), 204); /* gname */ archive_entry_set_gname(e, "group"); assertEqualString(archive_entry_gname(e), "group"); wcscpy(wbuff, L"wgroup"); archive_entry_copy_gname_w(e, wbuff); assertEqualWString(archive_entry_gname_w(e), L"wgroup"); memset(wbuff, 0, sizeof(wbuff)); assertEqualWString(archive_entry_gname_w(e), L"wgroup"); /* hardlink */ archive_entry_set_hardlink(e, "hardlinkname"); assertEqualString(archive_entry_hardlink(e), "hardlinkname"); strcpy(buff, "hardlinkname2"); archive_entry_copy_hardlink(e, buff); assertEqualString(archive_entry_hardlink(e), "hardlinkname2"); memset(buff, 0, sizeof(buff)); assertEqualString(archive_entry_hardlink(e), "hardlinkname2"); wcscpy(wbuff, L"whardlink"); archive_entry_copy_hardlink_w(e, wbuff); assertEqualWString(archive_entry_hardlink_w(e), L"whardlink"); memset(wbuff, 0, sizeof(wbuff)); assertEqualWString(archive_entry_hardlink_w(e), L"whardlink"); #if ARCHIVE_VERSION_STAMP >= 1009000 /* ino */ archive_entry_set_ino(e, 8593); assertEqualInt(archive_entry_ino(e), 8593); #else skipping("archive_entry_ino()"); #endif + /* link */ - /* TODO: implement these tests. */ + archive_entry_set_hardlink(e, "hardlinkname"); + archive_entry_set_symlink(e, NULL); + archive_entry_set_link(e, "link"); + assertEqualString(archive_entry_hardlink(e), "link"); + assertEqualString(archive_entry_symlink(e), NULL); + archive_entry_copy_link(e, "link2"); + assertEqualString(archive_entry_hardlink(e), "link2"); + assertEqualString(archive_entry_symlink(e), NULL); + archive_entry_copy_link_w(e, L"link3"); + assertEqualString(archive_entry_hardlink(e), "link3"); + assertEqualString(archive_entry_symlink(e), NULL); + archive_entry_set_hardlink(e, NULL); + archive_entry_set_symlink(e, "symlink"); + archive_entry_set_link(e, "link"); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualString(archive_entry_symlink(e), "link"); + archive_entry_copy_link(e, "link2"); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualString(archive_entry_symlink(e), "link2"); + archive_entry_copy_link_w(e, L"link3"); + assertEqualString(archive_entry_hardlink(e), NULL); + assertEqualString(archive_entry_symlink(e), "link3"); + /* Arbitrarily override hardlink if both hardlink and symlink set. */ + archive_entry_set_hardlink(e, "hardlink"); + archive_entry_set_symlink(e, "symlink"); + archive_entry_set_link(e, "link"); + assertEqualString(archive_entry_hardlink(e), "hardlink"); + assertEqualString(archive_entry_symlink(e), "link"); + /* mode */ archive_entry_set_mode(e, 0123456); assertEqualInt(archive_entry_mode(e), 0123456); /* mtime */ archive_entry_set_mtime(e, 13581, 24682); assertEqualInt(archive_entry_mtime(e), 13581); assertEqualInt(archive_entry_mtime_nsec(e), 24682); #if ARCHIVE_VERSION_STAMP >= 1009000 /* nlink */ archive_entry_set_nlink(e, 736); assertEqualInt(archive_entry_nlink(e), 736); #else skipping("archive_entry_nlink()"); #endif /* pathname */ archive_entry_set_pathname(e, "path"); assertEqualString(archive_entry_pathname(e), "path"); archive_entry_set_pathname(e, "path"); assertEqualString(archive_entry_pathname(e), "path"); strcpy(buff, "path2"); archive_entry_copy_pathname(e, buff); assertEqualString(archive_entry_pathname(e), "path2"); memset(buff, 0, sizeof(buff)); assertEqualString(archive_entry_pathname(e), "path2"); wcscpy(wbuff, L"wpath"); archive_entry_copy_pathname_w(e, wbuff); assertEqualWString(archive_entry_pathname_w(e), L"wpath"); memset(wbuff, 0, sizeof(wbuff)); assertEqualWString(archive_entry_pathname_w(e), L"wpath"); #if ARCHIVE_VERSION_STAMP >= 1009000 /* rdev */ archive_entry_set_rdev(e, 532); assertEqualInt(archive_entry_rdev(e), 532); #else skipping("archive_entry_rdev()"); #endif /* rdevmajor/rdevminor are tested specially below. */ /* size */ archive_entry_set_size(e, 987654321); assertEqualInt(archive_entry_size(e), 987654321); /* symlink */ archive_entry_set_symlink(e, "symlinkname"); assertEqualString(archive_entry_symlink(e), "symlinkname"); #if ARCHIVE_VERSION_STAMP >= 1009000 strcpy(buff, "symlinkname2"); archive_entry_copy_symlink(e, buff); assertEqualString(archive_entry_symlink(e), "symlinkname2"); memset(buff, 0, sizeof(buff)); assertEqualString(archive_entry_symlink(e), "symlinkname2"); #endif archive_entry_copy_symlink_w(e, L"wsymlink"); assertEqualWString(archive_entry_symlink_w(e), L"wsymlink"); /* uid */ archive_entry_set_uid(e, 83); assertEqualInt(archive_entry_uid(e), 83); /* uname */ archive_entry_set_uname(e, "user"); assertEqualString(archive_entry_uname(e), "user"); wcscpy(wbuff, L"wuser"); archive_entry_copy_gname_w(e, wbuff); assertEqualWString(archive_entry_gname_w(e), L"wuser"); memset(wbuff, 0, sizeof(wbuff)); assertEqualWString(archive_entry_gname_w(e), L"wuser"); /* Test fflags interface. */ archive_entry_set_fflags(e, 0x55, 0xAA); archive_entry_fflags(e, &set, &clear); failure("Testing set/get of fflags data."); assertEqualInt(set, 0x55); failure("Testing set/get of fflags data."); assertEqualInt(clear, 0xAA); #ifdef __FreeBSD__ /* Converting fflags bitmap to string is currently system-dependent. */ /* TODO: Make this system-independent. */ assertEqualString(archive_entry_fflags_text(e), "uappnd,nouchg,nodump,noopaque,uunlnk"); /* TODO: Test archive_entry_copy_fflags_text_w() */ #endif /* See test_acl_basic.c for tests of ACL set/get consistency. */ /* Test xattrs set/get consistency. */ archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12); assertEqualInt(1, archive_entry_xattr_reset(e)); assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize)); assertEqualString(xname, "xattr1"); assertEqualString(xval, "xattrvalue1"); assertEqualInt(xsize, 12); assertEqualInt(1, archive_entry_xattr_count(e)); assertEqualInt(ARCHIVE_WARN, archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt(xsize, 0); archive_entry_xattr_clear(e); assertEqualInt(0, archive_entry_xattr_reset(e)); assertEqualInt(ARCHIVE_WARN, archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt(xsize, 0); archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12); assertEqualInt(1, archive_entry_xattr_reset(e)); archive_entry_xattr_add_entry(e, "xattr2", "xattrvalue2", 12); assertEqualInt(2, archive_entry_xattr_reset(e)); assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize)); assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize)); assertEqualInt(ARCHIVE_WARN, archive_entry_xattr_next(e, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt(xsize, 0); /* * Test clone() implementation. */ /* Set values in 'e' */ archive_entry_clear(e); archive_entry_set_atime(e, 13579, 24680); archive_entry_set_ctime(e, 13580, 24681); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_dev(e, 235); #endif archive_entry_set_fflags(e, 0x55, 0xAA); archive_entry_set_gid(e, 204); archive_entry_set_gname(e, "group"); archive_entry_set_hardlink(e, "hardlinkname"); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_ino(e, 8593); #endif archive_entry_set_mode(e, 0123456); archive_entry_set_mtime(e, 13581, 24682); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_nlink(e, 736); #endif archive_entry_set_pathname(e, "path"); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_rdev(e, 532); #endif archive_entry_set_size(e, 987654321); archive_entry_set_symlink(e, "symlinkname"); archive_entry_set_uid(e, 83); archive_entry_set_uname(e, "user"); /* Add an ACL entry. */ archive_entry_acl_add_entry(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ, ARCHIVE_ENTRY_ACL_USER, 77, "user77"); /* Add an extended attribute. */ archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue", 11); /* Make a clone. */ e2 = archive_entry_clone(e); /* Clone should have same contents. */ assertEqualInt(archive_entry_atime(e2), 13579); assertEqualInt(archive_entry_atime_nsec(e2), 24680); assertEqualInt(archive_entry_ctime(e2), 13580); assertEqualInt(archive_entry_ctime_nsec(e2), 24681); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_dev(e2), 235); #endif archive_entry_fflags(e, &set, &clear); assertEqualInt(clear, 0xAA); assertEqualInt(set, 0x55); assertEqualInt(archive_entry_gid(e2), 204); assertEqualString(archive_entry_gname(e2), "group"); assertEqualString(archive_entry_hardlink(e2), "hardlinkname"); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_ino(e2), 8593); #endif assertEqualInt(archive_entry_mode(e2), 0123456); assertEqualInt(archive_entry_mtime(e2), 13581); assertEqualInt(archive_entry_mtime_nsec(e2), 24682); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_nlink(e2), 736); #endif assertEqualString(archive_entry_pathname(e2), "path"); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_rdev(e2), 532); #endif assertEqualInt(archive_entry_size(e2), 987654321); assertEqualString(archive_entry_symlink(e2), "symlinkname"); assertEqualInt(archive_entry_uid(e2), 83); assertEqualString(archive_entry_uname(e2), "user"); #if ARCHIVE_VERSION_STAMP < 1009000 skipping("ACL preserved by archive_entry_clone()"); #else /* Verify ACL was copied. */ assertEqualInt(4, c = archive_entry_acl_reset(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); /* First three are standard permission bits. */ assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, 4); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ); assertEqualInt(qual, -1); assertEqualString(name, NULL); assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, 5); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ); assertEqualInt(qual, -1); assertEqualString(name, NULL); assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, 6); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER); assertEqualInt(qual, -1); assertEqualString(name, NULL); /* Fourth is custom one. */ assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER); assertEqualInt(qual, 77); assertEqualString(name, "user77"); #endif #if ARCHIVE_VERSION_STAMP < 1009000 skipping("xattr data preserved by archive_entry_clone"); #else /* Verify xattr was copied. */ assertEqualInt(1, c = archive_entry_xattr_reset(e2)); assertEqualInt(0, archive_entry_xattr_next(e2, &xname, &xval, &xsize)); assertEqualString(xname, "xattr1"); assertEqualString(xval, "xattrvalue"); assertEqualInt(xsize, 11); + assertEqualInt(ARCHIVE_WARN, + archive_entry_xattr_next(e2, &xname, &xval, &xsize)); + assertEqualString(xname, NULL); + assertEqualString(xval, NULL); + assertEqualInt(xsize, 0); #endif /* Change the original */ archive_entry_set_atime(e, 13580, 24690); archive_entry_set_ctime(e, 13590, 24691); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_dev(e, 245); #endif archive_entry_set_fflags(e, 0x85, 0xDA); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_filetype(e, AE_IFLNK); #endif archive_entry_set_gid(e, 214); archive_entry_set_gname(e, "grouper"); archive_entry_set_hardlink(e, "hardlinkpath"); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_ino(e, 8763); #endif archive_entry_set_mode(e, 0123654); archive_entry_set_mtime(e, 18351, 28642); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_nlink(e, 73); #endif archive_entry_set_pathname(e, "pathest"); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_rdev(e, 132); #endif archive_entry_set_size(e, 987456321); archive_entry_set_symlink(e, "symlinkpath"); archive_entry_set_uid(e, 93); archive_entry_set_uname(e, "username"); archive_entry_acl_clear(e); archive_entry_xattr_clear(e); /* Clone should still have same contents. */ assertEqualInt(archive_entry_atime(e2), 13579); assertEqualInt(archive_entry_atime_nsec(e2), 24680); assertEqualInt(archive_entry_ctime(e2), 13580); assertEqualInt(archive_entry_ctime_nsec(e2), 24681); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_dev(e2), 235); #endif archive_entry_fflags(e2, &set, &clear); assertEqualInt(clear, 0xAA); assertEqualInt(set, 0x55); assertEqualInt(archive_entry_gid(e2), 204); assertEqualString(archive_entry_gname(e2), "group"); assertEqualString(archive_entry_hardlink(e2), "hardlinkname"); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_ino(e2), 8593); #endif assertEqualInt(archive_entry_mode(e2), 0123456); assertEqualInt(archive_entry_mtime(e2), 13581); assertEqualInt(archive_entry_mtime_nsec(e2), 24682); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_nlink(e2), 736); #endif assertEqualString(archive_entry_pathname(e2), "path"); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_rdev(e2), 532); #endif assertEqualInt(archive_entry_size(e2), 987654321); assertEqualString(archive_entry_symlink(e2), "symlinkname"); assertEqualInt(archive_entry_uid(e2), 83); assertEqualString(archive_entry_uname(e2), "user"); #if ARCHIVE_VERSION_STAMP < 1009000 skipping("ACL held by clone of archive_entry"); #else /* Verify ACL was unchanged. */ assertEqualInt(4, c = archive_entry_acl_reset(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); /* First three are standard permission bits. */ assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, 4); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ); assertEqualInt(qual, -1); assertEqualString(name, NULL); assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, 5); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ); assertEqualInt(qual, -1); assertEqualString(name, NULL); assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, 6); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER); assertEqualInt(qual, -1); assertEqualString(name, NULL); /* Fourth is custom one. */ assertEqualInt(0, archive_entry_acl_next(e2, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, &type, &permset, &tag, &qual, &name)); assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ); assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER); assertEqualInt(qual, 77); assertEqualString(name, "user77"); + assertEqualInt(1, archive_entry_acl_next(e2, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(type, 0); + assertEqualInt(permset, 0); + assertEqualInt(tag, 0); + assertEqualInt(qual, -1); + assertEqualString(name, NULL); #endif #if ARCHIVE_VERSION_STAMP < 1009000 skipping("xattr preserved in archive_entry copy"); #else /* Verify xattr was unchanged. */ assertEqualInt(1, archive_entry_xattr_reset(e2)); #endif /* Release clone. */ archive_entry_free(e2); /* * Test clear() implementation. */ archive_entry_clear(e); assertEqualInt(archive_entry_atime(e), 0); assertEqualInt(archive_entry_atime_nsec(e), 0); assertEqualInt(archive_entry_ctime(e), 0); assertEqualInt(archive_entry_ctime_nsec(e), 0); assertEqualInt(archive_entry_dev(e), 0); archive_entry_fflags(e, &set, &clear); assertEqualInt(clear, 0); assertEqualInt(set, 0); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_filetype(e), 0); #endif assertEqualInt(archive_entry_gid(e), 0); assertEqualString(archive_entry_gname(e), NULL); assertEqualString(archive_entry_hardlink(e), NULL); assertEqualInt(archive_entry_ino(e), 0); assertEqualInt(archive_entry_mode(e), 0); assertEqualInt(archive_entry_mtime(e), 0); assertEqualInt(archive_entry_mtime_nsec(e), 0); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_nlink(e), 0); #endif assertEqualString(archive_entry_pathname(e), NULL); assertEqualInt(archive_entry_rdev(e), 0); assertEqualInt(archive_entry_size(e), 0); assertEqualString(archive_entry_symlink(e), NULL); assertEqualInt(archive_entry_uid(e), 0); assertEqualString(archive_entry_uname(e), NULL); /* ACLs should be cleared. */ assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), 0); assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT), 0); /* Extended attributes should be cleared. */ assertEqualInt(archive_entry_xattr_count(e), 0); /* * Test archive_entry_copy_stat(). */ memset(&st, 0, sizeof(st)); /* Set all of the standard 'struct stat' fields. */ st.st_atime = 456789; st.st_ctime = 345678; st.st_dev = 123; st.st_gid = 34; st.st_ino = 234; st.st_mode = 077777; st.st_mtime = 234567; st.st_nlink = 345; st.st_size = 123456789; st.st_uid = 23; #ifdef __FreeBSD__ /* On FreeBSD, high-res timestamp data should come through. */ st.st_atimespec.tv_nsec = 6543210; st.st_ctimespec.tv_nsec = 5432109; st.st_mtimespec.tv_nsec = 3210987; #endif /* Copy them into the entry. */ archive_entry_copy_stat(e, &st); /* Read each one back separately and compare. */ assertEqualInt(archive_entry_atime(e), 456789); assertEqualInt(archive_entry_ctime(e), 345678); assertEqualInt(archive_entry_dev(e), 123); assertEqualInt(archive_entry_gid(e), 34); assertEqualInt(archive_entry_ino(e), 234); assertEqualInt(archive_entry_mode(e), 077777); assertEqualInt(archive_entry_mtime(e), 234567); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(archive_entry_nlink(e), 345); #endif assertEqualInt(archive_entry_size(e), 123456789); assertEqualInt(archive_entry_uid(e), 23); #if __FreeBSD__ /* On FreeBSD, high-res timestamp data should come through. */ assertEqualInt(archive_entry_atime_nsec(e), 6543210); assertEqualInt(archive_entry_ctime_nsec(e), 5432109); assertEqualInt(archive_entry_mtime_nsec(e), 3210987); #endif /* * Test archive_entry_stat(). */ /* First, clear out any existing stat data. */ memset(&st, 0, sizeof(st)); archive_entry_copy_stat(e, &st); /* Set a bunch of fields individually. */ archive_entry_set_atime(e, 456789, 321); archive_entry_set_ctime(e, 345678, 432); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_dev(e, 123); #endif archive_entry_set_gid(e, 34); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_ino(e, 234); #endif archive_entry_set_mode(e, 012345); archive_entry_set_mode(e, 012345); archive_entry_set_mtime(e, 234567, 543); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_nlink(e, 345); #endif archive_entry_set_size(e, 123456789); archive_entry_set_uid(e, 23); /* Retrieve a stat structure. */ assert((pst = archive_entry_stat(e)) != NULL); /* Check that the values match. */ assertEqualInt(pst->st_atime, 456789); assertEqualInt(pst->st_ctime, 345678); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(pst->st_dev, 123); #endif assertEqualInt(pst->st_gid, 34); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(pst->st_ino, 234); #endif assertEqualInt(pst->st_mode, 012345); assertEqualInt(pst->st_mtime, 234567); #if ARCHIVE_VERSION_STAMP >= 1009000 assertEqualInt(pst->st_nlink, 345); #endif assertEqualInt(pst->st_size, 123456789); assertEqualInt(pst->st_uid, 23); #ifdef __FreeBSD__ /* On FreeBSD, high-res timestamp data should come through. */ assertEqualInt(pst->st_atimespec.tv_nsec, 321); assertEqualInt(pst->st_ctimespec.tv_nsec, 432); assertEqualInt(pst->st_mtimespec.tv_nsec, 543); #endif /* Changing any one value should update struct stat. */ archive_entry_set_atime(e, 456788, 0); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_atime, 456788); archive_entry_set_ctime(e, 345677, 431); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_ctime, 345677); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_dev(e, 122); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_dev, 122); #endif archive_entry_set_gid(e, 33); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_gid, 33); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_ino(e, 233); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_ino, 233); #endif archive_entry_set_mode(e, 012344); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_mode, 012344); archive_entry_set_mtime(e, 234566, 542); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_mtime, 234566); #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_nlink(e, 344); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_nlink, 344); #endif archive_entry_set_size(e, 123456788); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_size, 123456788); archive_entry_set_uid(e, 22); assert((pst = archive_entry_stat(e)) != NULL); assertEqualInt(pst->st_uid, 22); /* We don't need to check high-res fields here. */ /* * Test dev/major/minor interfaces. Setting 'dev' or 'rdev' * should change the corresponding major/minor values, and * vice versa. * * The test here is system-specific because it assumes that * makedev(), major(), and minor() are defined in sys/stat.h. * I'm not too worried about it, though, because the code is * simple. If it works on FreeBSD, it's unlikely to be broken * anywhere else. Note: The functionality is present on every * platform even if these tests only run some places; * libarchive's more extensive configuration logic should find * the necessary definitions on every platform. */ #if __FreeBSD__ #if ARCHIVE_VERSION_STAMP >= 1009000 archive_entry_set_dev(e, 0x12345678); assertEqualInt(archive_entry_devmajor(e), major(0x12345678)); assertEqualInt(archive_entry_devminor(e), minor(0x12345678)); assertEqualInt(archive_entry_dev(e), 0x12345678); archive_entry_set_devmajor(e, 0xfe); archive_entry_set_devminor(e, 0xdcba98); assertEqualInt(archive_entry_devmajor(e), 0xfe); assertEqualInt(archive_entry_devminor(e), 0xdcba98); assertEqualInt(archive_entry_dev(e), makedev(0xfe, 0xdcba98)); archive_entry_set_rdev(e, 0x12345678); assertEqualInt(archive_entry_rdevmajor(e), major(0x12345678)); assertEqualInt(archive_entry_rdevminor(e), minor(0x12345678)); assertEqualInt(archive_entry_rdev(e), 0x12345678); archive_entry_set_rdevmajor(e, 0xfe); archive_entry_set_rdevminor(e, 0xdcba98); assertEqualInt(archive_entry_rdevmajor(e), 0xfe); assertEqualInt(archive_entry_rdevminor(e), 0xdcba98); assertEqualInt(archive_entry_rdev(e), makedev(0xfe, 0xdcba98)); #endif #endif + + /* + * Exercise the character-conversion logic, if we can. + */ + failure("Can't exercise charset-conversion logic."); + if (assert(NULL != setlocale(LC_ALL, "de_DE.UTF-8"))) { + /* A filename that cannot be converted to wide characters. */ + archive_entry_copy_pathname(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_pathname_w(e)); + //failure("Converting invalid chars to UTF-8 should fail."); + //assert(NULL == archive_entry_pathname_utf8(e)); + + /* A group name that cannot be converted. */ + archive_entry_copy_gname(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_gname_w(e)); + + /* A user name that cannot be converted. */ + archive_entry_copy_uname(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_uname_w(e)); + + /* A hardlink target that cannot be converted. */ + archive_entry_copy_hardlink(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_hardlink_w(e)); + + /* A symlink target that cannot be converted. */ + archive_entry_copy_symlink(e, "abc\314\214mno\374xyz"); + failure("Converting invalid chars to Unicode should fail."); + assert(NULL == archive_entry_symlink_w(e)); + } /* Release the experimental entry. */ archive_entry_free(e); } Index: stable/7/lib/libarchive/test/test_read_format_gtar_sparse.c =================================================================== --- stable/7/lib/libarchive/test/test_read_format_gtar_sparse.c (revision 179170) +++ stable/7/lib/libarchive/test/test_read_format_gtar_sparse.c (revision 179171) @@ -1,322 +1,321 @@ /*- * 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$"); struct contents { off_t o; size_t s; const char *d; }; struct contents archive_contents_sparse[] = { { 1000000, 1, "a" }, { 2000000, 1, "a" }, { 3145728, 0, NULL } }; struct contents archive_contents_sparse2[] = { { 1000000, 1, "a" }, { 2000000, 1, "a" }, { 3000000, 1, "a" }, { 4000000, 1, "a" }, { 5000000, 1, "a" }, { 6000000, 1, "a" }, { 7000000, 1, "a" }, { 8000000, 1, "a" }, { 9000000, 1, "a" }, { 10000000, 1, "a" }, { 11000000, 1, "a" }, { 12000000, 1, "a" }, { 13000000, 1, "a" }, { 14000000, 1, "a" }, { 15000000, 1, "a" }, { 16000000, 1, "a" }, { 17000000, 1, "a" }, { 18000000, 1, "a" }, { 19000000, 1, "a" }, { 20000000, 1, "a" }, { 21000000, 1, "a" }, { 22000000, 1, "a" }, { 23000000, 1, "a" }, { 24000000, 1, "a" }, { 25000000, 1, "a" }, { 26000000, 1, "a" }, { 27000000, 1, "a" }, { 28000000, 1, "a" }, { 29000000, 1, "a" }, { 30000000, 1, "a" }, { 31000000, 1, "a" }, { 32000000, 1, "a" }, { 33000000, 1, "a" }, { 34000000, 1, "a" }, { 35000000, 1, "a" }, { 36000000, 1, "a" }, { 37000000, 1, "a" }, { 38000000, 1, "a" }, { 39000000, 1, "a" }, { 40000000, 1, "a" }, { 41000000, 1, "a" }, { 42000000, 1, "a" }, { 43000000, 1, "a" }, { 44000000, 1, "a" }, { 45000000, 1, "a" }, { 46000000, 1, "a" }, { 47000000, 1, "a" }, { 48000000, 1, "a" }, { 49000000, 1, "a" }, { 50000000, 1, "a" }, { 51000000, 1, "a" }, { 52000000, 1, "a" }, { 53000000, 1, "a" }, { 54000000, 1, "a" }, { 55000000, 1, "a" }, { 56000000, 1, "a" }, { 57000000, 1, "a" }, { 58000000, 1, "a" }, { 59000000, 1, "a" }, { 60000000, 1, "a" }, { 61000000, 1, "a" }, { 62000000, 1, "a" }, { 63000000, 1, "a" }, { 64000000, 1, "a" }, { 65000000, 1, "a" }, { 66000000, 1, "a" }, { 67000000, 1, "a" }, { 68000000, 1, "a" }, { 69000000, 1, "a" }, { 70000000, 1, "a" }, { 71000000, 1, "a" }, { 72000000, 1, "a" }, { 73000000, 1, "a" }, { 74000000, 1, "a" }, { 75000000, 1, "a" }, { 76000000, 1, "a" }, { 77000000, 1, "a" }, { 78000000, 1, "a" }, { 79000000, 1, "a" }, { 80000000, 1, "a" }, { 81000000, 1, "a" }, { 82000000, 1, "a" }, { 83000000, 1, "a" }, { 84000000, 1, "a" }, { 85000000, 1, "a" }, { 86000000, 1, "a" }, { 87000000, 1, "a" }, { 88000000, 1, "a" }, { 89000000, 1, "a" }, { 90000000, 1, "a" }, { 91000000, 1, "a" }, { 92000000, 1, "a" }, { 93000000, 1, "a" }, { 94000000, 1, "a" }, { 95000000, 1, "a" }, { 96000000, 1, "a" }, { 97000000, 1, "a" }, { 98000000, 1, "a" }, { 99000000, 1, "a" }, { 99000001, 0, NULL } }; struct contents archive_contents_nonsparse[] = { { 0, 1, "a" }, { 1, 0, NULL } }; /* * Describe an archive with three entries: * * File 1: named "sparse" * * a length of 3145728 bytes (3MiB) * * a single 'a' byte at offset 1000000 * * a single 'a' byte at offset 2000000 * File 2: named "sparse2" * * a single 'a' byte at offset 1,000,000, 2,000,000, ..., 99,000,000 * * length of 99,000,001 * File 3: named 'non-sparse' * * length of 1 byte * * contains a single byte 'a' */ struct archive_contents { const char *filename; struct contents *contents; } files[] = { { "sparse", archive_contents_sparse }, { "sparse2", archive_contents_sparse2 }, { "non-sparse", archive_contents_nonsparse }, { NULL, NULL } }; /* * A tricky piece of code that verifies the contents of a sparse * archive entry against a description as defined at the top of this * source file. */ #define min(a,b) ((a) < (b) ? (a) : (b)) static void verify_archive_file(const char *name, struct archive_contents *ac) { - char path[512]; struct archive_entry *ae; int err; /* data, size, offset of next expected block. */ struct contents expect; /* data, size, offset of block read from archive. */ struct contents actual; struct archive *a; - sprintf(path, "%s/%s", refdir, name); + extract_reference_file(name); assert((a = archive_read_new()) != NULL); assert(0 == archive_read_support_compression_all(a)); assert(0 == archive_read_support_format_tar(a)); - failure("Can't open %s", path); - assert(0 == archive_read_open_filename(a, path, 3)); + failure("Can't open %s", name); + assert(0 == archive_read_open_filename(a, name, 3)); while (ac->filename != NULL) { struct contents *cts = ac->contents; assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); failure("Name mismatch in archive %s", name); assertEqualString(ac->filename, archive_entry_pathname(ae)); expect = *cts++; while (0 == (err = archive_read_data_block(a, (const void **)&actual.d, &actual.s, &actual.o))) { while (actual.s > 0) { char c = *(const char *)actual.d; if(actual.o < expect.o) { /* * Any byte before the expected * data must be NULL. */ failure("%s: pad at offset %d " "should be zero", name, actual.o); assertEqualInt(c, 0); } else if (actual.o == expect.o) { /* * Data at matching offsets must match. */ assertEqualInt(c, *expect.d); expect.d++; expect.o++; expect.s--; /* End of expected? step to next expected. */ if (expect.s <= 0) expect = *cts++; } else { /* * We found data beyond that expected. */ failure("%s: Unexpected trailing data", name); assert(actual.o <= expect.o); archive_read_finish(a); return; } actual.d++; actual.o++; actual.s--; } } failure("%s: should be end of entry", name); assertEqualIntA(a, err, ARCHIVE_EOF); failure("%s: Size returned at EOF must be zero", name); assertEqualInt(actual.s, 0); #if ARCHIVE_VERSION_STAMP < 1009000 /* libarchive < 1.9 doesn't get this right */ skipping("offset of final sparse chunk"); #else failure("%s: Offset of final empty chunk must be same as file size", name); assertEqualInt(actual.o, expect.o); #endif /* Step to next file description. */ ++ac; } err = archive_read_next_header(a, &ae); assertEqualIntA(a, ARCHIVE_EOF, err); assert(0 == archive_read_close(a)); #if ARCHIVE_API_VERSION > 1 assert(0 == archive_read_finish(a)); #else archive_read_finish(a); #endif } DEFINE_TEST(test_read_format_gtar_sparse) { /* Two archives that use the "GNU tar sparse format". */ verify_archive_file("test_read_format_gtar_sparse_1_13.tgz", files); verify_archive_file("test_read_format_gtar_sparse_1_17.tgz", files); /* * libarchive < 1.9 doesn't support the newer --posix sparse formats * from GNU tar 1.15 and later. */ #if ARCHIVE_VERSION_STAMP < 1009000 skipping("read support for GNUtar --posix sparse formats"); #else /* * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1 */ verify_archive_file( "test_read_format_gtar_sparse_1_17_posix00.tgz", files); /* * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1 */ verify_archive_file( "test_read_format_gtar_sparse_1_17_posix01.tgz", files); /* * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0 */ verify_archive_file( "test_read_format_gtar_sparse_1_17_posix10.tgz", files); /* * The last test archive here is a little odd. First, it's * uncompressed, because that exercises some of the block * reassembly code a little harder. Second, it includes some * leading comments prior to the sparse block description. * GNU tar doesn't do this, but I think it should, so I want * to ensure that libarchive correctly ignores such comments. * Dump the file, looking for "#!gnu-sparse-format" starting * at byte 0x600. */ verify_archive_file( "test_read_format_gtar_sparse_1_17_posix10_modified.tar", files); #endif }