diff options
author | mm <mm@FreeBSD.org> | 2012-02-25 00:16:00 +0000 |
---|---|---|
committer | mm <mm@FreeBSD.org> | 2012-02-25 00:16:00 +0000 |
commit | b3125341847b997f9f4943129b21004310c1cacd (patch) | |
tree | 2668d05088fbc82cf0170e53f56d547365926031 | |
parent | 3d633235caf324d605954130bd14f380a80cddd3 (diff) | |
download | FreeBSD-src-b3125341847b997f9f4943129b21004310c1cacd.zip FreeBSD-src-b3125341847b997f9f4943129b21004310c1cacd.tar.gz |
Update libarchive's vendor dist to latest changes in release branch.
Git branch: release
Git commit: e2cc36190d7d733b3ac6744ec860d09776c9da02
Obtained from: https://github.com/libarchive/libarchive.git
40 files changed, 961 insertions, 227 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 60672ce..21464cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -607,6 +607,37 @@ ELSE(LIBXML2_FOUND) ENDIF(LIBXML2_FOUND) # +# Find Libregex +# +FIND_PATH(REGEX_INCLUDE_DIR regex.h) +IF(REGEX_INCLUDE_DIR) + CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBC) + # + # If libc does not provide regex, find libregex. + # + IF(NOT HAVE_REGCOMP_LIBC) + FIND_LIBRARY(REGEX_LIBRARY regex) + IF(REGEX_LIBRARY) + SET(CMAKE_REQUIRED_LIBRARIES ${REGEX_LIBRARY}) + CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBREGEX) + IF(HAVE_REGCOMP_LIBREGEX) + LIST(APPEND ADDITIONAL_LIBS ${REGEX_LIBRARY}) + # + # If regex.h is not found, retry looking for regex.h at + # REGEX_INCLUDE_DIR + # + IF(NOT HAVE_REGEX_H) + UNSET(HAVE_REGEX_H CACHE) + INCLUDE_DIRECTORIES(${REGEX_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_INCLUDES ${REGEX_INCLUDE_DIR}) + LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) + ENDIF(NOT HAVE_REGEX_H) + ENDIF(HAVE_REGCOMP_LIBREGEX) + ENDIF(REGEX_LIBRARY) + ENDIF(NOT HAVE_REGCOMP_LIBC) +ENDIF(REGEX_INCLUDE_DIR) + +# # Check functions # IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") diff --git a/configure.ac b/configure.ac index 75c2ca3..91e3469 100644 --- a/configure.ac +++ b/configure.ac @@ -322,6 +322,15 @@ if test "x$ac_cv_header_libxml_xmlreader_h" != "xyes"; then fi fi +AC_ARG_WITH([libregex], + AS_HELP_STRING([--without-libregex], [Don't build support for regex through libregex])) + +if test "x$with_libregex" != "xno"; then + if test "x$ac_cv_header_regex_h" != "xno"; then + AC_CHECK_FUNC(regcomp, , [AC_CHECK_LIB(regex,regcomp)]) + fi +fi + # TODO: Give the user the option of using a pre-existing system # libarchive. This will define HAVE_LIBARCHIVE which will cause # bsdtar_platform.h to use #include <...> for the libarchive headers. diff --git a/cpio/cpio.c b/cpio/cpio.c index 025c50c..2c28d88 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -119,6 +119,7 @@ static void mode_in(struct cpio *); static void mode_list(struct cpio *); static void mode_out(struct cpio *); static void mode_pass(struct cpio *, const char *); +static const char *remove_leading_slash(const char *); static int restore_time(struct cpio *, struct archive_entry *, const char *, int fd); static void usage(void); @@ -155,9 +156,9 @@ main(int argc, char *argv[]) else { #if defined(_WIN32) && !defined(__CYGWIN__) lafe_progname = strrchr(*argv, '\\'); -#else - lafe_progname = strrchr(*argv, '/'); + if (strrchr(*argv, '/') > lafe_progname) #endif + lafe_progname = strrchr(*argv, '/'); if (lafe_progname != NULL) lafe_progname++; else @@ -574,6 +575,49 @@ mode_out(struct cpio *cpio) archive_write_free(cpio->archive); } +static const char * +remove_leading_slash(const char *p) +{ + const char *rp; + + /* Remove leading "//./" or "//?/" or "//?/UNC/" + * (absolute path prefixes used by Windows API) */ + if ((p[0] == '/' || p[0] == '\\') && + (p[1] == '/' || p[1] == '\\') && + (p[2] == '.' || p[2] == '?') && + (p[3] == '/' || p[3] == '\\')) + { + if (p[2] == '?' && + (p[4] == 'U' || p[4] == 'u') && + (p[5] == 'N' || p[5] == 'n') && + (p[6] == 'C' || p[6] == 'c') && + (p[7] == '/' || p[7] == '\\')) + p += 8; + else + p += 4; + } + do { + rp = p; + /* Remove leading drive letter from archives created + * on Windows. */ + if (((p[0] >= 'a' && p[0] <= 'z') || + (p[0] >= 'A' && p[0] <= 'Z')) && + p[1] == ':') { + p += 2; + } + /* Remove leading "/../", "//", etc. */ + while (p[0] == '/' || p[0] == '\\') { + if (p[1] == '.' && p[2] == '.' && + (p[3] == '/' || p[3] == '\\')) { + p += 3; /* Remove "/..", leave "/" + * for next pass. */ + } else + p += 1; /* Remove "/". */ + } + } while (rp != p); + return (p); +} + /* * This is used by both out mode (to copy objects from disk into * an archive) and pass mode (to copy objects from disk to @@ -585,7 +629,6 @@ file_to_archive(struct cpio *cpio, const char *srcpath) const char *destpath; struct archive_entry *entry, *spare; size_t len; - const char *p; int r; /* @@ -639,10 +682,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath) "Can't allocate path buffer"); } strcpy(cpio->pass_destpath, cpio->destdir); - p = srcpath; - while (p[0] == '/') - ++p; - strcat(cpio->pass_destpath, p); + strcat(cpio->pass_destpath, remove_leading_slash(srcpath)); destpath = cpio->pass_destpath; } if (cpio->option_rename) @@ -1139,12 +1179,24 @@ cpio_rename(const char *name) static char buff[1024]; FILE *t; char *p, *ret; +#if defined(_WIN32) && !defined(__CYGWIN__) + FILE *to; + t = fopen("CONIN$", "r"); + if (t == NULL) + return (name); + to = fopen("CONOUT$", "w"); + if (to == NULL) + return (name); + fprintf(to, "%s (Enter/./(new name))? ", name); + fclose(to); +#else t = fopen("/dev/tty", "r+"); if (t == NULL) return (name); fprintf(t, "%s (Enter/./(new name))? ", name); fflush(t); +#endif p = fgets(buff, sizeof(buff), t); fclose(t); diff --git a/cpio/test/main.c b/cpio/test/main.c index a0c5295..0e04059 100644 --- a/cpio/test/main.c +++ b/cpio/test/main.c @@ -2289,7 +2289,15 @@ main(int argc, char **argv) j++; } testprogdir[i] = '\0'; +#if defined(_WIN32) && !defined(__CYGWIN__) + if (testprogdir[0] != '/' && testprogdir[0] != '\\' && + !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') || + (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) && + testprogdir[1] == ':' && + (testprogdir[2] == '/' || testprogdir[2] == '\\'))) +#else if (testprogdir[0] != '/') +#endif { /* Fixup path for relative directories. */ if ((testprogdir = (char *)realloc(testprogdir, @@ -2298,8 +2306,9 @@ main(int argc, char **argv) fprintf(stderr, "ERROR: Out of memory."); exit(1); } - strcpy(testprogdir + strlen(pwd) + 1, testprogdir); - strcpy(testprogdir, pwd); + memmove(testprogdir + strlen(pwd) + 1, testprogdir, + strlen(testprogdir)); + memcpy(testprogdir, pwd, strlen(pwd)); testprogdir[strlen(pwd)] = '/'; } diff --git a/libarchive/archive_options.c b/libarchive/archive_options.c index 962572c..08a348f 100644 --- a/libarchive/archive_options.c +++ b/libarchive/archive_options.c @@ -38,6 +38,7 @@ _archive_set_option(struct archive *a, int magic, const char *fn, option_handler use_option) { const char *mp, *op, *vp; + int r; archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); @@ -47,10 +48,24 @@ _archive_set_option(struct archive *a, if (op == NULL && vp == NULL) return (ARCHIVE_OK); - if (op == NULL) + if (op == NULL) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option"); return (ARCHIVE_FAILED); + } - return use_option(a, mp, op, vp); + r = use_option(a, mp, op, vp); + if (r == ARCHIVE_WARN - 1) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown module name: `%s'", mp); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Undefined option: `%s%s%s%s%s%s'", + vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:""); + return (ARCHIVE_FAILED); + } + return (r); } int @@ -102,6 +117,25 @@ _archive_set_options(struct archive *a, const char *options, free(data); return (ARCHIVE_FATAL); } + if (r == ARCHIVE_FAILED && mod != NULL) { + free(data); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN - 1) { + /* The module name is wrong. */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown module name: `%s'", mod); + free(data); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN) { + /* The option name is wrong. No-one used this. */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Undefined option: `%s%s%s'", + mod?mod:"", mod?":":"", opt); + free(data); + return (ARCHIVE_FAILED); + } if (r == ARCHIVE_OK) anyok = 1; else diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index b1d4914..987295f 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -633,7 +633,7 @@ archive_read_data(struct archive *_a, void *buff, size_t s) } /* Compute the amount of zero padding needed. */ - if (a->read_data_output_offset + s < + if (a->read_data_output_offset + (int64_t)s < a->read_data_offset) { len = s; } else if (a->read_data_output_offset < diff --git a/libarchive/archive_read_data_into_fd.c b/libarchive/archive_read_data_into_fd.c index 14f9410..b4398f1 100644 --- a/libarchive/archive_read_data_into_fd.c +++ b/libarchive/archive_read_data_into_fd.c @@ -64,7 +64,7 @@ pad_to(struct archive *a, int fd, int can_lseek, } while (target_offset > actual_offset) { to_write = nulls_size; - if (target_offset < actual_offset + nulls_size) + if (target_offset < actual_offset + (int64_t)nulls_size) to_write = (size_t)(target_offset - actual_offset); bytes_written = write(fd, nulls, to_write); if (bytes_written < 0) { diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index dd03cee..94c953a 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -733,7 +733,7 @@ _archive_read_data_block(struct archive *_a, const void **buff, t->entry_buff_size = t->current_filesystem->buff_size; buffbytes = t->entry_buff_size; - if (buffbytes > t->current_sparse->length) + if ((int64_t)buffbytes > t->current_sparse->length) buffbytes = t->current_sparse->length; /* diff --git a/libarchive/archive_read_set_options.c b/libarchive/archive_read_set_options.c index d6a5f45..793f8f7 100644 --- a/libarchive/archive_read_set_options.c +++ b/libarchive/archive_read_set_options.c @@ -78,7 +78,7 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o, struct archive_read *a = (struct archive_read *)_a; struct archive_format_descriptor *format; size_t i; - int r, rv = ARCHIVE_FAILED; + int r, rv = ARCHIVE_WARN; for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) { format = &a->formats[i]; @@ -102,6 +102,10 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o, if (r == ARCHIVE_OK) rv = ARCHIVE_OK; } + /* If the format name didn't match, return a special code for + * _archive_set_option[s]. */ + if (rv == ARCHIVE_WARN && m != NULL) + rv = ARCHIVE_WARN - 1; return (rv); } @@ -112,7 +116,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, struct archive_read *a = (struct archive_read *)_a; struct archive_read_filter *filter; struct archive_read_filter_bidder *bidder; - int r, rv = ARCHIVE_FAILED; + int r, rv = ARCHIVE_WARN; for (filter = a->filter; filter != NULL; filter = filter->upstream) { bidder = filter->bidder; @@ -135,6 +139,10 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, if (r == ARCHIVE_OK) rv = ARCHIVE_OK; } + /* If the filter name didn't match, return a special code for + * _archive_set_option[s]. */ + if (rv == ARCHIVE_WARN && m != NULL) + rv = ARCHIVE_WARN - 1; return (rv); } diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index 685c548..0bc7c99 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -478,11 +478,13 @@ archive_read_format_cab_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "cab: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -2066,6 +2068,7 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits) struct lzx_dec *ds; int slot, w_size, w_slot; int base, footer; + int base_inc[18]; if (strm->ds == NULL) { strm->ds = calloc(1, sizeof(*strm->ds)); @@ -2100,13 +2103,15 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits) lzx_huffman_free(&(ds->mt)); } + for (footer = 0; footer < 18; footer++) + base_inc[footer] = 1 << footer; base = footer = 0; for (slot = 0; slot < w_slot; slot++) { int n; if (footer == 0) base = slot; else - base += 1 << footer; + base += base_inc[footer]; if (footer < 17) { footer = -2; for (n = base; n; n >>= 1) @@ -2180,11 +2185,11 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset) end = b + size - 10; while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) { size_t i = b - (unsigned char *)p; - long cp, displacement, value; + int32_t cp, displacement, value; cp = offset + i; value = archive_le32dec(&b[1]); - if (value >= -cp && value < (long)ds->translation_size) { + if (value >= -cp && value < (int32_t)ds->translation_size) { if (value >= 0) displacement = value - cp; else @@ -2475,7 +2480,10 @@ lzx_read_blocks(struct lzx_stream *strm, int last) */ /* Skip padding to align following field on * 16-bit boundary. */ - lzx_br_consume_unalined_bits(br); + if (br->cache_avail == 32 || br->cache_avail == 16) + lzx_br_consume(br, 16); + else + lzx_br_consume_unalined_bits(br); /* Preparation to read repeated offsets R0,R1 and R2. */ ds->rbytes_avail = 0; ds->state = ST_RD_R0; diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c index 5ae73d7..a1f842a 100644 --- a/libarchive/archive_read_support_format_cpio.c +++ b/libarchive/archive_read_support_format_cpio.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -325,7 +325,7 @@ archive_read_format_cpio_options(struct archive_read *a, if (strcmp(key, "compat-2x") == 0) { /* Handle filnames as libarchive 2.x */ cpio->init_default_conversion = (val != NULL)?1:0; - ret = ARCHIVE_OK; + return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -339,11 +339,13 @@ archive_read_format_cpio_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "cpio: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c index 4f0bf0e..ace3b3a 100644 --- a/libarchive/archive_read_support_format_lha.c +++ b/libarchive/archive_read_support_format_lha.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2011 Michihiro NAKAJIMA + * Copyright (c) 2008-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -445,11 +445,13 @@ archive_read_format_lha_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "lha: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 1a8b157..d2a893e 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -757,11 +757,13 @@ archive_read_format_rar_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "rar: unknown keyword ``%s''", key); - - return (ret); + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index eb25581..52d431e 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -369,7 +369,7 @@ archive_read_format_tar_options(struct archive_read *a, /* Handle UTF-8 filnames as libarchive 2.x */ tar->compat_2x = (val != NULL)?1:0; tar->init_default_conversion = tar->compat_2x; - ret = ARCHIVE_OK; + return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -383,11 +383,13 @@ archive_read_format_tar_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "tar: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } /* utility function- this exists to centralize the logic of tracking diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 5668f12..e8e1ce5 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2004 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -441,7 +441,7 @@ archive_read_format_zip_options(struct archive_read *a, if (strcmp(key, "compat-2x") == 0) { /* Handle filnames as libarchive 2.x */ zip->init_default_conversion = (val != NULL) ? 1 : 0; - ret = ARCHIVE_OK; + return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -456,11 +456,13 @@ archive_read_format_zip_options(struct archive_read *a, } else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "zip: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index 1dce560..911d168 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2011 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -849,7 +849,7 @@ archive_string_append_from_wcs(struct archive_string *as, } } as->length += r; - if (wp == NULL || (wp - wpp) >= nwc) + if (wp == NULL || (wp - wpp) >= (int64_t)nwc) break; /* Get a remaining WCS lenth. */ nwc -= wp - wpp; @@ -2333,7 +2333,7 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, { size_t remaining; char *outp; - const char *inp; + const uint8_t *inp; size_t avail; int return_value = 0; /* success */ @@ -2357,11 +2357,11 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, return (-1); remaining = length; - inp = (const char *)_p; + inp = (const uint8_t *)_p; outp = as->s + as->length; avail = as->buffer_length - as->length -1; while (*inp && remaining > 0) { - if (*inp < 0 && (sc->flag & SCONV_TO_UTF8)) { + if (*inp > 127 && (sc->flag & SCONV_TO_UTF8)) { if (avail < UTF8_R_CHAR_SIZE) { as->length = outp - as->s; if (NULL == archive_string_ensure(as, @@ -2381,13 +2381,13 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, inp++; remaining--; return_value = -1; - } else if (*inp < 0) { + } else if (*inp > 127) { *outp++ = '?'; inp++; remaining--; return_value = -1; } else { - *outp++ = *inp++; + *outp++ = (char)*inp++; remaining--; } } diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index 4d37a9c..18c26c7 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -48,6 +48,7 @@ #include "archive_platform.h" #include "archive_private.h" +#include "archive_entry.h" #include <ctype.h> #include <errno.h> #include <stddef.h> @@ -640,6 +641,113 @@ __la_write(int fd, const void *buf, size_t nbytes) } /* + * Replace the Windows path separator '\' with '/'. + */ +static int +replace_pathseparator(struct archive_wstring *ws, const wchar_t *wp) +{ + wchar_t *w; + size_t path_length; + + if (wp == NULL) + return(0); + if (wcschr(wp, L'\\') == NULL) + return(0); + path_length = wcslen(wp); + if (archive_wstring_ensure(ws, path_length) == NULL) + return(-1); + archive_wstrncpy(ws, wp, path_length); + for (w = ws->s; *w; w++) { + if (*w == L'\\') + *w = L'/'; + } + return(1); +} + +static int +fix_pathseparator(struct archive_entry *entry) +{ + struct archive_wstring ws; + const wchar_t *wp; + int ret = ARCHIVE_OK; + + archive_string_init(&ws); + wp = archive_entry_pathname_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_pathname_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + wp = archive_entry_hardlink_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_hardlink_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + wp = archive_entry_symlink_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_symlink_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + archive_wstring_free(&ws); + return(ret); +} + +struct archive_entry * +__la_win_entry_in_posix_pathseparator(struct archive_entry *entry) +{ + struct archive_entry *entry_main; + const wchar_t *wp; + int has_backslash = 0; + int ret; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + if (!has_backslash) { + wp = archive_entry_hardlink_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + } + if (!has_backslash) { + wp = archive_entry_symlink_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + } + /* + * If there is no backslach chars, return the original. + */ + if (!has_backslash) + return (entry); + + /* Copy entry so we can modify it as needed. */ + entry_main = archive_entry_clone(entry); + if (entry_main == NULL) + return (NULL); + /* Replace the Windows path-separator '\' with '/'. */ + ret = fix_pathseparator(entry_main); + if (ret < ARCHIVE_WARN) { + archive_entry_free(entry_main); + return (NULL); + } + return (entry_main); +} + + +/* * The following function was modified from PostgreSQL sources and is * subject to the copyright below. */ diff --git a/libarchive/archive_windows.h b/libarchive/archive_windows.h index cfb3e97..523f855 100644 --- a/libarchive/archive_windows.h +++ b/libarchive/archive_windows.h @@ -261,6 +261,8 @@ extern wchar_t *__la_win_permissive_name(const char *name); extern wchar_t *__la_win_permissive_name_w(const wchar_t *wname); extern void __la_dosmaperr(unsigned long e); #define la_dosmaperr(e) __la_dosmaperr(e) +extern struct archive_entry *__la_win_entry_in_posix_pathseparator( + struct archive_entry *); #endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */ diff --git a/libarchive/archive_write_add_filter_bzip2.c b/libarchive/archive_write_add_filter_bzip2.c index e0d07a9..ef1fcf4 100644 --- a/libarchive/archive_write_add_filter_bzip2.c +++ b/libarchive/archive_write_add_filter_bzip2.c @@ -208,6 +208,9 @@ archive_compressor_bzip2_options(struct archive_write_filter *f, return (ARCHIVE_OK); } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ return (ARCHIVE_WARN); } diff --git a/libarchive/archive_write_add_filter_gzip.c b/libarchive/archive_write_add_filter_gzip.c index 786ae98..d761540 100644 --- a/libarchive/archive_write_add_filter_gzip.c +++ b/libarchive/archive_write_add_filter_gzip.c @@ -220,6 +220,10 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, data->compression_level = value[0] - '0'; return (ARCHIVE_OK); } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ return (ARCHIVE_WARN); } diff --git a/libarchive/archive_write_add_filter_xz.c b/libarchive/archive_write_add_filter_xz.c index b067752..c6a9677 100644 --- a/libarchive/archive_write_add_filter_xz.c +++ b/libarchive/archive_write_add_filter_xz.c @@ -1,6 +1,6 @@ /*- - * Copyright (c) 2009,2010 Michihiro NAKAJIMA * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -365,6 +365,9 @@ archive_compressor_xz_options(struct archive_write_filter *f, return (ARCHIVE_OK); } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ return (ARCHIVE_WARN); } diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index 8300e2e..57000aa 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -1434,7 +1434,7 @@ restore_entry(struct archive_write_disk *a) if (en) { /* Everything failed; give up here. */ - archive_set_error(&a->archive, en, "Can't create '%s'", + archive_set_error(&a->archive, en, "Can't create '%ls'", a->name); return (ARCHIVE_FAILED); } @@ -1844,7 +1844,7 @@ check_symlinks(struct archive_write_disk *a) */ if (disk_unlink(a->name)) { archive_set_error(&a->archive, errno, - "Could not remove symlink %s", + "Could not remove symlink %ls", a->name); pn[0] = c; return (ARCHIVE_FAILED); @@ -1858,7 +1858,7 @@ check_symlinks(struct archive_write_disk *a) */ if (!S_ISLNK(a->mode)) { archive_set_error(&a->archive, 0, - "Removing symlink %s", + "Removing symlink %ls", a->name); } /* Symlink gone. No more problem! */ @@ -1868,15 +1868,15 @@ check_symlinks(struct archive_write_disk *a) /* User asked us to remove problems. */ if (disk_unlink(a->name) != 0) { archive_set_error(&a->archive, 0, - "Cannot remove intervening symlink %s", - a->name); + "Cannot remove intervening " + "symlink %ls", a->name); pn[0] = c; return (ARCHIVE_FAILED); } a->pst = NULL; } else { archive_set_error(&a->archive, 0, - "Cannot extract through symlink %s", + "Cannot extract through symlink %ls", a->name); pn[0] = c; return (ARCHIVE_FAILED); @@ -2147,19 +2147,20 @@ create_dir(struct archive_write_disk *a, wchar_t *path) return (ARCHIVE_OK); if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { archive_set_error(&a->archive, EEXIST, - "Can't create directory '%s'", path); + "Can't create directory '%ls'", path); return (ARCHIVE_FAILED); } if (disk_unlink(path) != 0) { archive_set_error(&a->archive, errno, - "Can't create directory '%s': " + "Can't create directory '%ls': " "Conflicting file cannot be removed", path); return (ARCHIVE_FAILED); } } else if (errno != ENOENT && errno != ENOTDIR) { /* Stat failed? */ - archive_set_error(&a->archive, errno, "Can't test directory '%s'", path); + archive_set_error(&a->archive, errno, + "Can't test directory '%ls'", path); return (ARCHIVE_FAILED); } else if (slash != NULL) { *slash = '\0'; @@ -2211,7 +2212,7 @@ create_dir(struct archive_write_disk *a, wchar_t *path) if (file_information(a, path, &st, &st_mode, 0) == 0 && S_ISDIR(st_mode)) return (ARCHIVE_OK); - archive_set_error(&a->archive, errno, "Failed to create dir '%s'", + archive_set_error(&a->archive, errno, "Failed to create dir '%ls'", path); return (ARCHIVE_FAILED); } @@ -2240,7 +2241,7 @@ set_ownership(struct archive_write_disk *a) } archive_set_error(&a->archive, errno, - "Can't set user=%jd/group=%jd for %s", + "Can't set user=%jd/group=%jd for %ls", (intmax_t)a->uid, (intmax_t)a->gid, a->name); return (ARCHIVE_WARN); } diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index 9820f13..f4dbe30 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -413,7 +413,10 @@ _7z_options(struct archive_write *a, const char *key, const char *value) return (ARCHIVE_OK); } - return (ARCHIVE_FAILED); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -1587,7 +1590,8 @@ file_init_register_empty(struct _7zip *zip) zip->empty_list.last = &(zip->empty_list.first); } -#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) +#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\ + !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) static int compression_unsupported_encoder(struct archive *a, struct la_zstream *lastrm, const char *name) diff --git a/libarchive/archive_write_set_format_cpio.c b/libarchive/archive_write_set_format_cpio.c index 92b9bfb..3ab4f2f 100644 --- a/libarchive/archive_write_set_format_cpio.c +++ b/libarchive/archive_write_set_format_cpio.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -147,11 +148,13 @@ archive_write_cpio_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } /* @@ -278,18 +281,37 @@ write_header(struct archive_write *a, struct archive_entry *entry) int64_t ino; char h[76]; struct archive_string_conv *sconv; + struct archive_entry *entry_main; size_t len; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; sconv = get_sconv(a); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + ret = archive_entry_pathname_l(entry, &path, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", @@ -308,11 +330,13 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (ino < 0) { archive_set_error(&a->archive, ENOMEM, "No memory for ino translation table"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } else if (ino > 0777777) { archive_set_error(&a->archive, ERANGE, "Too many files for this cpio format"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } format_octal(ino & 0777777, h + c_ino_offset, c_ino_size); @@ -339,7 +363,8 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Linkname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate linkname '%s' to %s", @@ -356,25 +381,35 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (ret) { archive_set_error(&a->archive, ERANGE, "File is too large for cpio format."); - return (ARCHIVE_FAILED); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; } ret = __archive_write_output(a, h, sizeof(h)); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } ret = __archive_write_output(a, path, pathlength); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } cpio->entry_bytes_remaining = archive_entry_size(entry); /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = __archive_write_output(a, p, strlen(p)); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } } +exit_write_header: + if (entry_main) + archive_entry_free(entry_main); return (ret_final); } diff --git a/libarchive/archive_write_set_format_cpio_newc.c b/libarchive/archive_write_set_format_cpio_newc.c index d06c391..63ae522 100644 --- a/libarchive/archive_write_set_format_cpio_newc.c +++ b/libarchive/archive_write_set_format_cpio_newc.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2006 Rudolf Marek SYSGO s.r.o. + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -154,11 +155,13 @@ archive_write_newc_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static struct archive_string_conv * @@ -220,6 +223,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) int pathlength, ret, ret_final; char h[c_header_size]; struct archive_string_conv *sconv; + struct archive_entry *entry_main; size_t len; int pad; @@ -227,12 +231,30 @@ write_header(struct archive_write *a, struct archive_entry *entry) ret_final = ARCHIVE_OK; sconv = get_sconv(a); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + ret = archive_entry_pathname_l(entry, &path, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", @@ -284,7 +306,8 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Likname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate linkname '%s' to %s", @@ -301,22 +324,29 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (ret) { archive_set_error(&a->archive, ERANGE, "File is too large for this format."); - return (ARCHIVE_FAILED); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; } ret = __archive_write_output(a, h, c_header_size); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } /* Pad pathname to even length. */ ret = __archive_write_output(a, path, pathlength); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } pad = PAD4(pathlength + c_header_size); if (pad) { ret = __archive_write_output(a, "\0\0\0", pad); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } } cpio->entry_bytes_remaining = archive_entry_size(entry); @@ -325,13 +355,20 @@ write_header(struct archive_write *a, struct archive_entry *entry) /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = __archive_write_output(a, p, strlen(p)); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } pad = PAD4(strlen(p)); ret = __archive_write_output(a, "\0\0\0", pad); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } } +exit_write_header: + if (entry_main) + archive_entry_free(entry_main); return (ret_final); } diff --git a/libarchive/archive_write_set_format_gnutar.c b/libarchive/archive_write_set_format_gnutar.c index dea46b0..5fac49c 100644 --- a/libarchive/archive_write_set_format_gnutar.c +++ b/libarchive/archive_write_set_format_gnutar.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). * Author: Jonas Gastal <jgastal@profusion.mobi> - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * * All rights reserved. * @@ -177,7 +177,8 @@ archive_write_set_format_gnutar(struct archive *_a) gnutar = (struct gnutar *)calloc(1, sizeof(*gnutar)); if (gnutar == NULL) { - archive_set_error(&a->archive, ENOMEM, "Can't allocate gnutar data"); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate gnutar data"); return (ARCHIVE_FATAL); } a->format_data = gnutar; @@ -213,11 +214,13 @@ archive_write_gnutar_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -275,6 +278,7 @@ archive_write_gnutar_header(struct archive_write *a, int tartype; struct gnutar *gnutar; struct archive_string_conv *sconv; + struct archive_entry *entry_main; gnutar = (struct gnutar *)a->format_data; @@ -298,33 +302,95 @@ archive_write_gnutar_header(struct archive_write *a, if (AE_IFDIR == archive_entry_filetype(entry)) { const char *p; - char *t; + size_t path_length; /* * Ensure a trailing '/'. Modify the entry so * the client sees the change. */ - p = archive_entry_pathname(entry); - if (p[strlen(p) - 1] != '/') { - t = (char *)malloc(strlen(p) + 2); - if (t == NULL) { +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate gnutar data"); + "Can't allocate ustar data"); + archive_string_free(&as); return(ARCHIVE_FATAL); } - strcpy(t, p); - strcat(t, "/"); - archive_entry_copy_pathname(entry, t); - free(t); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); } } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif r = archive_entry_pathname_l(entry, &(gnutar->pathname), &(gnutar->pathname_length), sconv); if (r != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathame"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", @@ -338,7 +404,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Uname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -353,7 +420,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Gname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -370,7 +438,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Linkname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -386,7 +455,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Linkname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -409,18 +479,18 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_size(temp, gnutar->linkname_length + 1); ret = archive_format_gnutar_header(a, buff, temp, 'K'); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_output(a, buff, 512); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; archive_entry_free(temp); /* Write as many 512 bytes blocks as needed to write full name. */ ret = __archive_write_output(a, gnutar->linkname, todo); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)todo)); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; } /* If pathname is longer than 100 chars we need to add an 'L' header. */ @@ -438,18 +508,18 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_size(temp, gnutar->pathname_length + 1); ret = archive_format_gnutar_header(a, buff, temp, 'L'); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_output(a, buff, 512); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; archive_entry_free(temp); /* Write as many 512 bytes blocks as needed to write full name. */ ret = __archive_write_output(a, pathname, todo); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)todo)); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; } if (archive_entry_hardlink(entry) != NULL) { @@ -466,28 +536,35 @@ archive_write_gnutar_header(struct archive_write *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "tar format cannot archive socket"); - return (ARCHIVE_FAILED); + ret = ARCHIVE_FAILED; + goto exit_write_header; default: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "tar format cannot archive this (mode=0%lo)", (unsigned long)archive_entry_mode(entry)); - return (ARCHIVE_FAILED); + ret = ARCHIVE_FAILED; + goto exit_write_header; } ret = archive_format_gnutar_header(a, buff, entry, tartype); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; if (ret2 < ret) ret = ret2; ret2 = __archive_write_output(a, buff, 512); - if (ret2 < ARCHIVE_WARN) - return (ret2); + if (ret2 < ARCHIVE_WARN) { + ret = ret2; + goto exit_write_header; + } if (ret2 < ret) ret = ret2; gnutar->entry_bytes_remaining = archive_entry_size(entry); gnutar->entry_padding = 0x1ff & (-(int64_t)gnutar->entry_bytes_remaining); +exit_write_header: + if (entry_main) + archive_entry_free(entry_main); return (ret); } diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index bdb3e3a..90c2157 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1507,6 +1507,11 @@ iso9660_options(struct archive_write *a, const char *key, const char *value) break; } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); + invalid_value: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid value for option ``%s''", key); diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c index 3802a25..6b6449c 100644 --- a/libarchive/archive_write_set_format_mtree.c +++ b/libarchive/archive_write_set_format_mtree.c @@ -1,6 +1,6 @@ /*- - * Copyright (c) 2009,2011 Michihiro NAKAJIMA * Copyright (c) 2008 Joerg Sonnenberger + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1222,7 +1222,10 @@ archive_write_mtree_options(struct archive_write *a, const char *key, return (ARCHIVE_OK); } - return (ARCHIVE_FAILED); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } int diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c index a62d99d..2cd31e7 100644 --- a/libarchive/archive_write_set_format_pax.c +++ b/libarchive/archive_write_set_format_pax.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -187,11 +187,13 @@ archive_write_pax_options(struct archive_write *a, const char *key, } else archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "pax: invalid charset name"); - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "pax: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } /* @@ -463,7 +465,6 @@ archive_write_pax_header(struct archive_write *a, { struct archive_entry *entry_main; const char *p; - char *t; const char *suffix; int need_extension, r, ret; int sparse_count; @@ -541,24 +542,73 @@ archive_write_pax_header(struct archive_write *a, case AE_IFREG: break; case AE_IFDIR: + { /* * Ensure a trailing '/'. Modify the original * entry so the client sees the change. */ - p = archive_entry_pathname(entry_original); - if (p[strlen(p) - 1] != '/') { - t = (char *)malloc(strlen(p) + 2); - if (t == NULL) { +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry_original); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate pax data"); + "Can't allocate pax data"); + archive_wstring_free(&ws); return(ARCHIVE_FATAL); } - strcpy(t, p); - strcat(t, "/"); - archive_entry_copy_pathname(entry_original, t); - free(t); + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w( + entry_original, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry_original); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + archive_string_free(&as); + return(ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname( + entry_original, as.s); + archive_string_free(&as); } break; + } case AE_IFSOCK: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -655,7 +705,20 @@ archive_write_pax_header(struct archive_write *a, } /* Copy entry so we can modify it as needed. */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry_original); + if (entry_main == entry_original) + entry_main = archive_entry_clone(entry_original); +#else entry_main = archive_entry_clone(entry_original); +#endif + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + return(ARCHIVE_FATAL); + } archive_string_empty(&(pax->pax_header)); /* Blank our work area. */ archive_string_empty(&(pax->sparse_map)); sparse_total = 0; diff --git a/libarchive/archive_write_set_format_ustar.c b/libarchive/archive_write_set_format_ustar.c index 4b96ac2..fe8c96a 100644 --- a/libarchive/archive_write_set_format_ustar.c +++ b/libarchive/archive_write_set_format_ustar.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -224,11 +224,13 @@ archive_write_ustar_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -237,6 +239,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) char buff[512]; int ret, ret2; struct ustar *ustar; + struct archive_entry *entry_main; struct archive_string_conv *sconv; ustar = (struct ustar *)a->format_data; @@ -267,37 +270,106 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) if (AE_IFDIR == archive_entry_filetype(entry)) { const char *p; - char *t; + size_t path_length; /* * Ensure a trailing '/'. Modify the entry so * the client sees the change. */ - p = archive_entry_pathname(entry); - if (p[strlen(p) - 1] != '/') { - t = (char *)malloc(strlen(p) + 2); - if (t == NULL) { +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate ustar data"); + "Can't allocate ustar data"); + archive_string_free(&as); return(ARCHIVE_FATAL); } - strcpy(t, p); - strcat(t, "/"); - archive_entry_copy_pathname(entry, t); - free(t); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); } } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv); - if (ret < ARCHIVE_WARN) + if (ret < ARCHIVE_WARN) { + if (entry_main) + archive_entry_free(entry_main); return (ret); + } ret2 = __archive_write_output(a, buff, 512); - if (ret2 < ARCHIVE_WARN) + if (ret2 < ARCHIVE_WARN) { + if (entry_main) + archive_entry_free(entry_main); return (ret2); + } if (ret2 < ret) ret = ret2; ustar->entry_bytes_remaining = archive_entry_size(entry); ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining); + if (entry_main) + archive_entry_free(entry_main); return (ret); } diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index d6e9bcb..988a971 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -498,7 +498,10 @@ xar_options(struct archive_write *a, const char *key, const char *value) return (ARCHIVE_OK); } - return (ARCHIVE_FAILED); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index f07a14f..3801ce1 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2008 Anselm Strauss * Copyright (c) 2009 Joerg Sonnenberger - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -238,6 +238,7 @@ archive_write_zip_options(struct archive_write *a, const char *key, zip->compression = COMPRESSION_STORE; ret = ARCHIVE_OK; } + return (ret); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -251,10 +252,13 @@ archive_write_zip_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); - return (ret); + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } int @@ -381,7 +385,21 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) "Can't allocate zip header data"); return (ARCHIVE_FATAL); } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + l->entry = __la_win_entry_in_posix_pathseparator(entry); + if (l->entry == entry) + l->entry = archive_entry_clone(entry); +#else l->entry = archive_entry_clone(entry); +#endif + if (l->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip header data"); + free(l); + return (ARCHIVE_FATAL); + } l->flags = zip->flags; if (zip->opt_sconv != NULL) sconv = zip->opt_sconv; diff --git a/libarchive/archive_write_set_options.c b/libarchive/archive_write_set_options.c index a8c2d23..2e17984 100644 --- a/libarchive/archive_write_set_options.c +++ b/libarchive/archive_write_set_options.c @@ -79,10 +79,12 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o, if (a->format_name == NULL) return (ARCHIVE_FAILED); + /* If the format name didn't match, return a special code for + * _archive_set_option[s]. */ if (m != NULL && strcmp(m, a->format_name) != 0) - return (ARCHIVE_FAILED); + return (ARCHIVE_WARN - 1); if (a->format_options == NULL) - return (ARCHIVE_FAILED); + return (ARCHIVE_WARN); return a->format_options(a, o, v); } @@ -92,7 +94,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, { struct archive_write *a = (struct archive_write *)_a; struct archive_write_filter *filter; - int r, rv = ARCHIVE_FAILED; + int r, rv = ARCHIVE_WARN; for (filter = a->filter_first; filter != NULL; filter = filter->next_filter) { if (filter->options == NULL) @@ -111,6 +113,10 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, if (r == ARCHIVE_OK) rv = ARCHIVE_OK; } + /* If the filter name didn't match, return a special code for + * _archive_set_option[s]. */ + if (rv == ARCHIVE_WARN && m != NULL) + rv = ARCHIVE_WARN - 1; return (rv); } diff --git a/libarchive/test/main.c b/libarchive/test/main.c index 386b10b..c07d2d2 100644 --- a/libarchive/test/main.c +++ b/libarchive/test/main.c @@ -2287,7 +2287,15 @@ main(int argc, char **argv) j++; } testprogdir[i] = '\0'; +#if defined(_WIN32) && !defined(__CYGWIN__) + if (testprogdir[0] != '/' && testprogdir[0] != '\\' && + !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') || + (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) && + testprogdir[1] == ':' && + (testprogdir[2] == '/' || testprogdir[2] == '\\'))) +#else if (testprogdir[0] != '/') +#endif { /* Fixup path for relative directories. */ if ((testprogdir = (char *)realloc(testprogdir, @@ -2296,8 +2304,9 @@ main(int argc, char **argv) fprintf(stderr, "ERROR: Out of memory."); exit(1); } - strcpy(testprogdir + strlen(pwd) + 1, testprogdir); - strcpy(testprogdir, pwd); + memmove(testprogdir + strlen(pwd) + 1, testprogdir, + strlen(testprogdir)); + memcpy(testprogdir, pwd, strlen(pwd)); testprogdir[strlen(pwd)] = '/'; } diff --git a/libarchive/test/test_archive_read_set_options.c b/libarchive/test/test_archive_read_set_options.c index a199afe..297d8fe 100644 --- a/libarchive/test/test_archive_read_set_options.c +++ b/libarchive/test/test_archive_read_set_options.c @@ -33,14 +33,13 @@ static void test(int pristine) { struct archive* a = archive_read_new(); - int halfempty_options_rv = pristine ? ARCHIVE_WARN : ARCHIVE_OK; + int halfempty_options_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; - int mixed_options_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_WARN; if (!pristine) { archive_read_support_filter_all(a); archive_read_support_format_all(a); - } + } /* NULL and "" denote `no option', so they're ok no matter * what, if any, formats are registered */ @@ -49,25 +48,73 @@ test(int pristine) /* unknown modules and options */ should(a, ARCHIVE_FAILED, "fubar:snafu"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); should(a, ARCHIVE_FAILED, "fubar:snafu=betcha"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); /* unknown modules and options */ should(a, ARCHIVE_FAILED, "snafu"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); should(a, ARCHIVE_FAILED, "snafu=betcha"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); - /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_WARN otherwise */ + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_FAILED otherwise */ should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } should(a, known_option_rv, "joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } should(a, known_option_rv, "!joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } should(a, ARCHIVE_OK, ","); should(a, ARCHIVE_OK, ",,"); should(a, halfempty_options_rv, ",joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } should(a, halfempty_options_rv, "joliet,"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } - should(a, mixed_options_rv, "joliet,snafu"); + should(a, ARCHIVE_FAILED, "joliet,snafu"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + } + + should(a, ARCHIVE_FAILED, "iso9660:snafu"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `iso9660:snafu'", + archive_error_string(a)); + } archive_read_finish(a); } diff --git a/libarchive/test/test_archive_write_set_options.c b/libarchive/test/test_archive_write_set_options.c index f98342e..57aba98 100644 --- a/libarchive/test/test_archive_write_set_options.c +++ b/libarchive/test/test_archive_write_set_options.c @@ -33,14 +33,13 @@ static void test(int pristine) { struct archive* a = archive_write_new(); - int halfempty_options_rv = pristine ? ARCHIVE_WARN : ARCHIVE_OK; + int halfempty_options_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK; - int mixed_options_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_WARN; if (!pristine) { archive_write_set_compression_gzip(a); archive_write_set_format_iso9660(a); - } + } /* NULL and "" denote `no option', so they're ok no matter * what, if any, formats are registered */ @@ -49,25 +48,73 @@ test(int pristine) /* unknown modules and options */ should(a, ARCHIVE_FAILED, "fubar:snafu"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); should(a, ARCHIVE_FAILED, "fubar:snafu=betcha"); + assertEqualString("Unknown module name: `fubar'", + archive_error_string(a)); /* unknown modules and options */ should(a, ARCHIVE_FAILED, "snafu"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); should(a, ARCHIVE_FAILED, "snafu=betcha"); + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); - /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_WARN otherwise */ + /* ARCHIVE_OK with iso9660 loaded, ARCHIVE_FAILED otherwise */ should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } should(a, known_option_rv, "iso9660:joliet"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } should(a, known_option_rv, "joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } should(a, known_option_rv, "!joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } should(a, ARCHIVE_OK, ","); should(a, ARCHIVE_OK, ",,"); should(a, halfempty_options_rv, ",joliet"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } should(a, halfempty_options_rv, "joliet,"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } - should(a, mixed_options_rv, "joliet,snafu"); + should(a, ARCHIVE_FAILED, "joliet,snafu"); + if (pristine) { + assertEqualString("Undefined option: `joliet'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `snafu'", + archive_error_string(a)); + } + + should(a, ARCHIVE_FAILED, "iso9660:snafu"); + if (pristine) { + assertEqualString("Unknown module name: `iso9660'", + archive_error_string(a)); + } else { + assertEqualString("Undefined option: `iso9660:snafu'", + archive_error_string(a)); + } archive_write_finish(a); } diff --git a/libarchive/test/test_write_compress_program.c b/libarchive/test/test_write_compress_program.c index ba005a6..4956e1a 100644 --- a/libarchive/test/test_write_compress_program.c +++ b/libarchive/test/test_write_compress_program.c @@ -40,6 +40,15 @@ DEFINE_TEST(test_write_compress_program) skipping("Cannot run 'gzip'"); return; } + /* NOTE: Setting blocksize=1024 will cause gunzip failure because + * it add extra bytes that gunzip ignores with its warning and + * exit code 1. So we should set blocksize=1 in order not to + * yield the extra bytes when using gunzip. */ + assert((a = archive_read_new()) != NULL); + r = archive_read_support_filter_gzip(a); + if (r != ARCHIVE_OK && canGunzip()) + blocksize = 1; + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Create a new archive in memory. */ /* Write it through an external "gzip" program. */ diff --git a/tar/bsdtar.c b/tar/bsdtar.c index c1fae6a..b8904bf 100644 --- a/tar/bsdtar.c +++ b/tar/bsdtar.c @@ -183,9 +183,9 @@ main(int argc, char **argv) else { #if defined(_WIN32) && !defined(__CYGWIN__) lafe_progname = strrchr(*argv, '\\'); -#else - lafe_progname = strrchr(*argv, '/'); + if (strrchr(*argv, '/') > lafe_progname) #endif + lafe_progname = strrchr(*argv, '/'); if (lafe_progname != NULL) lafe_progname++; else diff --git a/tar/test/main.c b/tar/test/main.c index 984b4ce..d9bd4de 100644 --- a/tar/test/main.c +++ b/tar/test/main.c @@ -2289,7 +2289,15 @@ main(int argc, char **argv) j++; } testprogdir[i] = '\0'; +#if defined(_WIN32) && !defined(__CYGWIN__) + if (testprogdir[0] != '/' && testprogdir[0] != '\\' && + !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') || + (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) && + testprogdir[1] == ':' && + (testprogdir[2] == '/' || testprogdir[2] == '\\'))) +#else if (testprogdir[0] != '/') +#endif { /* Fixup path for relative directories. */ if ((testprogdir = (char *)realloc(testprogdir, @@ -2298,8 +2306,9 @@ main(int argc, char **argv) fprintf(stderr, "ERROR: Out of memory."); exit(1); } - strcpy(testprogdir + strlen(pwd) + 1, testprogdir); - strcpy(testprogdir, pwd); + memmove(testprogdir + strlen(pwd) + 1, testprogdir, + strlen(testprogdir)); + memcpy(testprogdir, pwd, strlen(pwd)); testprogdir[strlen(pwd)] = '/'; } diff --git a/tar/test/test_option_s.c b/tar/test/test_option_s.c index f643f18..a1f8697 100644 --- a/tar/test/test_option_s.c +++ b/tar/test/test_option_s.c @@ -55,33 +55,35 @@ DEFINE_TEST(test_option_s) * 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); + systemf("%s -cf test1_1.tar -s /foo/bar/ in/d1/foo", testprog); + systemf("%s -xf test1_1.tar -C test1", testprog); assertFileContents("foo", 3, "test1/in/d1/bar"); - systemf("%s -cf - -s /d1/d2/ in/d1/foo | %s -xf - -C test1", - testprog, testprog); + systemf("%s -cf test1_2.tar -s /d1/d2/ in/d1/foo", testprog); + systemf("%s -xf test1_2.tar -C test1", 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); + systemf("%s -cf test2.tar in/d1/foo", testprog); + systemf("%s -xf test2.tar -s /foo/bar/ -C test2", 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); + systemf("%s -cf test3.tar -s ,in/d1/foo,, in/d1/foo", testprog); + systemf("%s -tvf test3.tar > in.lst", 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", + systemf("%s -cf test4.tar in/d1/foo in/d1/bar", + testprog, testprog); + systemf("%s -xf test4.tar -s /foo/bar/ -s }bar}baz} -C test4", testprog, testprog); assertFileContents("foo", 3, "test4/in/d1/bar"); assertFileContents("bar", 3, "test4/in/d1/baz"); @@ -90,7 +92,9 @@ DEFINE_TEST(test_option_s) * 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", + systemf("%s -cf test5.tar in/d1/foo in/d1/bar", + testprog, testprog); + systemf("%s -xf test5.tar -s /foo/bar/ -s }bar}foo} -C test5", testprog, testprog); assertFileContents("foo", 3, "test5/in/d1/bar"); assertFileContents("bar", 3, "test5/in/d1/foo"); @@ -140,13 +144,13 @@ DEFINE_TEST(test_option_s) */ /* At extraction time. */ assertMakeDir("test8a", 0755); - systemf("%s -cf - in/d1 | %s -xf - -s /d1/d2/ -C test8a", - testprog, testprog); + systemf("%s -cf test8a.tar in/d1", testprog); + systemf("%s -xf test8a.tar -s /d1/d2/ -C test8a", testprog); assertIsHardlink("test8a/in/d2/hardlink1", "test8a/in/d2/hardlink2"); /* At creation time. */ assertMakeDir("test8b", 0755); - systemf("%s -cf - -s /d1/d2/ in/d1 | %s -xf - -C test8b", - testprog, testprog); + systemf("%s -cf test8b.tar -s /d1/d2/ in/d1", testprog); + systemf("%s -xf test8b.tar -C test8b", testprog); assertIsHardlink("test8b/in/d2/hardlink1", "test8b/in/d2/hardlink2"); /* @@ -154,23 +158,27 @@ DEFINE_TEST(test_option_s) */ /* At extraction. (assuming hardlink2 is the hardlink entry) */ assertMakeDir("test9a", 0755); - systemf("%s -cf - in/d1 | %s -xf - -s /hardlink1/hardlink1-renamed/ -C test9a", - testprog, testprog); + systemf("%s -cf test9a.tar in/d1", testprog); + systemf("%s -xf test9a.tar -s /hardlink1/hardlink1-renamed/ -C test9a", + testprog); assertIsHardlink("test9a/in/d1/hardlink1-renamed", "test9a/in/d1/hardlink2"); /* At extraction. (assuming hardlink1 is the hardlink entry) */ assertMakeDir("test9b", 0755); - systemf("%s -cf - in/d1 | %s -xf - -s /hardlink2/hardlink2-renamed/ -C test9b", - testprog, testprog); + systemf("%s -cf test9b.tar in/d1", testprog); + systemf("%s -xf test9b.tar -s /hardlink2/hardlink2-renamed/ -C test9b", + testprog); assertIsHardlink("test9b/in/d1/hardlink1", "test9b/in/d1/hardlink2-renamed"); /* At creation. (assuming hardlink2 is the hardlink entry) */ assertMakeDir("test9c", 0755); - systemf("%s -cf - -s /hardlink1/hardlink1-renamed/ in/d1 | %s -xf - -C test9c", - testprog, testprog); + systemf("%s -cf test9c.tar -s /hardlink1/hardlink1-renamed/ in/d1", + testprog); + systemf("%s -xf test9c.tar -C test9c", testprog); assertIsHardlink("test9c/in/d1/hardlink1-renamed", "test9c/in/d1/hardlink2"); /* At creation. (assuming hardlink1 is the hardlink entry) */ assertMakeDir("test9d", 0755); - systemf("%s -cf - -s /hardlink2/hardlink2-renamed/ in/d1 | %s -xf - -C test9d", - testprog, testprog); + systemf("%s -cf test9d.tar -s /hardlink2/hardlink2-renamed/ in/d1", + testprog); + systemf("%s -xf test9d.tar -C test9d", testprog); assertIsHardlink("test9d/in/d1/hardlink1", "test9d/in/d1/hardlink2-renamed"); /* @@ -224,8 +232,8 @@ DEFINE_TEST(test_option_s) */ extract_reference_file("test_option_s.tar.Z"); assertMakeDir("test12a", 0755); - systemf("%s -xf test_option_s.tar.Z -s /hardlink1/foo/H -s /foo/hardlink1/ -C test12a", - testprog); + systemf("%s -xf test_option_s.tar.Z -s /hardlink1/foo/H -s /foo/hardlink1/ %s -C test12a", + testprog, canSymlink()?"":"--exclude in/d1/symlink"); assertFileContents("foo", 3, "test12a/in/d1/hardlink1"); assertFileContents("hardlinkedfile", 14, "test12a/in/d1/foo"); assertFileContents("foo", 3, "test12a/in/d1/hardlink2"); @@ -243,8 +251,8 @@ DEFINE_TEST(test_option_s) */ extract_reference_file("test_option_s.tar.Z"); assertMakeDir("test13a", 0755); - systemf("%s -xf test_option_s.tar.Z -s /hardlink1/foo/Rh -s /foo/hardlink1/Rh -C test13a", - testprog); + systemf("%s -xf test_option_s.tar.Z -s /hardlink1/foo/Rh -s /foo/hardlink1/Rh %s -C test13a", + testprog, canSymlink()?"":"--exclude in/d1/symlink"); assertFileContents("foo", 3, "test13a/in/d1/foo"); assertFileContents("hardlinkedfile", 14, "test13a/in/d1/hardlink1"); assertFileContents("foo", 3, "test13a/in/d1/hardlink2"); |