Update bsdtar to 2.8.4
Use common code from lib/libarchive/libarchive_fe Approved by: kientzle MFC after: 2 weeks
This commit is contained in:
parent
38abb26b5a
commit
2ad1419f1b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=224153
@ -2,21 +2,24 @@
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= bsdtar
|
||||
BSDTAR_VERSION_STRING=2.8.3
|
||||
BSDTAR_VERSION_STRING=2.8.4
|
||||
SRCS= bsdtar.c \
|
||||
cmdline.c \
|
||||
err.c \
|
||||
getdate.c \
|
||||
line_reader.c \
|
||||
matching.c \
|
||||
pathmatch.c \
|
||||
read.c \
|
||||
subst.c \
|
||||
tree.c \
|
||||
util.c \
|
||||
write.c
|
||||
DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ} ${LIBMD} ${LIBLZMA}
|
||||
LDADD= -larchive -lbz2 -lz -lmd -llzma
|
||||
|
||||
.PATH: ${.CURDIR}/../../lib/libarchive/libarchive_fe
|
||||
SRCS+= err.c \
|
||||
line_reader.c \
|
||||
matching.c \
|
||||
pathmatch.c
|
||||
|
||||
DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ} ${LIBMD} ${LIBLZMA} ${LIBBSDXML}
|
||||
LDADD= -larchive -lbz2 -lz -lmd -llzma -lbsdxml
|
||||
.if ${MK_OPENSSL} != "no"
|
||||
DPADD+= ${LIBCRYPTO}
|
||||
LDADD+= -lcrypto
|
||||
@ -24,6 +27,7 @@ LDADD+= -lcrypto
|
||||
CFLAGS+= -DBSDTAR_VERSION_STRING=\"${BSDTAR_VERSION_STRING}\"
|
||||
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
|
||||
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../lib/libarchive
|
||||
CFLAGS+= -I${.CURDIR}/../../lib/libarchive/libarchive_fe
|
||||
SYMLINKS= bsdtar ${BINDIR}/tar
|
||||
MLINKS= bsdtar.1 tar.1
|
||||
DEBUG_FLAGS=-g
|
||||
|
@ -50,8 +50,8 @@
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
creates and manipulates streaming archive files.
|
||||
This implementation can extract from tar, pax, cpio, zip, jar, ar,
|
||||
xar, and ISO 9660 cdrom images and can create tar, pax, cpio, ar, zip,
|
||||
This implementation can extract from tar, pax, cpio, zip, jar, ar, xar,
|
||||
rpm and ISO 9660 cdrom images and can create tar, pax, cpio, ar, zip,
|
||||
and shar archives.
|
||||
.Pp
|
||||
The first synopsis form shows a
|
||||
|
@ -63,6 +63,9 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#include "bsdtar.h"
|
||||
#include "err.h"
|
||||
@ -86,6 +89,8 @@ __FBSDID("$FreeBSD$");
|
||||
int _CRT_glob = 0; /* Disable broken CRT globbing. */
|
||||
#endif
|
||||
|
||||
static struct bsdtar *_bsdtar;
|
||||
|
||||
#if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1))
|
||||
static volatile int siginfo_occurred;
|
||||
|
||||
@ -139,7 +144,7 @@ main(int argc, char **argv)
|
||||
* Use a pointer for consistency, but stack-allocated storage
|
||||
* for ease of cleanup.
|
||||
*/
|
||||
bsdtar = &bsdtar_storage;
|
||||
_bsdtar = bsdtar = &bsdtar_storage;
|
||||
memset(bsdtar, 0, sizeof(*bsdtar));
|
||||
bsdtar->fd = -1; /* Mark as "unused" */
|
||||
option_o = 0;
|
||||
@ -152,36 +157,36 @@ main(int argc, char **argv)
|
||||
sa.sa_flags = 0;
|
||||
#ifdef SIGINFO
|
||||
if (sigaction(SIGINFO, &sa, NULL))
|
||||
bsdtar_errc(1, errno, "sigaction(SIGINFO) failed");
|
||||
lafe_errc(1, errno, "sigaction(SIGINFO) failed");
|
||||
#endif
|
||||
#ifdef SIGUSR1
|
||||
/* ... and treat SIGUSR1 the same way as SIGINFO. */
|
||||
if (sigaction(SIGUSR1, &sa, NULL))
|
||||
bsdtar_errc(1, errno, "sigaction(SIGUSR1) failed");
|
||||
lafe_errc(1, errno, "sigaction(SIGUSR1) failed");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Need bsdtar_progname before calling bsdtar_warnc. */
|
||||
/* Need lafe_progname before calling lafe_warnc. */
|
||||
if (*argv == NULL)
|
||||
bsdtar_progname = "bsdtar";
|
||||
lafe_progname = "bsdtar";
|
||||
else {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
bsdtar_progname = strrchr(*argv, '\\');
|
||||
lafe_progname = strrchr(*argv, '\\');
|
||||
#else
|
||||
bsdtar_progname = strrchr(*argv, '/');
|
||||
lafe_progname = strrchr(*argv, '/');
|
||||
#endif
|
||||
if (bsdtar_progname != NULL)
|
||||
bsdtar_progname++;
|
||||
if (lafe_progname != NULL)
|
||||
lafe_progname++;
|
||||
else
|
||||
bsdtar_progname = *argv;
|
||||
lafe_progname = *argv;
|
||||
}
|
||||
|
||||
time(&now);
|
||||
|
||||
#if HAVE_SETLOCALE
|
||||
if (setlocale(LC_ALL, "") == NULL)
|
||||
bsdtar_warnc(0, "Failed to set default locale");
|
||||
lafe_warnc(0, "Failed to set default locale");
|
||||
#endif
|
||||
#if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER)
|
||||
bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd');
|
||||
@ -233,7 +238,7 @@ main(int argc, char **argv)
|
||||
case 'b': /* SUSv2 */
|
||||
t = atoi(bsdtar->optarg);
|
||||
if (t <= 0 || t > 8192)
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Argument to -b is out of range (1..8192)");
|
||||
bsdtar->bytes_per_block = 512 * t;
|
||||
break;
|
||||
@ -251,7 +256,7 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case OPTION_EXCLUDE: /* GNU tar */
|
||||
if (lafe_exclude(&bsdtar->matching, bsdtar->optarg))
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Couldn't exclude %s\n", bsdtar->optarg);
|
||||
break;
|
||||
case OPTION_FORMAT: /* GNU tar, others */
|
||||
@ -297,20 +302,20 @@ main(int argc, char **argv)
|
||||
* when transforming archives.
|
||||
*/
|
||||
if (lafe_include(&bsdtar->matching, bsdtar->optarg))
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Failed to add %s to inclusion list",
|
||||
bsdtar->optarg);
|
||||
break;
|
||||
case 'j': /* GNU tar */
|
||||
if (bsdtar->create_compression != '\0')
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't specify both -%c and -%c", opt,
|
||||
bsdtar->create_compression);
|
||||
bsdtar->create_compression = opt;
|
||||
break;
|
||||
case 'J': /* GNU tar 1.21 and later */
|
||||
if (bsdtar->create_compression != '\0')
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't specify both -%c and -%c", opt,
|
||||
bsdtar->create_compression);
|
||||
bsdtar->create_compression = opt;
|
||||
@ -330,7 +335,7 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case OPTION_LZMA:
|
||||
if (bsdtar->create_compression != '\0')
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't specify both -%c and -%c", opt,
|
||||
bsdtar->create_compression);
|
||||
bsdtar->create_compression = opt;
|
||||
@ -355,7 +360,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(bsdtar->optarg, &st) != 0)
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't open file %s", bsdtar->optarg);
|
||||
bsdtar->newer_ctime_sec = st.st_ctime;
|
||||
bsdtar->newer_ctime_nsec =
|
||||
@ -369,7 +374,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(bsdtar->optarg, &st) != 0)
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't open file %s", bsdtar->optarg);
|
||||
bsdtar->newer_mtime_sec = st.st_mtime;
|
||||
bsdtar->newer_mtime_nsec =
|
||||
@ -440,7 +445,7 @@ main(int argc, char **argv)
|
||||
#if HAVE_REGEX_H
|
||||
add_substitution(bsdtar, bsdtar->optarg);
|
||||
#else
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"-s is not supported by this version of bsdtar");
|
||||
usage();
|
||||
#endif
|
||||
@ -487,7 +492,7 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case 'X': /* GNU tar */
|
||||
if (lafe_exclude_from_file(&bsdtar->matching, bsdtar->optarg))
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"failed to process exclusions from file %s",
|
||||
bsdtar->optarg);
|
||||
break;
|
||||
@ -496,21 +501,21 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case 'y': /* FreeBSD version of GNU tar */
|
||||
if (bsdtar->create_compression != '\0')
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't specify both -%c and -%c", opt,
|
||||
bsdtar->create_compression);
|
||||
bsdtar->create_compression = opt;
|
||||
break;
|
||||
case 'Z': /* GNU tar */
|
||||
if (bsdtar->create_compression != '\0')
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't specify both -%c and -%c", opt,
|
||||
bsdtar->create_compression);
|
||||
bsdtar->create_compression = opt;
|
||||
break;
|
||||
case 'z': /* GNU tar, star, many others */
|
||||
if (bsdtar->create_compression != '\0')
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't specify both -%c and -%c", opt,
|
||||
bsdtar->create_compression);
|
||||
bsdtar->create_compression = opt;
|
||||
@ -535,7 +540,7 @@ main(int argc, char **argv)
|
||||
|
||||
/* Otherwise, a mode is required. */
|
||||
if (bsdtar->mode == '\0')
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Must specify one of -c, -r, -t, -u, -x");
|
||||
|
||||
/* Check boolean options only permitted in certain modes. */
|
||||
@ -615,7 +620,7 @@ main(int argc, char **argv)
|
||||
#endif
|
||||
|
||||
if (bsdtar->return_value != 0)
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Error exit delayed from previous errors.");
|
||||
return (bsdtar->return_value);
|
||||
}
|
||||
@ -624,7 +629,7 @@ static void
|
||||
set_mode(struct bsdtar *bsdtar, char opt)
|
||||
{
|
||||
if (bsdtar->mode != '\0' && bsdtar->mode != opt)
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't specify both -%c and -%c", opt, bsdtar->mode);
|
||||
bsdtar->mode = opt;
|
||||
}
|
||||
@ -636,7 +641,7 @@ static void
|
||||
only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes)
|
||||
{
|
||||
if (strchr(valid_modes, bsdtar->mode) == NULL)
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Option %s is not permitted in mode -%c",
|
||||
opt, bsdtar->mode);
|
||||
}
|
||||
@ -647,7 +652,7 @@ usage(void)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
p = bsdtar_progname;
|
||||
p = lafe_progname;
|
||||
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr, " List: %s -tf <archive-filename>\n", p);
|
||||
@ -707,7 +712,7 @@ long_help(void)
|
||||
const char *prog;
|
||||
const char *p;
|
||||
|
||||
prog = bsdtar_progname;
|
||||
prog = lafe_progname;
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
|
@ -221,7 +221,7 @@ bsdtar_getopt(struct bsdtar *bsdtar)
|
||||
if (p[1] == ':') {
|
||||
bsdtar->optarg = *bsdtar->argv;
|
||||
if (bsdtar->optarg == NULL) {
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Option %c requires an argument",
|
||||
opt);
|
||||
return ('?');
|
||||
@ -288,7 +288,7 @@ bsdtar_getopt(struct bsdtar *bsdtar)
|
||||
/* Otherwise, pick up the next word. */
|
||||
opt_word = *bsdtar->argv;
|
||||
if (opt_word == NULL) {
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Option -%c requires an argument",
|
||||
opt);
|
||||
return ('?');
|
||||
@ -339,13 +339,13 @@ bsdtar_getopt(struct bsdtar *bsdtar)
|
||||
|
||||
/* Fail if there wasn't a unique match. */
|
||||
if (match == NULL) {
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Option %s%s is not supported",
|
||||
long_prefix, opt_word);
|
||||
return ('?');
|
||||
}
|
||||
if (match2 != NULL) {
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Ambiguous option %s%s (matches --%s and --%s)",
|
||||
long_prefix, opt_word, match->name, match2->name);
|
||||
return ('?');
|
||||
@ -357,7 +357,7 @@ bsdtar_getopt(struct bsdtar *bsdtar)
|
||||
if (bsdtar->optarg == NULL) {
|
||||
bsdtar->optarg = *bsdtar->argv;
|
||||
if (bsdtar->optarg == NULL) {
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Option %s%s requires an argument",
|
||||
long_prefix, match->name);
|
||||
return ('?');
|
||||
@ -368,7 +368,7 @@ bsdtar_getopt(struct bsdtar *bsdtar)
|
||||
} else {
|
||||
/* Argument forbidden: fail if there is one. */
|
||||
if (bsdtar->optarg != NULL) {
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Option %s%s does not allow an argument",
|
||||
long_prefix, match->name);
|
||||
return ('?');
|
||||
|
@ -44,6 +44,7 @@
|
||||
#undef HAVE_LIBACL
|
||||
#define HAVE_LIBARCHIVE 1
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_LINK 1
|
||||
#undef HAVE_LINUX_EXT2_FS_H
|
||||
#undef HAVE_LINUX_FS_H
|
||||
#define HAVE_LOCALE_H 1
|
||||
@ -77,5 +78,5 @@
|
||||
#define HAVE_TIME_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_WCTYPE_H 1
|
||||
#define HAVE_WCSCMP 1
|
||||
#undef HAVE_WINDOWS_H
|
||||
|
||||
|
@ -1,74 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2010 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
|
||||
* in this position and unchanged.
|
||||
* 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 "bsdtar_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "err.h"
|
||||
|
||||
const char *bsdtar_progname;
|
||||
|
||||
static void
|
||||
bsdtar_vwarnc(int code, const char *fmt, va_list ap)
|
||||
{
|
||||
fprintf(stderr, "%s: ", bsdtar_progname);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (code != 0)
|
||||
fprintf(stderr, ": %s", strerror(code));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
bsdtar_warnc(int code, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
bsdtar_vwarnc(code, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
bsdtar_errc(int eval, int code, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
bsdtar_vwarnc(code, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(eval);
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 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 "bsdtar_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "err.h"
|
||||
#include "line_reader.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read lines from file and do something with each one. If option_null
|
||||
* is set, lines are terminated with zero bytes; otherwise, they're
|
||||
* terminated with newlines.
|
||||
*
|
||||
* This uses a self-sizing buffer to handle arbitrarily-long lines.
|
||||
*/
|
||||
struct lafe_line_reader {
|
||||
FILE *f;
|
||||
char *buff, *buff_end, *line_start, *line_end, *p;
|
||||
char *pathname;
|
||||
size_t buff_length;
|
||||
int nullSeparator; /* Lines separated by null, not CR/CRLF/etc. */
|
||||
int ret;
|
||||
};
|
||||
|
||||
struct lafe_line_reader *
|
||||
lafe_line_reader(const char *pathname, int nullSeparator)
|
||||
{
|
||||
struct lafe_line_reader *lr;
|
||||
|
||||
lr = calloc(1, sizeof(*lr));
|
||||
if (lr == NULL)
|
||||
bsdtar_errc(1, ENOMEM, "Can't open %s", pathname);
|
||||
|
||||
lr->nullSeparator = nullSeparator;
|
||||
lr->pathname = strdup(pathname);
|
||||
|
||||
if (strcmp(pathname, "-") == 0)
|
||||
lr->f = stdin;
|
||||
else
|
||||
lr->f = fopen(pathname, "r");
|
||||
if (lr->f == NULL)
|
||||
bsdtar_errc(1, errno, "Couldn't open %s", pathname);
|
||||
lr->buff_length = 8192;
|
||||
lr->buff = malloc(lr->buff_length);
|
||||
if (lr->buff == NULL)
|
||||
bsdtar_errc(1, ENOMEM, "Can't read %s", pathname);
|
||||
lr->line_start = lr->line_end = lr->buff_end = lr->buff;
|
||||
|
||||
return (lr);
|
||||
}
|
||||
|
||||
const char *
|
||||
lafe_line_reader_next(struct lafe_line_reader *lr)
|
||||
{
|
||||
size_t bytes_wanted, bytes_read, new_buff_size;
|
||||
char *line_start, *p;
|
||||
|
||||
for (;;) {
|
||||
/* If there's a line in the buffer, return it immediately. */
|
||||
while (lr->line_end < lr->buff_end) {
|
||||
if (lr->nullSeparator) {
|
||||
if (*lr->line_end == '\0') {
|
||||
line_start = lr->line_start;
|
||||
lr->line_start = lr->line_end + 1;
|
||||
lr->line_end = lr->line_start;
|
||||
return (line_start);
|
||||
}
|
||||
} else if (*lr->line_end == '\x0a' || *lr->line_end == '\x0d') {
|
||||
*lr->line_end = '\0';
|
||||
line_start = lr->line_start;
|
||||
lr->line_start = lr->line_end + 1;
|
||||
lr->line_end = lr->line_start;
|
||||
if (line_start[0] != '\0')
|
||||
return (line_start);
|
||||
}
|
||||
lr->line_end++;
|
||||
}
|
||||
|
||||
/* If we're at end-of-file, process the final data. */
|
||||
if (lr->f == NULL) {
|
||||
/* If there's more text, return one last line. */
|
||||
if (lr->line_end > lr->line_start) {
|
||||
*lr->line_end = '\0';
|
||||
line_start = lr->line_start;
|
||||
lr->line_start = lr->line_end + 1;
|
||||
lr->line_end = lr->line_start;
|
||||
return (line_start);
|
||||
}
|
||||
/* Otherwise, we're done. */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Buffer only has part of a line. */
|
||||
if (lr->line_start > lr->buff) {
|
||||
/* Move a leftover fractional line to the beginning. */
|
||||
memmove(lr->buff, lr->line_start,
|
||||
lr->buff_end - lr->line_start);
|
||||
lr->buff_end -= lr->line_start - lr->buff;
|
||||
lr->line_end -= lr->line_start - lr->buff;
|
||||
lr->line_start = lr->buff;
|
||||
} else {
|
||||
/* Line is too big; enlarge the buffer. */
|
||||
new_buff_size = lr->buff_length * 2;
|
||||
if (new_buff_size <= lr->buff_length)
|
||||
bsdtar_errc(1, ENOMEM,
|
||||
"Line too long in %s", lr->pathname);
|
||||
lr->buff_length = new_buff_size;
|
||||
p = realloc(lr->buff, new_buff_size);
|
||||
if (p == NULL)
|
||||
bsdtar_errc(1, ENOMEM,
|
||||
"Line too long in %s", lr->pathname);
|
||||
lr->buff_end = p + (lr->buff_end - lr->buff);
|
||||
lr->line_end = p + (lr->line_end - lr->buff);
|
||||
lr->line_start = lr->buff = p;
|
||||
}
|
||||
|
||||
/* Get some more data into the buffer. */
|
||||
bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
|
||||
bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
|
||||
lr->buff_end += bytes_read;
|
||||
|
||||
if (ferror(lr->f))
|
||||
bsdtar_errc(1, errno, "Can't read %s", lr->pathname);
|
||||
if (feof(lr->f)) {
|
||||
if (lr->f != stdin)
|
||||
fclose(lr->f);
|
||||
lr->f = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lafe_line_reader_free(struct lafe_line_reader *lr)
|
||||
{
|
||||
free(lr->buff);
|
||||
free(lr->pathname);
|
||||
free(lr);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Joerg Sonnenberger
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef LAFE_LINE_READER_H
|
||||
#define LAFE_LINE_READER_H
|
||||
|
||||
struct lafe_line_reader;
|
||||
|
||||
struct lafe_line_reader *lafe_line_reader(const char *, int nullSeparator);
|
||||
const char *lafe_line_reader_next(struct lafe_line_reader *);
|
||||
void lafe_line_reader_free(struct lafe_line_reader *);
|
||||
|
||||
#endif
|
@ -1,281 +0,0 @@
|
||||
/*-
|
||||
* 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 "bsdtar_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "err.h"
|
||||
#include "line_reader.h"
|
||||
#include "matching.h"
|
||||
#include "pathmatch.h"
|
||||
|
||||
struct match {
|
||||
struct match *next;
|
||||
int matches;
|
||||
char pattern[1];
|
||||
};
|
||||
|
||||
struct lafe_matching {
|
||||
struct match *exclusions;
|
||||
int exclusions_count;
|
||||
struct match *inclusions;
|
||||
int inclusions_count;
|
||||
int inclusions_unmatched_count;
|
||||
};
|
||||
|
||||
static void add_pattern(struct match **list, const char *pattern);
|
||||
static void initialize_matching(struct lafe_matching **);
|
||||
static int match_exclusion(struct match *, const char *pathname);
|
||||
static int match_inclusion(struct match *, const char *pathname);
|
||||
|
||||
/*
|
||||
* The matching logic here needs to be re-thought. I started out to
|
||||
* try to mimic gtar's matching logic, but it's not entirely
|
||||
* consistent. In particular 'tar -t' and 'tar -x' interpret patterns
|
||||
* on the command line as anchored, but --exclude doesn't.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Utility functions to manage exclusion/inclusion patterns
|
||||
*/
|
||||
|
||||
int
|
||||
lafe_exclude(struct lafe_matching **matching, const char *pattern)
|
||||
{
|
||||
|
||||
if (*matching == NULL)
|
||||
initialize_matching(matching);
|
||||
add_pattern(&((*matching)->exclusions), pattern);
|
||||
(*matching)->exclusions_count++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
lafe_exclude_from_file(struct lafe_matching **matching, const char *pathname)
|
||||
{
|
||||
struct lafe_line_reader *lr;
|
||||
const char *p;
|
||||
int ret = 0;
|
||||
|
||||
lr = lafe_line_reader(pathname, 0);
|
||||
while ((p = lafe_line_reader_next(lr)) != NULL) {
|
||||
if (lafe_exclude(matching, p) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
lafe_line_reader_free(lr);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
lafe_include(struct lafe_matching **matching, const char *pattern)
|
||||
{
|
||||
|
||||
if (*matching == NULL)
|
||||
initialize_matching(matching);
|
||||
add_pattern(&((*matching)->inclusions), pattern);
|
||||
(*matching)->inclusions_count++;
|
||||
(*matching)->inclusions_unmatched_count++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
lafe_include_from_file(struct lafe_matching **matching, const char *pathname,
|
||||
int nullSeparator)
|
||||
{
|
||||
struct lafe_line_reader *lr;
|
||||
const char *p;
|
||||
int ret = 0;
|
||||
|
||||
lr = lafe_line_reader(pathname, nullSeparator);
|
||||
while ((p = lafe_line_reader_next(lr)) != NULL) {
|
||||
if (lafe_include(matching, p) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
lafe_line_reader_free(lr);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
add_pattern(struct match **list, const char *pattern)
|
||||
{
|
||||
struct match *match;
|
||||
size_t len;
|
||||
|
||||
len = strlen(pattern);
|
||||
match = malloc(sizeof(*match) + len + 1);
|
||||
if (match == NULL)
|
||||
bsdtar_errc(1, errno, "Out of memory");
|
||||
strcpy(match->pattern, pattern);
|
||||
/* Both "foo/" and "foo" should match "foo/bar". */
|
||||
if (len && match->pattern[len - 1] == '/')
|
||||
match->pattern[strlen(match->pattern)-1] = '\0';
|
||||
match->next = *list;
|
||||
*list = match;
|
||||
match->matches = 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lafe_excluded(struct lafe_matching *matching, const char *pathname)
|
||||
{
|
||||
struct match *match;
|
||||
struct match *matched;
|
||||
|
||||
if (matching == NULL)
|
||||
return (0);
|
||||
|
||||
/* Mark off any unmatched inclusions. */
|
||||
/* In particular, if a filename does appear in the archive and
|
||||
* is explicitly included and excluded, then we don't report
|
||||
* it as missing even though we don't extract it.
|
||||
*/
|
||||
matched = NULL;
|
||||
for (match = matching->inclusions; match != NULL; match = match->next){
|
||||
if (match->matches == 0
|
||||
&& match_inclusion(match, pathname)) {
|
||||
matching->inclusions_unmatched_count--;
|
||||
match->matches++;
|
||||
matched = match;
|
||||
}
|
||||
}
|
||||
|
||||
/* Exclusions take priority */
|
||||
for (match = matching->exclusions; match != NULL; match = match->next){
|
||||
if (match_exclusion(match, pathname))
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* It's not excluded and we found an inclusion above, so it's included. */
|
||||
if (matched != NULL)
|
||||
return (0);
|
||||
|
||||
|
||||
/* We didn't find an unmatched inclusion, check the remaining ones. */
|
||||
for (match = matching->inclusions; match != NULL; match = match->next){
|
||||
/* We looked at previously-unmatched inclusions already. */
|
||||
if (match->matches > 0
|
||||
&& match_inclusion(match, pathname)) {
|
||||
match->matches++;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there were inclusions, default is to exclude. */
|
||||
if (matching->inclusions != NULL)
|
||||
return (1);
|
||||
|
||||
/* No explicit inclusions, default is to match. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a little odd, but it matches the default behavior of
|
||||
* gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
|
||||
*
|
||||
*/
|
||||
static int
|
||||
match_exclusion(struct match *match, const char *pathname)
|
||||
{
|
||||
return (lafe_pathmatch(match->pattern,
|
||||
pathname,
|
||||
PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
|
||||
}
|
||||
|
||||
/*
|
||||
* Again, mimic gtar: inclusions are always anchored (have to match
|
||||
* the beginning of the path) even though exclusions are not anchored.
|
||||
*/
|
||||
static int
|
||||
match_inclusion(struct match *match, const char *pathname)
|
||||
{
|
||||
return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
|
||||
}
|
||||
|
||||
void
|
||||
lafe_cleanup_exclusions(struct lafe_matching **matching)
|
||||
{
|
||||
struct match *p, *q;
|
||||
|
||||
if (*matching == NULL)
|
||||
return;
|
||||
|
||||
for (p = (*matching)->inclusions; p != NULL; ) {
|
||||
q = p;
|
||||
p = p->next;
|
||||
free(q);
|
||||
}
|
||||
|
||||
for (p = (*matching)->exclusions; p != NULL; ) {
|
||||
q = p;
|
||||
p = p->next;
|
||||
free(q);
|
||||
}
|
||||
|
||||
free(*matching);
|
||||
*matching = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_matching(struct lafe_matching **matching)
|
||||
{
|
||||
*matching = calloc(sizeof(**matching), 1);
|
||||
if (*matching == NULL)
|
||||
bsdtar_errc(1, errno, "No memory");
|
||||
}
|
||||
|
||||
int
|
||||
lafe_unmatched_inclusions(struct lafe_matching *matching)
|
||||
{
|
||||
|
||||
if (matching == NULL)
|
||||
return (0);
|
||||
return (matching->inclusions_unmatched_count);
|
||||
}
|
||||
|
||||
int
|
||||
lafe_unmatched_inclusions_warn(struct lafe_matching *matching, const char *msg)
|
||||
{
|
||||
struct match *p;
|
||||
|
||||
if (matching == NULL)
|
||||
return (0);
|
||||
|
||||
for (p = matching->inclusions; p != NULL; p = p->next) {
|
||||
if (p->matches == 0)
|
||||
bsdtar_warnc(0, "%s: %s", p->pattern, msg);
|
||||
}
|
||||
|
||||
return (matching->inclusions_unmatched_count);
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*-
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef MATCHING_H
|
||||
#define MATCHING_H
|
||||
|
||||
struct lafe_matching;
|
||||
|
||||
int lafe_exclude(struct lafe_matching **matching, const char *pattern);
|
||||
int lafe_exclude_from_file(struct lafe_matching **matching,
|
||||
const char *pathname);
|
||||
int lafe_include(struct lafe_matching **matching, const char *pattern);
|
||||
int lafe_include_from_file(struct lafe_matching **matching,
|
||||
const char *pathname, int nullSeparator);
|
||||
|
||||
int lafe_excluded(struct lafe_matching *, const char *pathname);
|
||||
void lafe_cleanup_exclusions(struct lafe_matching **);
|
||||
int lafe_unmatched_inclusions(struct lafe_matching *);
|
||||
int lafe_unmatched_inclusions_warn(struct lafe_matching *, const char *msg);
|
||||
|
||||
#endif
|
@ -1,255 +0,0 @@
|
||||
/*-
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 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 "bsdtar_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "pathmatch.h"
|
||||
|
||||
/*
|
||||
* Check whether a character 'c' is matched by a list specification [...]:
|
||||
* * Leading '!' or '^' negates the class.
|
||||
* * <char>-<char> is a range of characters
|
||||
* * \<char> removes any special meaning for <char>
|
||||
*
|
||||
* Some interesting boundary cases:
|
||||
* a-d-e is one range (a-d) followed by two single characters - and e.
|
||||
* \a-\d is same as a-d
|
||||
* a\-d is three single characters: a, d, -
|
||||
* Trailing - is not special (so [a-] is two characters a and -).
|
||||
* Initial - is not special ([a-] is same as [-a] is same as [\\-a])
|
||||
* This function never sees a trailing \.
|
||||
* [] always fails
|
||||
* [!] always succeeds
|
||||
*/
|
||||
static int
|
||||
pm_list(const char *start, const char *end, const char c, int flags)
|
||||
{
|
||||
const char *p = start;
|
||||
char rangeStart = '\0', nextRangeStart;
|
||||
int match = 1, nomatch = 0;
|
||||
|
||||
/* This will be used soon... */
|
||||
(void)flags; /* UNUSED */
|
||||
|
||||
/* If this is a negated class, return success for nomatch. */
|
||||
if ((*p == '!' || *p == '^') && p < end) {
|
||||
match = 0;
|
||||
nomatch = 1;
|
||||
++p;
|
||||
}
|
||||
|
||||
while (p < end) {
|
||||
nextRangeStart = '\0';
|
||||
switch (*p) {
|
||||
case '-':
|
||||
/* Trailing or initial '-' is not special. */
|
||||
if ((rangeStart == '\0') || (p == end - 1)) {
|
||||
if (*p == c)
|
||||
return (match);
|
||||
} else {
|
||||
char rangeEnd = *++p;
|
||||
if (rangeEnd == '\\')
|
||||
rangeEnd = *++p;
|
||||
if ((rangeStart <= c) && (c <= rangeEnd))
|
||||
return (match);
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
++p;
|
||||
/* Fall through */
|
||||
default:
|
||||
if (*p == c)
|
||||
return (match);
|
||||
nextRangeStart = *p; /* Possible start of range. */
|
||||
}
|
||||
rangeStart = nextRangeStart;
|
||||
++p;
|
||||
}
|
||||
return (nomatch);
|
||||
}
|
||||
|
||||
/*
|
||||
* If s is pointing to "./", ".//", "./././" or the like, skip it.
|
||||
*/
|
||||
static const char *
|
||||
pm_slashskip(const char *s) {
|
||||
while ((*s == '/')
|
||||
|| (s[0] == '.' && s[1] == '/')
|
||||
|| (s[0] == '.' && s[1] == '\0'))
|
||||
++s;
|
||||
return (s);
|
||||
}
|
||||
|
||||
static int
|
||||
pm(const char *p, const char *s, int flags)
|
||||
{
|
||||
const char *end;
|
||||
|
||||
/*
|
||||
* Ignore leading './', './/', '././', etc.
|
||||
*/
|
||||
if (s[0] == '.' && s[1] == '/')
|
||||
s = pm_slashskip(s + 1);
|
||||
if (p[0] == '.' && p[1] == '/')
|
||||
p = pm_slashskip(p + 1);
|
||||
|
||||
for (;;) {
|
||||
switch (*p) {
|
||||
case '\0':
|
||||
if (s[0] == '/') {
|
||||
if (flags & PATHMATCH_NO_ANCHOR_END)
|
||||
return (1);
|
||||
/* "dir" == "dir/" == "dir/." */
|
||||
s = pm_slashskip(s);
|
||||
}
|
||||
return (*s == '\0');
|
||||
case '?':
|
||||
/* ? always succeds, unless we hit end of 's' */
|
||||
if (*s == '\0')
|
||||
return (0);
|
||||
break;
|
||||
case '*':
|
||||
/* "*" == "**" == "***" ... */
|
||||
while (*p == '*')
|
||||
++p;
|
||||
/* Trailing '*' always succeeds. */
|
||||
if (*p == '\0')
|
||||
return (1);
|
||||
while (*s) {
|
||||
if (lafe_pathmatch(p, s, flags))
|
||||
return (1);
|
||||
++s;
|
||||
}
|
||||
return (0);
|
||||
case '[':
|
||||
/*
|
||||
* Find the end of the [...] character class,
|
||||
* ignoring \] that might occur within the class.
|
||||
*/
|
||||
end = p + 1;
|
||||
while (*end != '\0' && *end != ']') {
|
||||
if (*end == '\\' && end[1] != '\0')
|
||||
++end;
|
||||
++end;
|
||||
}
|
||||
if (*end == ']') {
|
||||
/* We found [...], try to match it. */
|
||||
if (!pm_list(p + 1, end, *s, flags))
|
||||
return (0);
|
||||
p = end; /* Jump to trailing ']' char. */
|
||||
break;
|
||||
} else
|
||||
/* No final ']', so just match '['. */
|
||||
if (*p != *s)
|
||||
return (0);
|
||||
break;
|
||||
case '\\':
|
||||
/* Trailing '\\' matches itself. */
|
||||
if (p[1] == '\0') {
|
||||
if (*s != '\\')
|
||||
return (0);
|
||||
} else {
|
||||
++p;
|
||||
if (*p != *s)
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
if (*s != '/' && *s != '\0')
|
||||
return (0);
|
||||
/* Note: pattern "/\./" won't match "/";
|
||||
* pm_slashskip() correctly stops at backslash. */
|
||||
p = pm_slashskip(p);
|
||||
s = pm_slashskip(s);
|
||||
if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END))
|
||||
return (1);
|
||||
--p; /* Counteract the increment below. */
|
||||
--s;
|
||||
break;
|
||||
case '$':
|
||||
/* '$' is special only at end of pattern and only
|
||||
* if PATHMATCH_NO_ANCHOR_END is specified. */
|
||||
if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
|
||||
/* "dir" == "dir/" == "dir/." */
|
||||
return (*pm_slashskip(s) == '\0');
|
||||
}
|
||||
/* Otherwise, '$' is not special. */
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
if (*p != *s)
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main entry point. */
|
||||
int
|
||||
lafe_pathmatch(const char *p, const char *s, int flags)
|
||||
{
|
||||
/* Empty pattern only matches the empty string. */
|
||||
if (p == NULL || *p == '\0')
|
||||
return (s == NULL || *s == '\0');
|
||||
|
||||
/* Leading '^' anchors the start of the pattern. */
|
||||
if (*p == '^') {
|
||||
++p;
|
||||
flags &= ~PATHMATCH_NO_ANCHOR_START;
|
||||
}
|
||||
|
||||
if (*p == '/' && *s != '/')
|
||||
return (0);
|
||||
|
||||
/* Certain patterns and file names anchor implicitly. */
|
||||
if (*p == '*' || *p == '/' || *p == '/') {
|
||||
while (*p == '/')
|
||||
++p;
|
||||
while (*s == '/')
|
||||
++s;
|
||||
return (pm(p, s, flags));
|
||||
}
|
||||
|
||||
/* If start is unanchored, try to match start of each path element. */
|
||||
if (flags & PATHMATCH_NO_ANCHOR_START) {
|
||||
for ( ; s != NULL; s = strchr(s, '/')) {
|
||||
if (*s == '/')
|
||||
s++;
|
||||
if (pm(p, s, flags))
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Default: Match from beginning. */
|
||||
return (pm(p, s, flags));
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*-
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef LAFE_PATHMATCH_H
|
||||
#define LAFE_PATHMATCH_H
|
||||
|
||||
/* Don't anchor at beginning unless the pattern starts with "^" */
|
||||
#define PATHMATCH_NO_ANCHOR_START 1
|
||||
/* Don't anchor at end unless the pattern ends with "$" */
|
||||
#define PATHMATCH_NO_ANCHOR_END 2
|
||||
|
||||
/* Note that "^" and "$" are not special unless you set the corresponding
|
||||
* flag above. */
|
||||
|
||||
int lafe_pathmatch(const char *p, const char *s, int flags);
|
||||
|
||||
#endif
|
@ -23,7 +23,7 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "bsdtar_platform.h"
|
||||
#include "lafe_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
@ -160,11 +160,11 @@ read_archive(struct bsdtar *bsdtar, char mode)
|
||||
archive_read_support_compression_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
|
||||
bsdtar_errc(1, 0, "%s", archive_error_string(a));
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
if (archive_read_open_file(a, bsdtar->filename,
|
||||
bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
|
||||
DEFAULT_BYTES_PER_BLOCK))
|
||||
bsdtar_errc(1, 0, "Error opening archive: %s",
|
||||
lafe_errc(1, 0, "Error opening archive: %s",
|
||||
archive_error_string(a));
|
||||
|
||||
do_chdir(bsdtar);
|
||||
@ -180,9 +180,9 @@ read_archive(struct bsdtar *bsdtar, char mode)
|
||||
if (mode == 'x' && bsdtar->option_chroot) {
|
||||
#if HAVE_CHROOT
|
||||
if (chroot(".") != 0)
|
||||
bsdtar_errc(1, errno, "Can't chroot to \".\"");
|
||||
lafe_errc(1, errno, "Can't chroot to \".\"");
|
||||
#else
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"chroot isn't supported on this platform");
|
||||
#endif
|
||||
}
|
||||
@ -198,12 +198,12 @@ read_archive(struct bsdtar *bsdtar, char mode)
|
||||
if (r == ARCHIVE_EOF)
|
||||
break;
|
||||
if (r < ARCHIVE_OK)
|
||||
bsdtar_warnc(0, "%s", archive_error_string(a));
|
||||
lafe_warnc(0, "%s", archive_error_string(a));
|
||||
if (r <= ARCHIVE_WARN)
|
||||
bsdtar->return_value = 1;
|
||||
if (r == ARCHIVE_RETRY) {
|
||||
/* Retryable error: try again */
|
||||
bsdtar_warnc(0, "Retrying...");
|
||||
lafe_warnc(0, "Retrying...");
|
||||
continue;
|
||||
}
|
||||
if (r == ARCHIVE_FATAL)
|
||||
@ -267,17 +267,17 @@ read_archive(struct bsdtar *bsdtar, char mode)
|
||||
r = archive_read_data_skip(a);
|
||||
if (r == ARCHIVE_WARN) {
|
||||
fprintf(out, "\n");
|
||||
bsdtar_warnc(0, "%s",
|
||||
lafe_warnc(0, "%s",
|
||||
archive_error_string(a));
|
||||
}
|
||||
if (r == ARCHIVE_RETRY) {
|
||||
fprintf(out, "\n");
|
||||
bsdtar_warnc(0, "%s",
|
||||
lafe_warnc(0, "%s",
|
||||
archive_error_string(a));
|
||||
}
|
||||
if (r == ARCHIVE_FATAL) {
|
||||
fprintf(out, "\n");
|
||||
bsdtar_warnc(0, "%s",
|
||||
lafe_warnc(0, "%s",
|
||||
archive_error_string(a));
|
||||
bsdtar->return_value = 1;
|
||||
break;
|
||||
@ -329,7 +329,7 @@ read_archive(struct bsdtar *bsdtar, char mode)
|
||||
|
||||
r = archive_read_close(a);
|
||||
if (r != ARCHIVE_OK)
|
||||
bsdtar_warnc(0, "%s", archive_error_string(a));
|
||||
lafe_warnc(0, "%s", archive_error_string(a));
|
||||
if (r <= ARCHIVE_WARN)
|
||||
bsdtar->return_value = 1;
|
||||
|
||||
|
@ -58,7 +58,7 @@ init_substitution(struct bsdtar *bsdtar)
|
||||
|
||||
bsdtar->substitution = subst = malloc(sizeof(*subst));
|
||||
if (subst == NULL)
|
||||
bsdtar_errc(1, errno, "Out of memory");
|
||||
lafe_errc(1, errno, "Out of memory");
|
||||
subst->first_rule = subst->last_rule = NULL;
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text)
|
||||
|
||||
rule = malloc(sizeof(*rule));
|
||||
if (rule == NULL)
|
||||
bsdtar_errc(1, errno, "Out of memory");
|
||||
lafe_errc(1, errno, "Out of memory");
|
||||
rule->next = NULL;
|
||||
|
||||
if (subst->last_rule == NULL)
|
||||
@ -88,32 +88,32 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text)
|
||||
subst->last_rule = rule;
|
||||
|
||||
if (*rule_text == '\0')
|
||||
bsdtar_errc(1, 0, "Empty replacement string");
|
||||
lafe_errc(1, 0, "Empty replacement string");
|
||||
end_pattern = strchr(rule_text + 1, *rule_text);
|
||||
if (end_pattern == NULL)
|
||||
bsdtar_errc(1, 0, "Invalid replacement string");
|
||||
lafe_errc(1, 0, "Invalid replacement string");
|
||||
|
||||
pattern = malloc(end_pattern - rule_text);
|
||||
if (pattern == NULL)
|
||||
bsdtar_errc(1, errno, "Out of memory");
|
||||
lafe_errc(1, errno, "Out of memory");
|
||||
memcpy(pattern, rule_text + 1, end_pattern - rule_text - 1);
|
||||
pattern[end_pattern - rule_text - 1] = '\0';
|
||||
|
||||
if ((r = regcomp(&rule->re, pattern, REG_BASIC)) != 0) {
|
||||
char buf[80];
|
||||
regerror(r, &rule->re, buf, sizeof(buf));
|
||||
bsdtar_errc(1, 0, "Invalid regular expression: %s", buf);
|
||||
lafe_errc(1, 0, "Invalid regular expression: %s", buf);
|
||||
}
|
||||
free(pattern);
|
||||
|
||||
start_subst = end_pattern + 1;
|
||||
end_pattern = strchr(start_subst, *rule_text);
|
||||
if (end_pattern == NULL)
|
||||
bsdtar_errc(1, 0, "Invalid replacement string");
|
||||
lafe_errc(1, 0, "Invalid replacement string");
|
||||
|
||||
rule->result = malloc(end_pattern - start_subst + 1);
|
||||
if (rule->result == NULL)
|
||||
bsdtar_errc(1, errno, "Out of memory");
|
||||
lafe_errc(1, errno, "Out of memory");
|
||||
memcpy(rule->result, start_subst, end_pattern - start_subst);
|
||||
rule->result[end_pattern - start_subst] = '\0';
|
||||
|
||||
@ -136,7 +136,7 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text)
|
||||
rule->symlink = 1;
|
||||
break;
|
||||
default:
|
||||
bsdtar_errc(1, 0, "Invalid replacement flag %c", *end_pattern);
|
||||
lafe_errc(1, 0, "Invalid replacement flag %c", *end_pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -154,7 +154,7 @@ realloc_strncat(char **str, const char *append, size_t len)
|
||||
|
||||
new_str = malloc(old_len + len + 1);
|
||||
if (new_str == NULL)
|
||||
bsdtar_errc(1, errno, "Out of memory");
|
||||
lafe_errc(1, errno, "Out of memory");
|
||||
memcpy(new_str, *str, old_len);
|
||||
memcpy(new_str + old_len, append, len);
|
||||
new_str[old_len + len] = '\0';
|
||||
@ -175,7 +175,7 @@ realloc_strcat(char **str, const char *append)
|
||||
|
||||
new_str = malloc(old_len + strlen(append) + 1);
|
||||
if (new_str == NULL)
|
||||
bsdtar_errc(1, errno, "Out of memory");
|
||||
lafe_errc(1, errno, "Out of memory");
|
||||
memcpy(new_str, *str, old_len);
|
||||
strcpy(new_str + old_len, append);
|
||||
free(*str);
|
||||
|
@ -6,16 +6,18 @@ TAR_SRCDIR=${.CURDIR}/..
|
||||
|
||||
# Some tar sources are pulled in for white-box tests
|
||||
TAR_SRCS= \
|
||||
../getdate.c
|
||||
getdate.c
|
||||
|
||||
TESTS= \
|
||||
test_0.c \
|
||||
test_basic.c \
|
||||
test_copy.c \
|
||||
test_empty_mtree.c \
|
||||
test_getdate.c \
|
||||
test_help.c \
|
||||
test_option_T.c \
|
||||
test_option_T_upper.c \
|
||||
test_option_q.c \
|
||||
test_option_r.c \
|
||||
test_option_s.c \
|
||||
test_patterns.c \
|
||||
test_stdio.c \
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,37 +45,82 @@
|
||||
#error Oops: No config.h and no pre-built configuration in test.h.
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#include <dirent.h>
|
||||
#else
|
||||
#define dirent direct
|
||||
#include "../bsdtar_windows.h"
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h> /* Windows requires this before sys/stat.h */
|
||||
#include <sys/stat.h>
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef USE_DMALLOC
|
||||
#include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h> /* For __FBSDID */
|
||||
#else
|
||||
/* Some non-FreeBSD platforms such as newlib-derived ones like
|
||||
* cygwin, have __FBSDID, so this definition must be guarded.
|
||||
*/
|
||||
#ifndef __FBSDID
|
||||
#define __FBSDID(a) /* null */
|
||||
#if HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIRECT_H
|
||||
#include <direct.h>
|
||||
#define dirent direct
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_IO_H
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* System-specific tweaks. We really want to minimize these
|
||||
* as much as possible, since they make it harder to understand
|
||||
* the mainline code.
|
||||
*/
|
||||
|
||||
/* Windows (including Visual Studio and MinGW but not Cygwin) */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include "../bsdtar_windows.h"
|
||||
#if !defined(__BORLANDC__)
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
#define LOCALE_DE "deu"
|
||||
#else
|
||||
#define LOCALE_DE "de_DE.UTF-8"
|
||||
#endif
|
||||
|
||||
/* Visual Studio */
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
/* Cygwin */
|
||||
#if defined(__CYGWIN__)
|
||||
/* Cygwin-1.7.x is lazy about populating nlinks, so don't
|
||||
* expect it to be accurate. */
|
||||
# define NLINKS_INACCURATE_FOR_DIRS
|
||||
#endif
|
||||
|
||||
#if defined(__HAIKU__) || defined(__QNXNTO__)
|
||||
/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Get a real definition for __FBSDID if we can */
|
||||
#if HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
|
||||
/* If not, define it so as to avoid dangling semicolons. */
|
||||
#ifndef __FBSDID
|
||||
#define __FBSDID(a) struct _undefined_hack
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -85,41 +130,83 @@
|
||||
#define DEFINE_TEST(name) void name(void); void name(void)
|
||||
|
||||
/* An implementation of the standard assert() macro */
|
||||
#define assert(e) test_assert(__FILE__, __LINE__, (e), #e, NULL)
|
||||
|
||||
#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
|
||||
/* chdir() and error if it fails */
|
||||
#define assertChdir(path) \
|
||||
assertion_chdir(__FILE__, __LINE__, path)
|
||||
/* Assert two integers are the same. Reports value of each one if not. */
|
||||
#define assertEqualInt(v1,v2) \
|
||||
test_assert_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
|
||||
|
||||
#define assertEqualInt(v1,v2) \
|
||||
assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
|
||||
/* Assert two strings are the same. Reports value of each one if not. */
|
||||
#define assertEqualString(v1,v2) \
|
||||
test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
|
||||
assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
|
||||
/* As above, but v1 and v2 are wchar_t * */
|
||||
#define assertEqualWString(v1,v2) \
|
||||
test_assert_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
|
||||
assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
|
||||
/* As above, but raw blocks of bytes. */
|
||||
#define assertEqualMem(v1, v2, l) \
|
||||
test_assert_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
|
||||
assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
|
||||
/* Assert two files are the same; allow printf-style expansion of second name.
|
||||
* See below for comments about variable arguments here...
|
||||
*/
|
||||
#define assertEqualFile \
|
||||
test_setup(__FILE__, __LINE__);test_assert_equal_file
|
||||
assertion_setup(__FILE__, __LINE__);assertion_equal_file
|
||||
/* Assert that a file is empty; supports printf-style arguments. */
|
||||
#define assertEmptyFile \
|
||||
test_setup(__FILE__, __LINE__);test_assert_empty_file
|
||||
assertion_setup(__FILE__, __LINE__);assertion_empty_file
|
||||
/* Assert that a file is not empty; supports printf-style arguments. */
|
||||
#define assertNonEmptyFile \
|
||||
test_setup(__FILE__, __LINE__);test_assert_non_empty_file
|
||||
assertion_setup(__FILE__, __LINE__);assertion_non_empty_file
|
||||
#define assertFileAtime(pathname, sec, nsec) \
|
||||
assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
|
||||
#define assertFileAtimeRecent(pathname) \
|
||||
assertion_file_atime_recent(__FILE__, __LINE__, pathname)
|
||||
#define assertFileBirthtime(pathname, sec, nsec) \
|
||||
assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
|
||||
#define assertFileBirthtimeRecent(pathname) \
|
||||
assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
|
||||
/* Assert that a file exists; supports printf-style arguments. */
|
||||
#define assertFileExists \
|
||||
test_setup(__FILE__, __LINE__);test_assert_file_exists
|
||||
assertion_setup(__FILE__, __LINE__);assertion_file_exists
|
||||
/* Assert that a file exists; supports printf-style arguments. */
|
||||
#define assertFileNotExists \
|
||||
test_setup(__FILE__, __LINE__);test_assert_file_not_exists
|
||||
assertion_setup(__FILE__, __LINE__);assertion_file_not_exists
|
||||
/* Assert that file contents match a string; supports printf-style arguments. */
|
||||
#define assertFileContents \
|
||||
test_setup(__FILE__, __LINE__);test_assert_file_contents
|
||||
assertion_setup(__FILE__, __LINE__);assertion_file_contents
|
||||
#define assertFileMtime(pathname, sec, nsec) \
|
||||
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
|
||||
#define assertFileMtimeRecent(pathname) \
|
||||
assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
|
||||
#define assertFileNLinks(pathname, nlinks) \
|
||||
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
|
||||
#define assertFileSize(pathname, size) \
|
||||
assertion_file_size(__FILE__, __LINE__, pathname, size)
|
||||
#define assertTextFileContents \
|
||||
assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
|
||||
#define assertFileContainsLinesAnyOrder(pathname, lines) \
|
||||
assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
|
||||
#define assertIsDir(pathname, mode) \
|
||||
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
|
||||
#define assertIsHardlink(path1, path2) \
|
||||
assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
|
||||
#define assertIsNotHardlink(path1, path2) \
|
||||
assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
|
||||
#define assertIsReg(pathname, mode) \
|
||||
assertion_is_reg(__FILE__, __LINE__, pathname, mode)
|
||||
#define assertIsSymlink(pathname, contents) \
|
||||
assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
|
||||
/* Create a directory, report error if it fails. */
|
||||
#define assertMakeDir(dirname, mode) \
|
||||
assertion_make_dir(__FILE__, __LINE__, dirname, mode)
|
||||
#define assertMakeFile(path, mode, contents) \
|
||||
assertion_make_file(__FILE__, __LINE__, path, mode, contents)
|
||||
#define assertMakeHardlink(newfile, oldfile) \
|
||||
assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
|
||||
#define assertMakeSymlink(newfile, linkto) \
|
||||
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
|
||||
#define assertUmask(mask) \
|
||||
assertion_umask(__FILE__, __LINE__, mask)
|
||||
|
||||
/*
|
||||
* This would be simple with C99 variadic macros, but I don't want to
|
||||
@ -128,27 +215,61 @@
|
||||
* but effective.
|
||||
*/
|
||||
#define skipping \
|
||||
test_setup(__FILE__, __LINE__);test_skipping
|
||||
assertion_setup(__FILE__, __LINE__);test_skipping
|
||||
|
||||
/* Function declarations. These are defined in test_utility.c. */
|
||||
void failure(const char *fmt, ...);
|
||||
void test_setup(const char *, int);
|
||||
int assertion_assert(const char *, int, int, const char *, void *);
|
||||
int assertion_chdir(const char *, int, const char *);
|
||||
int assertion_empty_file(const char *, ...);
|
||||
int assertion_equal_file(const char *, const char *, ...);
|
||||
int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
|
||||
int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
|
||||
int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
|
||||
int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
|
||||
int assertion_file_atime(const char *, int, const char *, long, long);
|
||||
int assertion_file_atime_recent(const char *, int, const char *);
|
||||
int assertion_file_birthtime(const char *, int, const char *, long, long);
|
||||
int assertion_file_birthtime_recent(const char *, int, const char *);
|
||||
int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
|
||||
int assertion_file_contents(const void *, int, const char *, ...);
|
||||
int assertion_file_exists(const char *, ...);
|
||||
int assertion_file_mtime(const char *, int, const char *, long, long);
|
||||
int assertion_file_mtime_recent(const char *, int, const char *);
|
||||
int assertion_file_nlinks(const char *, int, const char *, int);
|
||||
int assertion_file_not_exists(const char *, ...);
|
||||
int assertion_file_size(const char *, int, const char *, long);
|
||||
int assertion_is_dir(const char *, int, const char *, int);
|
||||
int assertion_is_hardlink(const char *, int, const char *, const char *);
|
||||
int assertion_is_not_hardlink(const char *, int, const char *, const char *);
|
||||
int assertion_is_reg(const char *, int, const char *, int);
|
||||
int assertion_is_symlink(const char *, int, const char *, const char *);
|
||||
int assertion_make_dir(const char *, int, const char *, int);
|
||||
int assertion_make_file(const char *, int, const char *, int, const char *);
|
||||
int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
|
||||
int assertion_make_symlink(const char *, int, const char *newpath, const char *);
|
||||
int assertion_non_empty_file(const char *, ...);
|
||||
int assertion_text_file_contents(const char *buff, const char *f);
|
||||
int assertion_umask(const char *, int, int);
|
||||
void assertion_setup(const char *, int);
|
||||
|
||||
void test_skipping(const char *fmt, ...);
|
||||
int test_assert(const char *, int, int, const char *, void *);
|
||||
int test_assert_empty_file(const char *, ...);
|
||||
int test_assert_non_empty_file(const char *, ...);
|
||||
int test_assert_equal_file(const char *, const char *, ...);
|
||||
int test_assert_equal_int(const char *, int, int, const char *, int, const char *, void *);
|
||||
int test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
|
||||
int test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
|
||||
int test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *);
|
||||
int test_assert_file_contents(const void *, int, const char *, ...);
|
||||
int test_assert_file_exists(const char *, ...);
|
||||
int test_assert_file_not_exists(const char *, ...);
|
||||
|
||||
/* Like sprintf, then system() */
|
||||
int systemf(const char * fmt, ...);
|
||||
|
||||
/* Delay until time() returns a value after this. */
|
||||
void sleepUntilAfter(time_t);
|
||||
|
||||
/* Return true if this platform can create symlinks. */
|
||||
int canSymlink(void);
|
||||
|
||||
/* Return true if this platform can run the "gzip" program. */
|
||||
int canGzip(void);
|
||||
|
||||
/* Return true if this platform can run the "gunzip" program. */
|
||||
int canGunzip(void);
|
||||
|
||||
/* Suck file into string allocated via malloc(). Call free() when done. */
|
||||
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
|
||||
char *slurpfile(size_t *, const char *fmt, ...);
|
||||
@ -161,4 +282,7 @@ void extract_reference_file(const char *);
|
||||
*/
|
||||
|
||||
/* Pathname of exe to be tested. */
|
||||
const char *testprogfile;
|
||||
/* Name of exe to use in printf-formatted command strings. */
|
||||
/* On Windows, this includes leading/trailing quotes. */
|
||||
const char *testprog;
|
||||
|
@ -40,7 +40,7 @@ DEFINE_TEST(test_0)
|
||||
struct stat st;
|
||||
|
||||
failure("File %s does not exist?!", testprog);
|
||||
if (!assertEqualInt(0, stat(testprog, &st)))
|
||||
if (!assertEqualInt(0, stat(testprogfile, &st)))
|
||||
exit(1);
|
||||
|
||||
failure("%s is not executable?!", testprog);
|
||||
|
@ -30,24 +30,16 @@ static void
|
||||
basic_tar(const char *target, const char *pack_options,
|
||||
const char *unpack_options, const char *flist)
|
||||
{
|
||||
struct stat st, st2;
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
char buff[128];
|
||||
#endif
|
||||
int r;
|
||||
|
||||
assertEqualInt(0, mkdir(target, 0775));
|
||||
assertMakeDir(target, 0775);
|
||||
|
||||
/* Use the tar program to create an archive. */
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
r = systemf("%s cf - %s `cat %s` >%s/archive 2>%s/pack.err", testprog, pack_options, flist, target, target);
|
||||
#else
|
||||
r = systemf("%s cf - %s %s >%s/archive 2>%s/pack.err", testprog, pack_options, flist, target, target);
|
||||
#endif
|
||||
failure("Error invoking %s cf -", testprog, pack_options);
|
||||
assertEqualInt(r, 0);
|
||||
|
||||
chdir(target);
|
||||
assertChdir(target);
|
||||
|
||||
/* Verify that nothing went to stderr. */
|
||||
assertEmptyFile("pack.err");
|
||||
@ -67,119 +59,57 @@ basic_tar(const char *target, const char *pack_options,
|
||||
*/
|
||||
|
||||
/* Regular file with 2 links. */
|
||||
r = lstat("file", &st);
|
||||
failure("Failed to stat file %s/file, errno=%d", target, errno);
|
||||
assertEqualInt(r, 0);
|
||||
if (r == 0) {
|
||||
assert(S_ISREG(st.st_mode));
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
assertEqualInt(0644, st.st_mode & 0777);
|
||||
#else
|
||||
assertEqualInt(0600, st.st_mode & 0700);
|
||||
#endif
|
||||
assertEqualInt(10, st.st_size);
|
||||
failure("file %s/file", target);
|
||||
assertEqualInt(2, st.st_nlink);
|
||||
}
|
||||
assertIsReg("file", -1);
|
||||
assertFileSize("file", 10);
|
||||
failure("%s", target);
|
||||
assertFileNLinks("file", 2);
|
||||
|
||||
/* Another name for the same file. */
|
||||
r = lstat("linkfile", &st2);
|
||||
failure("Failed to stat file %s/linkfile, errno=%d", target, errno);
|
||||
assertEqualInt(r, 0);
|
||||
if (r == 0) {
|
||||
assert(S_ISREG(st2.st_mode));
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
assertEqualInt(0644, st2.st_mode & 0777);
|
||||
#else
|
||||
assertEqualInt(0600, st2.st_mode & 0700);
|
||||
#endif
|
||||
assertEqualInt(10, st2.st_size);
|
||||
failure("file %s/linkfile", target);
|
||||
assertEqualInt(2, st2.st_nlink);
|
||||
/* Verify that the two are really hardlinked. */
|
||||
assertEqualInt(st.st_dev, st2.st_dev);
|
||||
failure("%s/linkfile and %s/file aren't really hardlinks", target, target);
|
||||
assertEqualInt(st.st_ino, st2.st_ino);
|
||||
}
|
||||
assertIsReg("linkfile", -1);
|
||||
assertFileSize("linkfile", 10);
|
||||
assertFileNLinks("linkfile", 2);
|
||||
assertIsHardlink("file", "linkfile");
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
/* Symlink */
|
||||
r = lstat("symlink", &st);
|
||||
failure("Failed to stat file %s/symlink, errno=%d", target, errno);
|
||||
assertEqualInt(r, 0);
|
||||
if (r == 0) {
|
||||
failure("symlink should be a symlink; actual mode is %o",
|
||||
st.st_mode);
|
||||
assert(S_ISLNK(st.st_mode));
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
r = readlink("symlink", buff, sizeof(buff));
|
||||
assertEqualInt(r, 4);
|
||||
buff[r] = '\0';
|
||||
assertEqualString(buff, "file");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (canSymlink())
|
||||
assertIsSymlink("symlink", "file");
|
||||
|
||||
/* dir */
|
||||
r = lstat("dir", &st);
|
||||
if (r == 0) {
|
||||
assertEqualInt(r, 0);
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
assertEqualInt(0775, st.st_mode & 0777);
|
||||
#else
|
||||
assertEqualInt(0700, st.st_mode & 0700);
|
||||
#endif
|
||||
}
|
||||
|
||||
chdir("..");
|
||||
assertIsDir("dir", 0775);
|
||||
assertChdir("..");
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_basic)
|
||||
{
|
||||
int fd;
|
||||
int filelist;
|
||||
int oldumask;
|
||||
FILE *f;
|
||||
const char *flist;
|
||||
|
||||
oldumask = umask(0);
|
||||
|
||||
/*
|
||||
* Create an assortment of files on disk.
|
||||
*/
|
||||
filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
|
||||
assertUmask(0);
|
||||
|
||||
/* File with 10 bytes content. */
|
||||
fd = open("file", O_CREAT | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
assertEqualInt(10, write(fd, "123456789", 10));
|
||||
close(fd);
|
||||
write(filelist, "file\n", 5);
|
||||
f = fopen("file", "wb");
|
||||
assert(f != NULL);
|
||||
assertEqualInt(10, fwrite("123456789", 1, 10, f));
|
||||
fclose(f);
|
||||
|
||||
/* hardlink to above file. */
|
||||
assertEqualInt(0, link("file", "linkfile"));
|
||||
write(filelist, "linkfile\n", 9);
|
||||
assertMakeHardlink("linkfile", "file");
|
||||
assertIsHardlink("file", "linkfile");
|
||||
|
||||
/* Symlink to above file. */
|
||||
assertEqualInt(0, symlink("file", "symlink"));
|
||||
write(filelist, "symlink\n", 8);
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("symlink", "file");
|
||||
|
||||
/* Directory. */
|
||||
assertEqualInt(0, mkdir("dir", 0775));
|
||||
write(filelist, "dir\n", 4);
|
||||
/* All done. */
|
||||
close(filelist);
|
||||
assertMakeDir("dir", 0775);
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
flist = "filelist";
|
||||
#else
|
||||
flist = "file linkfile symlink dir";
|
||||
#endif
|
||||
if (canSymlink())
|
||||
flist = "file linkfile symlink dir";
|
||||
else
|
||||
flist = "file linkfile dir";
|
||||
/* Archive/dearchive with a variety of options. */
|
||||
basic_tar("copy", "", "", flist);
|
||||
/* tar doesn't handle cpio symlinks correctly */
|
||||
/* basic_tar("copy_odc", "--format=odc", ""); */
|
||||
basic_tar("copy_ustar", "--format=ustar", "", flist);
|
||||
|
||||
umask(oldumask);
|
||||
}
|
||||
|
@ -25,7 +25,108 @@
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#define LOOP_MAX 170
|
||||
#if defined(__CYGWIN__)
|
||||
# include <limits.h>
|
||||
# include <sys/cygwin.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Try to figure out how deep we can go in our tests. Assumes that
|
||||
* the first call to this function has the longest starting cwd (which
|
||||
* is currently "<testdir>/original"). This is mostly to work around
|
||||
* limits in our Win32 support.
|
||||
*
|
||||
* Background: On Posix systems, PATH_MAX is merely a limit on the
|
||||
* length of the string passed into a system call. By repeatedly
|
||||
* calling chdir(), you can work with arbitrarily long paths on such
|
||||
* systems. In contrast, Win32 APIs apply PATH_MAX limits to the full
|
||||
* absolute path, so the permissible length of a system call argument
|
||||
* varies with the cwd. Some APIs actually enforce limits
|
||||
* significantly less than PATH_MAX to ensure that you can create
|
||||
* files within the current working directory. The Win32 limits also
|
||||
* apply to Cygwin before 1.7.
|
||||
*
|
||||
* Someday, I want to convert the Win32 support to use newer
|
||||
* wide-character paths with '\\?\' prefix, which has a 32k PATH_MAX
|
||||
* instead of the rather anemic 260 character limit of the older
|
||||
* system calls. Then we can drop this mess (unless we want to
|
||||
* continue to special-case Cygwin 1.5 and earlier).
|
||||
*/
|
||||
static int
|
||||
compute_loop_max(void)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
static int LOOP_MAX = 0;
|
||||
char buf[MAX_PATH];
|
||||
size_t cwdlen;
|
||||
|
||||
if (LOOP_MAX == 0) {
|
||||
assert(_getcwd(buf, MAX_PATH) != NULL);
|
||||
cwdlen = strlen(buf);
|
||||
/* 12 characters = length of 8.3 filename */
|
||||
/* 4 characters = length of "/../" used in symlink tests */
|
||||
/* 1 character = length of extra "/" separator */
|
||||
LOOP_MAX = MAX_PATH - (int)cwdlen - 12 - 4 - 1;
|
||||
}
|
||||
return LOOP_MAX;
|
||||
#elif defined(__CYGWIN__) && !defined(HAVE_CYGWIN_CONV_PATH)
|
||||
static int LOOP_MAX = 0;
|
||||
if (LOOP_MAX == 0) {
|
||||
char wbuf[PATH_MAX];
|
||||
char pbuf[PATH_MAX];
|
||||
size_t wcwdlen;
|
||||
size_t pcwdlen;
|
||||
size_t cwdlen;
|
||||
assert(getcwd(pbuf, PATH_MAX) != NULL);
|
||||
pcwdlen = strlen(pbuf);
|
||||
cygwin_conv_to_full_win32_path(pbuf, wbuf);
|
||||
wcwdlen = strlen(wbuf);
|
||||
cwdlen = ((wcwdlen > pcwdlen) ? wcwdlen : pcwdlen);
|
||||
/* Cygwin helper needs an extra few characters. */
|
||||
LOOP_MAX = PATH_MAX - (int)cwdlen - 12 - 4 - 4;
|
||||
}
|
||||
return LOOP_MAX;
|
||||
#else
|
||||
/* cygwin-1.7 ends up here, along with "normal" unix */
|
||||
return 200; /* restore pre-r278 depth */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* filenames[i] is a distinctive filename of length i. */
|
||||
/* To simplify interpreting failures, each filename ends with a
|
||||
* decimal integer which is the length of the filename. E.g., A
|
||||
* filename ending in "_92" is 92 characters long. To detect errors
|
||||
* which drop or misplace characters, the filenames use a repeating
|
||||
* "abcdefghijklmnopqrstuvwxyz..." pattern. */
|
||||
static char *filenames[201];
|
||||
|
||||
static void
|
||||
compute_filenames(void)
|
||||
{
|
||||
char buff[250];
|
||||
size_t i,j;
|
||||
|
||||
filenames[0] = strdup("");
|
||||
filenames[1] = strdup("1");
|
||||
filenames[2] = strdup("a2");
|
||||
for (i = 3; i < sizeof(filenames)/sizeof(filenames[0]); ++i) {
|
||||
/* Fill with "abcdefghij..." */
|
||||
for (j = 0; j < i; ++j)
|
||||
buff[j] = 'a' + (j % 26);
|
||||
buff[j--] = '\0';
|
||||
/* Work from the end to fill in the number portion. */
|
||||
buff[j--] = '0' + (i % 10);
|
||||
if (i > 9) {
|
||||
buff[j--] = '0' + ((i / 10) % 10);
|
||||
if (i > 99)
|
||||
buff[j--] = '0' + (i / 100);
|
||||
}
|
||||
buff[j] = '_';
|
||||
/* Guard against obvious screwups in the above code. */
|
||||
assertEqualInt(strlen(buff), i);
|
||||
filenames[i] = strdup(buff);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_tree(void)
|
||||
@ -33,217 +134,145 @@ create_tree(void)
|
||||
char buff[260];
|
||||
char buff2[260];
|
||||
int i;
|
||||
int fd;
|
||||
int LOOP_MAX;
|
||||
|
||||
assertEqualInt(0, mkdir("original", 0775));
|
||||
chdir("original");
|
||||
assertEqualInt(0, mkdir("f", 0775));
|
||||
assertEqualInt(0, mkdir("l", 0775));
|
||||
assertEqualInt(0, mkdir("m", 0775));
|
||||
assertEqualInt(0, mkdir("s", 0775));
|
||||
assertEqualInt(0, mkdir("d", 0775));
|
||||
compute_filenames();
|
||||
|
||||
for (i = 0; i < LOOP_MAX; i++) {
|
||||
buff[0] = 'f';
|
||||
buff[1] = '/';
|
||||
/* Create a file named "f/abcdef..." */
|
||||
buff[i + 2] = 'a' + (i % 26);
|
||||
buff[i + 3] = '\0';
|
||||
fd = open(buff, O_CREAT | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
assertEqualInt(i + 3, write(fd, buff, strlen(buff)));
|
||||
close(fd);
|
||||
|
||||
/* Create a link named "l/abcdef..." to the above. */
|
||||
strcpy(buff2, buff);
|
||||
buff2[0] = 'l';
|
||||
assertEqualInt(0, link(buff, buff2));
|
||||
|
||||
/* Create a link named "m/abcdef..." to the above. */
|
||||
strcpy(buff2, buff);
|
||||
buff2[0] = 'm';
|
||||
assertEqualInt(0, link(buff, buff2));
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
/* Create a symlink named "s/abcdef..." to the above. */
|
||||
strcpy(buff2 + 3, buff);
|
||||
buff[0] = 's';
|
||||
buff2[0] = '.';
|
||||
buff2[1] = '.';
|
||||
buff2[2] = '/';
|
||||
assertEqualInt(0, symlink(buff2, buff));
|
||||
#else
|
||||
skipping("create a symlink to the above");
|
||||
#endif
|
||||
/* Create a dir named "d/abcdef...". */
|
||||
buff[0] = 'd';
|
||||
assertEqualInt(0, mkdir(buff, 0775));
|
||||
/* Log that we'll be omitting some checks. */
|
||||
if (!canSymlink()) {
|
||||
skipping("Symlink checks");
|
||||
}
|
||||
|
||||
chdir("..");
|
||||
assertMakeDir("original", 0775);
|
||||
assertEqualInt(0, chdir("original"));
|
||||
LOOP_MAX = compute_loop_max();
|
||||
|
||||
assertMakeDir("f", 0775);
|
||||
assertMakeDir("l", 0775);
|
||||
assertMakeDir("m", 0775);
|
||||
assertMakeDir("s", 0775);
|
||||
assertMakeDir("d", 0775);
|
||||
|
||||
for (i = 1; i < LOOP_MAX; i++) {
|
||||
failure("Internal sanity check failed: i = %d", i);
|
||||
assert(filenames[i] != NULL);
|
||||
|
||||
sprintf(buff, "f/%s", filenames[i]);
|
||||
assertMakeFile(buff, 0777, buff);
|
||||
|
||||
/* Create a link named "l/abcdef..." to the above. */
|
||||
sprintf(buff2, "l/%s", filenames[i]);
|
||||
assertMakeHardlink(buff2, buff);
|
||||
|
||||
/* Create a link named "m/abcdef..." to the above. */
|
||||
sprintf(buff2, "m/%s", filenames[i]);
|
||||
assertMakeHardlink(buff2, buff);
|
||||
|
||||
if (canSymlink()) {
|
||||
/* Create a symlink named "s/abcdef..." to the above. */
|
||||
sprintf(buff, "s/%s", filenames[i]);
|
||||
sprintf(buff2, "../f/%s", filenames[i]);
|
||||
failure("buff=\"%s\" buff2=\"%s\"", buff, buff2);
|
||||
assertMakeSymlink(buff, buff2);
|
||||
}
|
||||
/* Create a dir named "d/abcdef...". */
|
||||
buff[0] = 'd';
|
||||
failure("buff=\"%s\"", buff);
|
||||
assertMakeDir(buff, 0775);
|
||||
}
|
||||
|
||||
assertEqualInt(0, chdir(".."));
|
||||
}
|
||||
|
||||
#define LIMIT_NONE 0
|
||||
#define LIMIT_USTAR 1
|
||||
#define LIMIT_NONE 200
|
||||
#define LIMIT_USTAR 100
|
||||
|
||||
static void
|
||||
verify_tree(int limit)
|
||||
verify_tree(size_t limit)
|
||||
{
|
||||
struct stat st, st2;
|
||||
char filename[260];
|
||||
char name1[260];
|
||||
char name2[260];
|
||||
char contents[260];
|
||||
int i, j, r;
|
||||
int fd;
|
||||
int len;
|
||||
const char *p, *dp;
|
||||
DIR *d;
|
||||
struct dirent *de;
|
||||
size_t i, LOOP_MAX;
|
||||
|
||||
LOOP_MAX = compute_loop_max();
|
||||
|
||||
/* Generate the names we know should be there and verify them. */
|
||||
for (i = 1; i < LOOP_MAX; i++) {
|
||||
/* Generate a base name of the correct length. */
|
||||
for (j = 0; j < i; ++j)
|
||||
filename[j] = 'a' + (j % 26);
|
||||
#if 0
|
||||
for (n = i; n > 0; n /= 10)
|
||||
filename[--j] = '0' + (n % 10);
|
||||
#endif
|
||||
filename[i] = '\0';
|
||||
|
||||
/* Verify a file named "f/abcdef..." */
|
||||
strcpy(name1, "f/");
|
||||
strcat(name1, filename);
|
||||
if (limit != LIMIT_USTAR || strlen(filename) <= 100) {
|
||||
fd = open(name1, O_RDONLY);
|
||||
failure("Couldn't open \"%s\": %s",
|
||||
name1, strerror(errno));
|
||||
if (assert(fd >= 0)) {
|
||||
len = read(fd, contents, i + 10);
|
||||
close(fd);
|
||||
assertEqualInt(len, i + 2);
|
||||
/* Verify contents of 'contents' */
|
||||
contents[len] = '\0';
|
||||
failure("Each test file contains its own name");
|
||||
assertEqualString(name1, contents);
|
||||
/* stat() for dev/ino for next check */
|
||||
assertEqualInt(0, lstat(name1, &st));
|
||||
}
|
||||
sprintf(name1, "f/%s", filenames[i]);
|
||||
if (i <= limit) {
|
||||
assertFileExists(name1);
|
||||
assertFileContents(name1, strlen(name1), name1);
|
||||
}
|
||||
|
||||
/*
|
||||
* ustar allows 100 chars for links, and we have
|
||||
* "original/" as part of the name, so the link
|
||||
* names here can't exceed 91 chars.
|
||||
*/
|
||||
strcpy(name2, "l/");
|
||||
strcat(name2, filename);
|
||||
if (limit != LIMIT_USTAR || strlen(name2) <= 100) {
|
||||
sprintf(name2, "l/%s", filenames[i]);
|
||||
if (i + 2 <= limit) {
|
||||
/* Verify hardlink "l/abcdef..." */
|
||||
assertEqualInt(0, (r = lstat(name2, &st2)));
|
||||
if (r == 0) {
|
||||
assertEqualInt(st2.st_dev, st.st_dev);
|
||||
assertEqualInt(st2.st_ino, st.st_ino);
|
||||
}
|
||||
|
||||
/* Verify hardlink "m_abcdef..." */
|
||||
assertIsHardlink(name1, name2);
|
||||
/* Verify hardlink "m/abcdef..." */
|
||||
name2[0] = 'm';
|
||||
assertEqualInt(0, (r = lstat(name2, &st2)));
|
||||
if (r == 0) {
|
||||
assertEqualInt(st2.st_dev, st.st_dev);
|
||||
assertEqualInt(st2.st_ino, st.st_ino);
|
||||
assertIsHardlink(name1, name2);
|
||||
}
|
||||
|
||||
if (canSymlink()) {
|
||||
/* Verify symlink "s/abcdef..." */
|
||||
sprintf(name1, "s/%s", filenames[i]);
|
||||
sprintf(name2, "../f/%s", filenames[i]);
|
||||
if (strlen(name2) <= limit)
|
||||
assertIsSymlink(name1, name2);
|
||||
}
|
||||
|
||||
/* Verify dir "d/abcdef...". */
|
||||
sprintf(name1, "d/%s", filenames[i]);
|
||||
if (i + 1 <= limit) { /* +1 for trailing slash */
|
||||
if (assertIsDir(name1, -1)) {
|
||||
/* TODO: opendir/readdir this
|
||||
* directory and make sure
|
||||
* it's empty.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
/*
|
||||
* Symlink text doesn't include the 'original/' prefix,
|
||||
* so the limit here is 100 characters.
|
||||
*/
|
||||
/* Verify symlink "s/abcdef..." */
|
||||
strcpy(name2, "../s/");
|
||||
strcat(name2, filename);
|
||||
if (limit != LIMIT_USTAR || strlen(name2) <= 100) {
|
||||
/* This is a symlink. */
|
||||
failure("Couldn't stat %s (length %d)",
|
||||
filename, strlen(filename));
|
||||
if (assertEqualInt(0, lstat(name2 + 3, &st2))) {
|
||||
assert(S_ISLNK(st2.st_mode));
|
||||
/* This is a symlink to the file above. */
|
||||
failure("Couldn't stat %s", name2 + 3);
|
||||
if (assertEqualInt(0, stat(name2 + 3, &st2))) {
|
||||
assertEqualInt(st2.st_dev, st.st_dev);
|
||||
assertEqualInt(st2.st_ino, st.st_ino);
|
||||
{
|
||||
const char *dp;
|
||||
/* Now make sure nothing is there that shouldn't be. */
|
||||
for (dp = "dflms"; *dp != '\0'; ++dp) {
|
||||
DIR *d;
|
||||
struct dirent *de;
|
||||
char dir[2];
|
||||
dir[0] = *dp; dir[1] = '\0';
|
||||
d = opendir(dir);
|
||||
failure("Unable to open dir '%s'", dir);
|
||||
if (!assert(d != NULL))
|
||||
continue;
|
||||
while ((de = readdir(d)) != NULL) {
|
||||
char *p = de->d_name;
|
||||
if (p[0] == '.')
|
||||
continue;
|
||||
switch(dp[0]) {
|
||||
case 'l': case 'm': case 'd':
|
||||
failure("strlen(p)=%d", strlen(p));
|
||||
assert(strlen(p) < limit);
|
||||
assertEqualString(p,
|
||||
filenames[strlen(p)]);
|
||||
break;
|
||||
case 'f': case 's':
|
||||
failure("strlen(p)=%d", strlen(p));
|
||||
assert(strlen(p) < limit + 1);
|
||||
assertEqualString(p,
|
||||
filenames[strlen(p)]);
|
||||
break;
|
||||
default:
|
||||
failure("File %s shouldn't be here", p);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
#else
|
||||
skipping("verify symlink");
|
||||
}
|
||||
#endif
|
||||
/* Verify dir "d/abcdef...". */
|
||||
strcpy(name1, "d/");
|
||||
strcat(name1, filename);
|
||||
if (limit != LIMIT_USTAR || strlen(filename) < 100) {
|
||||
/* This is a dir. */
|
||||
failure("Couldn't stat %s (length %d)",
|
||||
name1, strlen(filename));
|
||||
if (assertEqualInt(0, lstat(name1, &st2))) {
|
||||
if (assert(S_ISDIR(st2.st_mode))) {
|
||||
/* TODO: opendir/readdir this
|
||||
* directory and make sure
|
||||
* it's empty.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now make sure nothing is there that shouldn't be. */
|
||||
for (dp = "dflms"; *dp != '\0'; ++dp) {
|
||||
char dir[2];
|
||||
dir[0] = *dp; dir[1] = '\0';
|
||||
d = opendir(dir);
|
||||
failure("Unable to open dir '%s'", dir);
|
||||
if (!assert(d != NULL))
|
||||
continue;
|
||||
while ((de = readdir(d)) != NULL) {
|
||||
p = de->d_name;
|
||||
switch(dp[0]) {
|
||||
case 'l': case 'm':
|
||||
if (limit == LIMIT_USTAR) {
|
||||
failure("strlen(p) = %d", strlen(p));
|
||||
assert(strlen(p) <= 100);
|
||||
}
|
||||
case 'd':
|
||||
if (limit == LIMIT_USTAR) {
|
||||
failure("strlen(p)=%d", strlen(p));
|
||||
assert(strlen(p) < 100);
|
||||
}
|
||||
case 'f': case 's':
|
||||
if (limit == LIMIT_USTAR) {
|
||||
failure("strlen(p)=%d", strlen(p));
|
||||
assert(strlen(p) < 101);
|
||||
}
|
||||
/* Our files have very particular filename patterns. */
|
||||
if (p[0] != '.' || (p[1] != '.' && p[1] != '\0')) {
|
||||
for (i = 0; p[i] != '\0' && i < LOOP_MAX; i++) {
|
||||
failure("i=%d, p[i]='%c' 'a'+(i%%26)='%c'", i, p[i], 'a' + (i % 26));
|
||||
assertEqualInt(p[i], 'a' + (i % 26));
|
||||
}
|
||||
assert(p[i] == '\0');
|
||||
}
|
||||
break;
|
||||
case '.':
|
||||
assert(p[1] == '\0' || (p[1] == '.' && p[2] == '\0'));
|
||||
break;
|
||||
default:
|
||||
failure("File %s shouldn't be here", p);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -251,7 +280,13 @@ copy_basic(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
assertEqualInt(0, mkdir("plain", 0775));
|
||||
/* NOTE: for proper operation on cygwin-1.5 and windows, the
|
||||
* length of the name of the directory below, "plain", must be
|
||||
* less than or equal to the lengthe of the name of the original
|
||||
* directory, "original" This restriction derives from the
|
||||
* extremely limited pathname lengths on those platforms.
|
||||
*/
|
||||
assertMakeDir("plain", 0775);
|
||||
assertEqualInt(0, chdir("plain"));
|
||||
|
||||
/*
|
||||
@ -287,7 +322,13 @@ copy_ustar(void)
|
||||
const char *target = "ustar";
|
||||
int r;
|
||||
|
||||
assertEqualInt(0, mkdir(target, 0775));
|
||||
/* NOTE: for proper operation on cygwin-1.5 and windows, the
|
||||
* length of the name of the directory below, "ustar", must be
|
||||
* less than or equal to the lengthe of the name of the original
|
||||
* directory, "original" This restriction derives from the
|
||||
* extremely limited pathname lengths on those platforms.
|
||||
*/
|
||||
assertMakeDir(target, 0775);
|
||||
assertEqualInt(0, chdir(target));
|
||||
|
||||
/*
|
||||
@ -314,17 +355,13 @@ copy_ustar(void)
|
||||
assertEmptyFile("unpack.err");
|
||||
assertEmptyFile("unpack.out");
|
||||
|
||||
chdir("original");
|
||||
verify_tree(LIMIT_USTAR);
|
||||
chdir("../..");
|
||||
assertEqualInt(0, chdir("../.."));
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_copy)
|
||||
{
|
||||
int oldumask;
|
||||
|
||||
oldumask = umask(0);
|
||||
|
||||
assertUmask(0);
|
||||
create_tree(); /* Create sample files in "original" dir. */
|
||||
|
||||
/* Test simple "tar -c | tar -x" pipeline copy. */
|
||||
@ -332,6 +369,4 @@ DEFINE_TEST(test_copy)
|
||||
|
||||
/* Same, but constrain to ustar format. */
|
||||
copy_ustar();
|
||||
|
||||
umask(oldumask);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Joerg Sonnenberger
|
||||
* Copyright (c) 2003-2009 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -21,23 +21,25 @@
|
||||
* 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$
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifndef LAFE_ERR_H
|
||||
#define LAFE_ERR_H
|
||||
/*
|
||||
* Regression test: We used to get a bogus error message when we
|
||||
* asked tar to copy entries out of an empty archive. See
|
||||
* Issue 51 on libarchive.googlecode.com for details.
|
||||
*/
|
||||
DEFINE_TEST(test_empty_mtree)
|
||||
{
|
||||
int r;
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2 || \
|
||||
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
|
||||
#define __LA_DEAD __attribute__((__noreturn__))
|
||||
#else
|
||||
#define __LA_DEAD
|
||||
#endif
|
||||
assertMakeFile("test1.mtree", 0777, "#mtree\n");
|
||||
|
||||
extern const char *bsdtar_progname;
|
||||
|
||||
void bsdtar_warnc(int code, const char *fmt, ...);
|
||||
void bsdtar_errc(int eval, int code, const char *fmt, ...) __LA_DEAD;
|
||||
|
||||
#endif
|
||||
r = systemf("%s cf test1.tar @test1.mtree >test1.out 2>test1.err",
|
||||
testprog);
|
||||
failure("Error invoking %s cf", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertEmptyFile("test1.out");
|
||||
assertEmptyFile("test1.err");
|
||||
}
|
@ -51,6 +51,7 @@ DEFINE_TEST(test_help)
|
||||
|
||||
/* Exercise --help option. */
|
||||
r = systemf("%s --help >help.stdout 2>help.stderr", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
failure("--help should generate nothing to stderr.");
|
||||
assertEmptyFile("help.stderr");
|
||||
/* Help message should start with name of program. */
|
||||
@ -67,6 +68,7 @@ DEFINE_TEST(test_help)
|
||||
|
||||
/* -h option should generate the same output. */
|
||||
r = systemf("%s -h >h.stdout 2>h.stderr", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
failure("-h should generate nothing to stderr.");
|
||||
assertEmptyFile("h.stderr");
|
||||
failure("stdout should be same for -h and --help");
|
||||
@ -74,6 +76,7 @@ DEFINE_TEST(test_help)
|
||||
|
||||
/* -W help should be another synonym. */
|
||||
r = systemf("%s -W help >Whelp.stdout 2>Whelp.stderr", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
failure("-W help should generate nothing to stderr.");
|
||||
assertEmptyFile("Whelp.stderr");
|
||||
failure("stdout should be same for -W help and --help");
|
||||
|
@ -26,110 +26,144 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static int
|
||||
touch(const char *fn)
|
||||
touch(const char *fn, int fail)
|
||||
{
|
||||
int fd = open(fn, O_RDWR | O_CREAT, 0644);
|
||||
failure("Couldn't create file '%s', fd=%d, errno=%d (%s)\n",
|
||||
fn, fd, errno, strerror(errno));
|
||||
if (!assert(fd > 0))
|
||||
return (0); /* Failure. */
|
||||
close(fd);
|
||||
FILE *f = fopen(fn, "w");
|
||||
if (fail) {
|
||||
failure("Couldn't create file '%s', errno=%d (%s)\n",
|
||||
fn, errno, strerror(errno));
|
||||
if (!assert(f != NULL))
|
||||
return (0); /* Failure. */
|
||||
} else {
|
||||
if (f == NULL)
|
||||
return (0); /* Soft failure. */
|
||||
}
|
||||
fclose(f);
|
||||
return (1); /* Success */
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_option_T)
|
||||
DEFINE_TEST(test_option_T_upper)
|
||||
{
|
||||
FILE *f;
|
||||
int r;
|
||||
struct stat st;
|
||||
int gnarlyFilesSupported;
|
||||
|
||||
/* Create a simple dir hierarchy; bail if anything fails. */
|
||||
if (!assertEqualInt(0, mkdir("d1", 0755))) return;
|
||||
if (!assertEqualInt(0, mkdir("d1/d2", 0755))) return;
|
||||
if (!touch("d1/f1")) return;
|
||||
if (!touch("d1/f2")) return;
|
||||
if (!touch("d1/d2/f3")) return;
|
||||
if (!touch("d1/d2/f4")) return;
|
||||
if (!touch("d1/d2/f5")) return;
|
||||
/* Create a simple dir heirarchy; bail if anything fails. */
|
||||
if (!assertMakeDir("d1", 0755)) return;
|
||||
if (!assertMakeDir("d1/d2", 0755)) return;
|
||||
if (!touch("f", 1)) return;
|
||||
if (!touch("d1/f1", 1)) return;
|
||||
if (!touch("d1/f2", 1)) return;
|
||||
if (!touch("d1/d2/f3", 1)) return;
|
||||
if (!touch("d1/d2/f4", 1)) return;
|
||||
if (!touch("d1/d2/f5", 1)) return;
|
||||
if (!touch("d1/d2/f6", 1)) return;
|
||||
/* Some platforms don't permit such things; just skip it. */
|
||||
gnarlyFilesSupported = touch("d1/d2/f\x0a", 0);
|
||||
|
||||
/* Populate a file list */
|
||||
f = fopen("filelist", "w+");
|
||||
if (!assert(f != NULL))
|
||||
return;
|
||||
fprintf(f, "d1/f1\n");
|
||||
fprintf(f, "d1/d2/f4\n");
|
||||
/* Use a variety of text line endings. */
|
||||
fprintf(f, "f\x0d"); /* CR */
|
||||
fprintf(f, "d1/f1\x0d\x0a"); /* CRLF */
|
||||
fprintf(f, "d1/d2/f4\x0a"); /* NL */
|
||||
fprintf(f, "d1/d2/f6"); /* EOF */
|
||||
fclose(f);
|
||||
|
||||
/* Populate a second file list */
|
||||
f = fopen("filelist2", "w+");
|
||||
if (!assert(f != NULL))
|
||||
return;
|
||||
fprintf(f, "d1/d2/f3\n");
|
||||
fprintf(f, "d1/d2/f5\n");
|
||||
/* Use null-terminated names. */
|
||||
fprintf(f, "d1/d2/f3");
|
||||
fwrite("\0", 1, 1, f);
|
||||
fprintf(f, "d1/d2/f5");
|
||||
fwrite("\0", 1, 1, f);
|
||||
if (gnarlyFilesSupported) {
|
||||
fprintf(f, "d1/d2/f\x0a");
|
||||
fwrite("\0", 1, 1, f);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
/* Use -c -T to archive up the files. */
|
||||
r = systemf("%s -c -f test1.tar -T filelist > test1.out 2> test1.err",
|
||||
testprog);
|
||||
failure("Failure here probably means that tar can't archive zero-length files without reading them");
|
||||
assert(r == 0);
|
||||
assertEmptyFile("test1.out");
|
||||
assertEmptyFile("test1.err");
|
||||
|
||||
/* Use -x -T to dearchive the files */
|
||||
if (!assertEqualInt(0, mkdir("test1", 0755))) return;
|
||||
if (!assertMakeDir("test1", 0755)) return;
|
||||
systemf("%s -x -f test1.tar -T filelist -C test1"
|
||||
" > test1b.out 2> test1b.err", testprog);
|
||||
assertEmptyFile("test1b.out");
|
||||
assertEmptyFile("test1b.err");
|
||||
|
||||
/* Verify the files were extracted. */
|
||||
assertFileExists("test1/f");
|
||||
assertFileExists("test1/d1/f1");
|
||||
assertFileNotExists("test1/d1/f2");
|
||||
assertFileNotExists("test1/d1/d2/f3");
|
||||
assertFileExists("test1/d1/d2/f4");
|
||||
assertFileNotExists("test1/d1/d2/f5");
|
||||
assertFileExists("test1/d1/d2/f6");
|
||||
if (gnarlyFilesSupported) {
|
||||
assertFileNotExists("test1/d1/d2/f\x0a");
|
||||
}
|
||||
|
||||
/* Use -r -T to add more files to the archive. */
|
||||
systemf("%s -r -f test1.tar -T filelist2 > test2.out 2> test2.err",
|
||||
systemf("%s -r -f test1.tar --null -T filelist2 > test2.out 2> test2.err",
|
||||
testprog);
|
||||
assertEmptyFile("test2.out");
|
||||
assertEmptyFile("test2.err");
|
||||
|
||||
/* Use -x without -T to dearchive the files (ensure -r worked) */
|
||||
if (!assertEqualInt(0, mkdir("test3", 0755))) return;
|
||||
if (!assertMakeDir("test3", 0755)) return;
|
||||
systemf("%s -x -f test1.tar -C test3"
|
||||
" > test3.out 2> test3.err", testprog);
|
||||
assertEmptyFile("test3.out");
|
||||
assertEmptyFile("test3.err");
|
||||
/* Verify the files were extracted.*/
|
||||
assertFileExists("test3/f");
|
||||
assertFileExists("test3/d1/f1");
|
||||
assertFileNotExists("test3/d1/f2");
|
||||
assertFileExists("test3/d1/d2/f3");
|
||||
assertFileExists("test3/d1/d2/f4");
|
||||
assertFileExists("test3/d1/d2/f5");
|
||||
assertFileExists("test3/d1/d2/f6");
|
||||
if (gnarlyFilesSupported) {
|
||||
assertFileExists("test3/d1/d2/f\x0a");
|
||||
}
|
||||
|
||||
/* Use -x -T to dearchive the files (verify -x -T together) */
|
||||
if (!assertEqualInt(0, mkdir("test2", 0755))) return;
|
||||
if (!assertMakeDir("test2", 0755)) return;
|
||||
systemf("%s -x -f test1.tar -T filelist -C test2"
|
||||
" > test2b.out 2> test2b.err", testprog);
|
||||
assertEmptyFile("test2b.out");
|
||||
assertEmptyFile("test2b.err");
|
||||
/* Verify the files were extracted.*/
|
||||
assertFileExists("test2/f");
|
||||
assertFileExists("test2/d1/f1");
|
||||
assertFileNotExists("test2/d1/f2");
|
||||
assertFileNotExists("test2/d1/d2/f3");
|
||||
assertFileExists("test2/d1/d2/f4");
|
||||
assertFileNotExists("test2/d1/d2/f5");
|
||||
assertFileExists("test2/d1/d2/f6");
|
||||
if (gnarlyFilesSupported) {
|
||||
assertFileNotExists("test2/d1/d2/f\x0a");
|
||||
}
|
||||
|
||||
assertEqualInt(0, mkdir("test4", 0755));
|
||||
assertEqualInt(0, mkdir("test4_out", 0755));
|
||||
assertEqualInt(0, mkdir("test4_out2", 0755));
|
||||
assertEqualInt(0, mkdir("test4/d1", 0755));
|
||||
assertEqualInt(1, touch("test4/d1/foo"));
|
||||
assertMakeDir("test4", 0755);
|
||||
assertMakeDir("test4_out", 0755);
|
||||
assertMakeDir("test4_out2", 0755);
|
||||
assertMakeDir("test4/d1", 0755);
|
||||
assertEqualInt(1, touch("test4/d1/foo", 0));
|
||||
|
||||
/* Does bsdtar support -s option ? */
|
||||
systemf("%s -cf - -s /foo/bar/ test4/d1/foo > NUL 2> check.err",
|
||||
systemf("%s -cf - -s /foo/bar/ test4/d1/foo > check.out 2> check.err",
|
||||
testprog);
|
||||
assertEqualInt(0, stat("check.err", &st));
|
||||
if (st.st_size == 0) {
|
||||
@ -148,6 +182,7 @@ DEFINE_TEST(test_option_T)
|
||||
} else {
|
||||
skipping("bsdtar does not support -s option on this platform");
|
||||
}
|
||||
|
||||
/* TODO: Include some use of -C directory-changing within the filelist. */
|
||||
/* I'm pretty sure -C within the filelist is broken on extract. */
|
||||
}
|
@ -27,7 +27,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_q)
|
||||
{
|
||||
int fd;
|
||||
FILE *f;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Create an archive with several different versions of the
|
||||
@ -39,38 +40,38 @@ DEFINE_TEST(test_option_q)
|
||||
* what we use to build up the test archive.
|
||||
*/
|
||||
|
||||
fd = open("foo", O_CREAT | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
assertEqualInt(4, write(fd, "foo1", 4));
|
||||
close(fd);
|
||||
f = fopen("foo", "w");
|
||||
assert(f != NULL);
|
||||
fprintf(f, "foo1");
|
||||
fclose(f);
|
||||
|
||||
assertEqualInt(0, systemf("%s -cf archive.tar foo", testprog));
|
||||
|
||||
fd = open("foo", O_TRUNC | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
assertEqualInt(4, write(fd, "foo2", 4));
|
||||
close(fd);
|
||||
f = fopen("foo", "w");
|
||||
assert(f != NULL);
|
||||
fprintf(f, "foo2");
|
||||
fclose(f);
|
||||
|
||||
assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog));
|
||||
|
||||
fd = open("bar", O_CREAT | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
assertEqualInt(4, write(fd, "bar1", 4));
|
||||
close(fd);
|
||||
f = fopen("bar", "w");
|
||||
assert(f != NULL);
|
||||
fprintf(f, "bar1");
|
||||
fclose(f);
|
||||
|
||||
assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog));
|
||||
|
||||
fd = open("foo", O_TRUNC | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
assertEqualInt(4, write(fd, "foo3", 4));
|
||||
close(fd);
|
||||
f = fopen("foo", "w");
|
||||
assert(f != NULL);
|
||||
fprintf(f, "foo3");
|
||||
fclose(f);
|
||||
|
||||
assertEqualInt(0, systemf("%s -rf archive.tar foo", testprog));
|
||||
|
||||
fd = open("bar", O_TRUNC | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
assertEqualInt(4, write(fd, "bar2", 4));
|
||||
close(fd);
|
||||
f = fopen("bar", "w");
|
||||
assert(f != NULL);
|
||||
fprintf(f, "bar2");
|
||||
fclose(f);
|
||||
|
||||
assertEqualInt(0, systemf("%s -rf archive.tar bar", testprog));
|
||||
|
||||
@ -80,46 +81,49 @@ DEFINE_TEST(test_option_q)
|
||||
*/
|
||||
|
||||
/* Test 1: -q foo should only extract the first foo. */
|
||||
assertEqualInt(0, mkdir("test1", 0755));
|
||||
assertEqualInt(0, chdir("test1"));
|
||||
assertEqualInt(0,
|
||||
systemf("%s -xf ../archive.tar -q foo >test.out 2>test.err",
|
||||
testprog));
|
||||
assertMakeDir("test1", 0755);
|
||||
assertChdir("test1");
|
||||
r = systemf("%s -xf ../archive.tar -q foo >test.out 2>test.err",
|
||||
testprog);
|
||||
failure("Fatal error trying to use -q option");
|
||||
if (!assertEqualInt(0, r))
|
||||
return;
|
||||
|
||||
assertFileContents("foo1", 4, "foo");
|
||||
assertEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
assertEqualInt(0, chdir(".."));
|
||||
assertChdir("..");
|
||||
|
||||
/* Test 2: -q foo bar should extract up to the first bar. */
|
||||
assertEqualInt(0, mkdir("test2", 0755));
|
||||
assertEqualInt(0, chdir("test2"));
|
||||
assertMakeDir("test2", 0755);
|
||||
assertChdir("test2");
|
||||
assertEqualInt(0,
|
||||
systemf("%s -xf ../archive.tar -q foo bar >test.out 2>test.err", testprog));
|
||||
assertFileContents("foo2", 4, "foo");
|
||||
assertFileContents("bar1", 4, "bar");
|
||||
assertEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
assertEqualInt(0, chdir(".."));
|
||||
assertChdir("..");
|
||||
|
||||
/* Test 3: Same as test 2, but use --fast-read spelling. */
|
||||
assertEqualInt(0, mkdir("test3", 0755));
|
||||
assertEqualInt(0, chdir("test3"));
|
||||
assertMakeDir("test3", 0755);
|
||||
assertChdir("test3");
|
||||
assertEqualInt(0,
|
||||
systemf("%s -xf ../archive.tar --fast-read foo bar >test.out 2>test.err", testprog));
|
||||
assertFileContents("foo2", 4, "foo");
|
||||
assertFileContents("bar1", 4, "bar");
|
||||
assertEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
assertEqualInt(0, chdir(".."));
|
||||
assertChdir("..");
|
||||
|
||||
/* Test 4: Without -q, should extract everything. */
|
||||
assertEqualInt(0, mkdir("test4", 0755));
|
||||
assertEqualInt(0, chdir("test4"));
|
||||
assertMakeDir("test4", 0755);
|
||||
assertChdir("test4");
|
||||
assertEqualInt(0,
|
||||
systemf("%s -xf ../archive.tar foo bar >test.out 2>test.err", testprog));
|
||||
assertFileContents("foo3", 4, "foo");
|
||||
assertFileContents("bar2", 4, "bar");
|
||||
assertEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
assertEqualInt(0, chdir(".."));
|
||||
assertChdir("..");
|
||||
}
|
||||
|
117
usr.bin/tar/test/test_option_r.c
Normal file
117
usr.bin/tar/test/test_option_r.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Also see test_option_q for additional validation of -r support.
|
||||
*/
|
||||
DEFINE_TEST(test_option_r)
|
||||
{
|
||||
char buff[15];
|
||||
char *p0, *p1;
|
||||
size_t s;
|
||||
FILE *f;
|
||||
int r;
|
||||
|
||||
/* Create a file */
|
||||
f = fopen("f1", "w");
|
||||
if (!assert(f != NULL))
|
||||
return;
|
||||
assertEqualInt(3, fwrite("abc", 1, 3, f));
|
||||
fclose(f);
|
||||
|
||||
/* Archive that one file. */
|
||||
r = systemf("%s cf archive.tar --format=ustar f1 >step1.out 2>step1.err", testprog);
|
||||
failure("Error invoking %s cf archive.tar f1", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
|
||||
/* Verify that nothing went to stdout or stderr. */
|
||||
assertEmptyFile("step1.out");
|
||||
assertEmptyFile("step1.err");
|
||||
|
||||
|
||||
/* Do some basic validation of the constructed archive. */
|
||||
p0 = slurpfile(&s, "archive.tar");
|
||||
if (!assert(p0 != NULL))
|
||||
return;
|
||||
if (!assert(s >= 2048)) {
|
||||
free(p0);
|
||||
return;
|
||||
}
|
||||
assertEqualMem(p0 + 0, "f1", 3);
|
||||
assertEqualMem(p0 + 512, "abc", 3);
|
||||
assertEqualMem(p0 + 1024, "\0\0\0\0\0\0\0\0", 8);
|
||||
assertEqualMem(p0 + 1536, "\0\0\0\0\0\0\0\0", 8);
|
||||
|
||||
/* Edit that file */
|
||||
f = fopen("f1", "w");
|
||||
if (!assert(f != NULL))
|
||||
return;
|
||||
assertEqualInt(3, fwrite("123", 1, 3, f));
|
||||
fclose(f);
|
||||
|
||||
/* Update the archive. */
|
||||
r = systemf("%s rf archive.tar --format=ustar f1 >step2.out 2>step2.err", testprog);
|
||||
failure("Error invoking %s rf archive.tar f1", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
|
||||
/* Verify that nothing went to stdout or stderr. */
|
||||
assertEmptyFile("step2.out");
|
||||
assertEmptyFile("step2.err");
|
||||
|
||||
/* Do some basic validation of the constructed archive. */
|
||||
p1 = slurpfile(&s, "archive.tar");
|
||||
if (!assert(p1 != NULL)) {
|
||||
free(p0);
|
||||
return;
|
||||
}
|
||||
assert(s >= 3072);
|
||||
/* Verify first entry is unchanged. */
|
||||
assertEqualMem(p0, p1, 1024);
|
||||
/* Verify that second entry is correct. */
|
||||
assertEqualMem(p1 + 1024, "f1", 3);
|
||||
assertEqualMem(p1 + 1536, "123", 3);
|
||||
/* Verify end-of-archive marker. */
|
||||
assertEqualMem(p1 + 2048, "\0\0\0\0\0\0\0\0", 8);
|
||||
assertEqualMem(p1 + 2560, "\0\0\0\0\0\0\0\0", 8);
|
||||
free(p0);
|
||||
free(p1);
|
||||
|
||||
/* Unpack both items */
|
||||
assertMakeDir("step3", 0775);
|
||||
assertChdir("step3");
|
||||
r = systemf("%s xf ../archive.tar", testprog);
|
||||
failure("Error invoking %s xf archive.tar", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
|
||||
/* Verify that the second one overwrote the first. */
|
||||
f = fopen("f1", "r");
|
||||
if (assert(f != NULL)) {
|
||||
assertEqualInt(3, fread(buff, 1, 3, f));
|
||||
assertEqualMem(buff, "123", 3);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
@ -28,15 +28,15 @@ __FBSDID("$FreeBSD$");
|
||||
static int
|
||||
mkfile(const char *fn, const char *contents)
|
||||
{
|
||||
int fd = open(fn, O_RDWR | O_CREAT, 0644);
|
||||
failure("Couldn't create file '%s', fd=%d, errno=%d (%s)\n",
|
||||
fn, fd, errno, strerror(errno));
|
||||
if (!assert(fd > 0))
|
||||
FILE *f = fopen(fn, "w");
|
||||
failure("Couldn't create file '%s', errno=%d (%s)\n",
|
||||
fn, errno, strerror(errno));
|
||||
if (!assert(f != NULL))
|
||||
return (1); /* Failure. */
|
||||
if (contents != NULL)
|
||||
assertEqualInt(strlen(contents),
|
||||
write(fd, contents, strlen(contents)));
|
||||
assertEqualInt(0, close(fd));
|
||||
fwrite(contents, 1, strlen(contents), f));
|
||||
assertEqualInt(0, fclose(f));
|
||||
return (0); /* Success */
|
||||
}
|
||||
|
||||
@ -44,9 +44,9 @@ DEFINE_TEST(test_option_s)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* Create a sample file hierarchy. */
|
||||
assertEqualInt(0, mkdir("in", 0755));
|
||||
assertEqualInt(0, mkdir("in/d1", 0755));
|
||||
/* Create a sample file heirarchy. */
|
||||
assertMakeDir("in", 0755);
|
||||
assertMakeDir("in/d1", 0755);
|
||||
assertEqualInt(0, mkfile("in/d1/foo", "foo"));
|
||||
assertEqualInt(0, mkfile("in/d1/bar", "bar"));
|
||||
|
||||
@ -55,14 +55,15 @@ DEFINE_TEST(test_option_s)
|
||||
testprog);
|
||||
assertEqualInt(0, stat("check.err", &st));
|
||||
if (st.st_size != 0) {
|
||||
skipping("bsdtar does not support -s option on this platform");
|
||||
skipping("%s does not support -s option on this platform",
|
||||
testprog);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test 1: Filename substitution when creating archives.
|
||||
*/
|
||||
assertEqualInt(0, mkdir("test1", 0755));
|
||||
assertMakeDir("test1", 0755);
|
||||
systemf("%s -cf - -s /foo/bar/ in/d1/foo | %s -xf - -C test1",
|
||||
testprog, testprog);
|
||||
assertFileContents("foo", 3, "test1/in/d1/bar");
|
||||
@ -74,7 +75,7 @@ DEFINE_TEST(test_option_s)
|
||||
/*
|
||||
* Test 2: Basic substitution when extracting archive.
|
||||
*/
|
||||
assertEqualInt(0, mkdir("test2", 0755));
|
||||
assertMakeDir("test2", 0755);
|
||||
systemf("%s -cf - in/d1/foo | %s -xf - -s /foo/bar/ -C test2",
|
||||
testprog, testprog);
|
||||
assertFileContents("foo", 3, "test2/in/d1/bar");
|
||||
@ -89,7 +90,7 @@ DEFINE_TEST(test_option_s)
|
||||
/*
|
||||
* Test 4: Multiple substitutions when extracting archive.
|
||||
*/
|
||||
assertEqualInt(0, mkdir("test4", 0755));
|
||||
assertMakeDir("test4", 0755);
|
||||
systemf("%s -cf - in/d1/foo in/d1/bar | %s -xf - -s /foo/bar/ -s }bar}baz} -C test4",
|
||||
testprog, testprog);
|
||||
assertFileContents("foo", 3, "test4/in/d1/bar");
|
||||
@ -98,7 +99,7 @@ DEFINE_TEST(test_option_s)
|
||||
/*
|
||||
* Test 5: Name-switching substitutions when extracting archive.
|
||||
*/
|
||||
assertEqualInt(0, mkdir("test5", 0755));
|
||||
assertMakeDir("test5", 0755);
|
||||
systemf("%s -cf - in/d1/foo in/d1/bar | %s -xf - -s /foo/bar/ -s }bar}foo} -C test5",
|
||||
testprog, testprog);
|
||||
assertFileContents("foo", 3, "test5/in/d1/bar");
|
||||
|
@ -28,11 +28,17 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_patterns)
|
||||
{
|
||||
int fd, r;
|
||||
FILE *f;
|
||||
int r;
|
||||
const char *reffile2 = "test_patterns_2.tar";
|
||||
const char *reffile3 = "test_patterns_3.tar";
|
||||
const char *reffile4 = "test_patterns_4.tar";
|
||||
const char *p;
|
||||
|
||||
const char *tar2aExpected[] = {
|
||||
"/tmp/foo/bar/",
|
||||
"/tmp/foo/bar/baz",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Test basic command-line pattern handling.
|
||||
@ -44,12 +50,12 @@ DEFINE_TEST(test_patterns)
|
||||
*
|
||||
* John Baldwin reported this problem in PR bin/121598
|
||||
*/
|
||||
fd = open("foo", O_CREAT | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
close(fd);
|
||||
f = fopen("foo", "w");
|
||||
assert(f != NULL);
|
||||
fclose(f);
|
||||
r = systemf("%s cfv tar1.tgz foo > tar1a.out 2> tar1a.err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
r = systemf("%s xfv tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog);
|
||||
r = systemf("%s xv --no-same-owner -f tar1.tgz foo bar > tar1b.out 2> tar1b.err", testprog);
|
||||
failure("tar should return non-zero because a file was given on the command line that's not in the archive");
|
||||
assert(r != 0);
|
||||
|
||||
@ -61,12 +67,7 @@ DEFINE_TEST(test_patterns)
|
||||
r = systemf("%s tf %s /tmp/foo/bar > tar2a.out 2> tar2a.err",
|
||||
testprog, reffile2);
|
||||
assertEqualInt(r, 0);
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
p = "/tmp/foo/bar/\n/tmp/foo/bar/baz\n";
|
||||
#else
|
||||
p = "/tmp/foo/bar/\r\n/tmp/foo/bar/baz\r\n";
|
||||
#endif
|
||||
assertFileContents(p, strlen(p), "tar2a.out");
|
||||
assertFileContainsLinesAnyOrder("tar2a.out", tar2aExpected);
|
||||
assertEmptyFile("tar2a.err");
|
||||
|
||||
/*
|
||||
@ -75,7 +76,7 @@ DEFINE_TEST(test_patterns)
|
||||
extract_reference_file(reffile3);
|
||||
|
||||
/* Test 3a: Pattern tmp/foo/bar should not match /tmp/foo/bar */
|
||||
r = systemf("%s xf %s tmp/foo/bar > tar3a.out 2> tar3a.err",
|
||||
r = systemf("%s x --no-same-owner -f %s tmp/foo/bar > tar3a.out 2> tar3a.err",
|
||||
testprog, reffile3);
|
||||
assert(r != 0);
|
||||
assertEmptyFile("tar3a.out");
|
||||
@ -83,26 +84,26 @@ DEFINE_TEST(test_patterns)
|
||||
/* Test 3b: Pattern /tmp/foo/baz should not match tmp/foo/baz */
|
||||
assertNonEmptyFile("tar3a.err");
|
||||
/* Again, with the '/' */
|
||||
r = systemf("%s xf %s /tmp/foo/baz > tar3b.out 2> tar3b.err",
|
||||
r = systemf("%s x --no-same-owner -f %s /tmp/foo/baz > tar3b.out 2> tar3b.err",
|
||||
testprog, reffile3);
|
||||
assert(r != 0);
|
||||
assertEmptyFile("tar3b.out");
|
||||
assertNonEmptyFile("tar3b.err");
|
||||
|
||||
/* Test 3c: ./tmp/foo/bar should not match /tmp/foo/bar */
|
||||
r = systemf("%s xf %s ./tmp/foo/bar > tar3c.out 2> tar3c.err",
|
||||
r = systemf("%s x --no-same-owner -f %s ./tmp/foo/bar > tar3c.out 2> tar3c.err",
|
||||
testprog, reffile3);
|
||||
assert(r != 0);
|
||||
assertEmptyFile("tar3c.out");
|
||||
assertNonEmptyFile("tar3c.err");
|
||||
|
||||
/* Test 3d: ./tmp/foo/baz should match tmp/foo/baz */
|
||||
r = systemf("%s xf %s ./tmp/foo/baz > tar3d.out 2> tar3d.err",
|
||||
r = systemf("%s x --no-same-owner -f %s ./tmp/foo/baz > tar3d.out 2> tar3d.err",
|
||||
testprog, reffile3);
|
||||
assertEqualInt(r, 0);
|
||||
assertEmptyFile("tar3d.out");
|
||||
assertEmptyFile("tar3d.err");
|
||||
assertEqualInt(0, access("tmp/foo/baz/bar", F_OK));
|
||||
assertFileExists("tmp/foo/baz/bar");
|
||||
|
||||
/*
|
||||
* Test 4 archive has some entries starting with windows drive letters
|
||||
@ -110,7 +111,7 @@ DEFINE_TEST(test_patterns)
|
||||
*/
|
||||
extract_reference_file(reffile4);
|
||||
|
||||
r = systemf("%s xf %s -C tmp > tar4.out 2> tar4.err",
|
||||
r = systemf("%s x --no-same-owner -f %s -C tmp > tar4.out 2> tar4.err",
|
||||
testprog, reffile4);
|
||||
assert(r != 0);
|
||||
assertEmptyFile("tar4.out");
|
||||
@ -167,16 +168,16 @@ DEFINE_TEST(test_patterns)
|
||||
* c:../..\file43
|
||||
* \/?\UnC\../file54
|
||||
*/
|
||||
assertEqualInt(-1, access(filex, F_OK));
|
||||
assertFileNotExists(filex);
|
||||
filex = file_c;
|
||||
xsize = sizeof(file_c);
|
||||
filex[xsize-3] = '0' + r / 10;
|
||||
filex[xsize-2] = '0' + r % 10;
|
||||
assertEqualInt(-1, access(filex, F_OK));
|
||||
assertFileNotExists(filex);
|
||||
break;
|
||||
default:
|
||||
/* Extracted patterns. */
|
||||
assertEqualInt(0, access(filex, F_OK));
|
||||
assertFileExists(filex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
$FreeBSD$
|
||||
|
||||
begin 644 test_patterns_2.tar
|
||||
M+W1M<"]F;V\O````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
|
@ -1,4 +1,5 @@
|
||||
$FreeBSD$
|
||||
|
||||
begin 644 test_patterns_3.tar
|
||||
M+W1M<"]F;V\O8F%R+P``````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
|
@ -1,4 +1,5 @@
|
||||
$FreeBSD$
|
||||
|
||||
begin 644 test_patterns_4.tar
|
||||
M+V9I;&4P,0``````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
|
@ -27,27 +27,27 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_stdio)
|
||||
{
|
||||
int fd;
|
||||
int filelist;
|
||||
int oldumask;
|
||||
FILE *filelist;
|
||||
char *p;
|
||||
size_t s;
|
||||
int r;
|
||||
|
||||
oldumask = umask(0);
|
||||
assertUmask(0);
|
||||
|
||||
/*
|
||||
* Create a couple of files on disk.
|
||||
*/
|
||||
filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
|
||||
/* File */
|
||||
fd = open("f", O_CREAT | O_WRONLY, 0644);
|
||||
assert(fd >= 0);
|
||||
write(fd, "f\n", 2);
|
||||
close(fd);
|
||||
write(filelist, "f\n", 2);
|
||||
assertMakeFile("f", 0755, "abc");
|
||||
/* Link to above file. */
|
||||
assertEqualInt(0, link("f", "l"));
|
||||
write(filelist, "l\n", 2);
|
||||
close(filelist);
|
||||
assertMakeHardlink("l", "f");
|
||||
|
||||
/* Create file list (text mode here) */
|
||||
filelist = fopen("filelist", "w");
|
||||
assert(filelist != NULL);
|
||||
fprintf(filelist, "f\n");
|
||||
fprintf(filelist, "l\n");
|
||||
fclose(filelist);
|
||||
|
||||
/*
|
||||
* Archive/dearchive with a variety of options, verifying
|
||||
@ -111,7 +111,10 @@ DEFINE_TEST(test_stdio)
|
||||
/* 'xvOf' should generate list on stderr, file contents on stdout. */
|
||||
r = systemf("%s xvOf archive >xvOf.out 2>xvOf.err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
/* TODO: Verify xvOf.out */
|
||||
/* Verify xvOf.out is the file contents */
|
||||
p = slurpfile(&s, "xvOf.out");
|
||||
assert(s = 3);
|
||||
assertEqualMem(p, "abc", 3);
|
||||
/* TODO: Verify xvf.err */
|
||||
|
||||
/* 'xvf -' should generate list on stderr, empty stdout. */
|
||||
@ -119,6 +122,4 @@ DEFINE_TEST(test_stdio)
|
||||
assertEqualInt(r, 0);
|
||||
assertEmptyFile("xvf-.out");
|
||||
/* TODO: Verify xvf-.err */
|
||||
|
||||
umask(oldumask);
|
||||
}
|
||||
|
@ -28,50 +28,49 @@ __FBSDID("$FreeBSD$");
|
||||
static int
|
||||
touch(const char *fn)
|
||||
{
|
||||
int fd = open(fn, O_RDWR | O_CREAT, 0644);
|
||||
failure("Couldn't create file '%s', fd=%d, errno=%d (%s)\n",
|
||||
fn, fd, errno, strerror(errno));
|
||||
if (!assert(fd > 0))
|
||||
FILE *f = fopen(fn, "w");
|
||||
failure("Couldn't create file '%s', errno=%d (%s)\n",
|
||||
fn, errno, strerror(errno));
|
||||
if (!assert(f != NULL))
|
||||
return (0); /* Failure. */
|
||||
close(fd);
|
||||
fclose(f);
|
||||
return (1); /* Success */
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_strip_components)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
assertEqualInt(0, mkdir("d0", 0755));
|
||||
assertEqualInt(0, chdir("d0"));
|
||||
assertEqualInt(0, mkdir("d1", 0755));
|
||||
assertEqualInt(0, mkdir("d1/d2", 0755));
|
||||
assertEqualInt(0, mkdir("d1/d2/d3", 0755));
|
||||
assertMakeDir("d0", 0755);
|
||||
assertChdir("d0");
|
||||
assertMakeDir("d1", 0755);
|
||||
assertMakeDir("d1/d2", 0755);
|
||||
assertMakeDir("d1/d2/d3", 0755);
|
||||
assertEqualInt(1, touch("d1/d2/f1"));
|
||||
assertEqualInt(0, link("d1/d2/f1", "l1"));
|
||||
assertEqualInt(0, link("d1/d2/f1", "d1/l2"));
|
||||
assertEqualInt(0, symlink("d1/d2/f1", "s1"));
|
||||
assertEqualInt(0, symlink("d2/f1", "d1/s2"));
|
||||
assertEqualInt(0, chdir(".."));
|
||||
assertMakeHardlink("l1", "d1/d2/f1");
|
||||
assertMakeHardlink("d1/l2", "d1/d2/f1");
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("s1", "d1/d2/f1");
|
||||
assertMakeSymlink("d1/s2", "d2/f1");
|
||||
}
|
||||
assertChdir("..");
|
||||
|
||||
assertEqualInt(0, systemf("%s -cf test.tar d0", testprog));
|
||||
|
||||
assertEqualInt(0, mkdir("target", 0755));
|
||||
assertMakeDir("target", 0755);
|
||||
assertEqualInt(0, systemf("%s -x -C target --strip-components 2 "
|
||||
"-f test.tar", testprog));
|
||||
|
||||
failure("d0/ is too short and should not get restored");
|
||||
assertEqualInt(-1, lstat("target/d0", &st));
|
||||
assertFileNotExists("target/d0");
|
||||
failure("d0/d1/ is too short and should not get restored");
|
||||
assertEqualInt(-1, lstat("target/d1", &st));
|
||||
assertFileNotExists("target/d1");
|
||||
failure("d0/d1/s2 is a symlink to something that won't be extracted");
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
assertEqualInt(-1, stat("target/s2", &st));
|
||||
#else
|
||||
skipping("symlink with stat()");
|
||||
#endif
|
||||
assertEqualInt(0, lstat("target/s2", &st));
|
||||
/* If platform supports symlinks, target/s2 is a broken symlink. */
|
||||
/* If platform does not support symlink, target/s2 doesn't exist. */
|
||||
assertFileNotExists("target/s2");
|
||||
if (canSymlink())
|
||||
assertIsSymlink("target/s2", "d2/f1");
|
||||
failure("d0/d1/d2 should be extracted");
|
||||
assertEqualInt(0, lstat("target/d2", &st));
|
||||
assertIsDir("target/d2", -1);
|
||||
|
||||
/*
|
||||
* This next is a complicated case. d0/l1, d0/d1/l2, and
|
||||
@ -102,9 +101,9 @@ DEFINE_TEST(test_strip_components)
|
||||
* parallel tests for cpio and newc formats.
|
||||
*/
|
||||
failure("d0/l1 is too short and should not get restored");
|
||||
assertEqualInt(-1, lstat("target/l1", &st));
|
||||
assertFileNotExists("target/l1");
|
||||
failure("d0/d1/l2 is a hardlink to file whose name was too short");
|
||||
assertEqualInt(-1, lstat("target/l2", &st));
|
||||
assertFileNotExists("target/l2");
|
||||
failure("d0/d1/d2/f1 is a hardlink to file whose name was too short");
|
||||
assertEqualInt(-1, lstat("target/d2/f1", &st));
|
||||
assertFileNotExists("target/d2/f1");
|
||||
}
|
||||
|
@ -32,40 +32,36 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
|
||||
static int
|
||||
mkfile(const char *name, int mode, const char *contents, ssize_t size)
|
||||
mkfile(const char *name, int mode, const char *contents, size_t size)
|
||||
{
|
||||
int fd = open(name, O_CREAT | O_WRONLY, mode);
|
||||
if (fd < 0)
|
||||
FILE *f = fopen(name, "wb");
|
||||
size_t written;
|
||||
|
||||
(void)mode; /* UNUSED */
|
||||
if (f == NULL)
|
||||
return (-1);
|
||||
if (size != write(fd, contents, size)) {
|
||||
close(fd);
|
||||
written = fwrite(contents, 1, size, f);
|
||||
fclose(f);
|
||||
if (size != written)
|
||||
return (-1);
|
||||
}
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_symlink_dir)
|
||||
{
|
||||
struct stat st;
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
struct stat st2;
|
||||
#endif
|
||||
int oldumask;
|
||||
assertUmask(0);
|
||||
|
||||
oldumask = umask(0);
|
||||
|
||||
assertEqualInt(0, mkdir("source", 0755));
|
||||
assertMakeDir("source", 0755);
|
||||
assertEqualInt(0, mkfile("source/file", 0755, "a", 1));
|
||||
assertEqualInt(0, mkfile("source/file2", 0755, "ab", 2));
|
||||
assertEqualInt(0, mkdir("source/dir", 0755));
|
||||
assertEqualInt(0, mkdir("source/dir/d", 0755));
|
||||
assertMakeDir("source/dir", 0755);
|
||||
assertMakeDir("source/dir/d", 0755);
|
||||
assertEqualInt(0, mkfile("source/dir/f", 0755, "abc", 3));
|
||||
assertEqualInt(0, mkdir("source/dir2", 0755));
|
||||
assertEqualInt(0, mkdir("source/dir2/d2", 0755));
|
||||
assertMakeDir("source/dir2", 0755);
|
||||
assertMakeDir("source/dir2/d2", 0755);
|
||||
assertEqualInt(0, mkfile("source/dir2/f2", 0755, "abcd", 4));
|
||||
assertEqualInt(0, mkdir("source/dir3", 0755));
|
||||
assertEqualInt(0, mkdir("source/dir3/d3", 0755));
|
||||
assertMakeDir("source/dir3", 0755);
|
||||
assertMakeDir("source/dir3/d3", 0755);
|
||||
assertEqualInt(0, mkfile("source/dir3/f3", 0755, "abcde", 5));
|
||||
|
||||
assertEqualInt(0,
|
||||
@ -75,119 +71,90 @@ DEFINE_TEST(test_symlink_dir)
|
||||
/*
|
||||
* Extract with -x and without -P.
|
||||
*/
|
||||
assertEqualInt(0, mkdir("dest1", 0755));
|
||||
/* "dir" is a symlink to an existing "real_dir" */
|
||||
assertEqualInt(0, mkdir("dest1/real_dir", 0755));
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
assertEqualInt(0, symlink("real_dir", "dest1/dir"));
|
||||
/* "dir2" is a symlink to a non-existing "real_dir2" */
|
||||
assertEqualInt(0, symlink("real_dir2", "dest1/dir2"));
|
||||
#else
|
||||
skipping("symlink does not work on this platform");
|
||||
#endif
|
||||
assertMakeDir("dest1", 0755);
|
||||
/* "dir" is a symlink to an existing "dest1/real_dir" */
|
||||
assertMakeDir("dest1/real_dir", 0755);
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("dest1/dir", "real_dir");
|
||||
/* "dir2" is a symlink to a non-existing "real_dir2" */
|
||||
assertMakeSymlink("dest1/dir2", "real_dir2");
|
||||
} else {
|
||||
skipping("some symlink checks");
|
||||
}
|
||||
/* "dir3" is a symlink to an existing "non_dir3" */
|
||||
assertEqualInt(0, mkfile("dest1/non_dir3", 0755, "abcdef", 6));
|
||||
assertEqualInt(0, symlink("non_dir3", "dest1/dir3"));
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("dest1/dir3", "non_dir3");
|
||||
/* "file" is a symlink to existing "real_file" */
|
||||
assertEqualInt(0, mkfile("dest1/real_file", 0755, "abcdefg", 7));
|
||||
assertEqualInt(0, symlink("real_file", "dest1/file"));
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
/* "file2" is a symlink to non-existing "real_file2" */
|
||||
assertEqualInt(0, symlink("real_file2", "dest1/file2"));
|
||||
#else
|
||||
skipping("symlink does not work on this platform");
|
||||
#endif
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("dest1/file", "real_file");
|
||||
/* "file2" is a symlink to non-existing "real_file2" */
|
||||
assertMakeSymlink("dest1/file2", "real_file2");
|
||||
}
|
||||
assertEqualInt(0, systemf("%s -xf test.tar -C dest1", testprog));
|
||||
|
||||
/* dest1/dir symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest1/dir", &st));
|
||||
/* dest1/dir symlink should be replaced */
|
||||
failure("symlink to dir was followed when it shouldn't be");
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
/* dest1/dir2 symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest1/dir2", &st));
|
||||
assertIsDir("dest1/dir", -1);
|
||||
/* dest1/dir2 symlink should be replaced */
|
||||
failure("Broken symlink wasn't replaced with dir");
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
/* dest1/dir3 symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest1/dir3", &st));
|
||||
assertIsDir("dest1/dir2", -1);
|
||||
/* dest1/dir3 symlink should be replaced */
|
||||
failure("Symlink to non-dir wasn't replaced with dir");
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
/* dest1/file symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest1/file", &st));
|
||||
failure("Symlink to existing file should be removed");
|
||||
assert(S_ISREG(st.st_mode));
|
||||
/* dest1/file2 symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest1/file2", &st));
|
||||
failure("Symlink to non-existing file should be removed");
|
||||
assert(S_ISREG(st.st_mode));
|
||||
assertIsDir("dest1/dir3", -1);
|
||||
/* dest1/file symlink should be replaced */
|
||||
failure("Symlink to existing file should be replaced");
|
||||
assertIsReg("dest1/file", -1);
|
||||
/* dest1/file2 symlink should be replaced */
|
||||
failure("Symlink to non-existing file should be replaced");
|
||||
assertIsReg("dest1/file2", -1);
|
||||
|
||||
/*
|
||||
* Extract with both -x and -P
|
||||
*/
|
||||
assertEqualInt(0, mkdir("dest2", 0755));
|
||||
assertMakeDir("dest2", 0755);
|
||||
/* "dir" is a symlink to existing "real_dir" */
|
||||
assertEqualInt(0, mkdir("dest2/real_dir", 0755));
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
assertEqualInt(0, symlink("real_dir", "dest2/dir"));
|
||||
assertMakeDir("dest2/real_dir", 0755);
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("dest2/dir", "real_dir");
|
||||
/* "dir2" is a symlink to a non-existing "real_dir2" */
|
||||
assertEqualInt(0, symlink("real_dir2", "dest2/dir2"));
|
||||
#else
|
||||
skipping("symlink does not work on this platform");
|
||||
#endif
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("dest2/dir2", "real_dir2");
|
||||
/* "dir3" is a symlink to an existing "non_dir3" */
|
||||
assertEqualInt(0, mkfile("dest2/non_dir3", 0755, "abcdefgh", 8));
|
||||
assertEqualInt(0, symlink("non_dir3", "dest2/dir3"));
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("dest2/dir3", "non_dir3");
|
||||
/* "file" is a symlink to existing "real_file" */
|
||||
assertEqualInt(0, mkfile("dest2/real_file", 0755, "abcdefghi", 9));
|
||||
assertEqualInt(0, symlink("real_file", "dest2/file"));
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("dest2/file", "real_file");
|
||||
/* "file2" is a symlink to non-existing "real_file2" */
|
||||
assertEqualInt(0, symlink("real_file2", "dest2/file2"));
|
||||
#else
|
||||
skipping("symlink does not work on this platform");
|
||||
#endif
|
||||
if (canSymlink())
|
||||
assertMakeSymlink("dest2/file2", "real_file2");
|
||||
assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog));
|
||||
|
||||
/* dest2/dir symlink should be followed */
|
||||
assertEqualInt(0, lstat("dest2/dir", &st));
|
||||
failure("tar -xP removed symlink instead of following it");
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (assert(S_ISLNK(st.st_mode))) {
|
||||
/* Only verify what the symlink points to if it
|
||||
* really is a symlink. */
|
||||
failure("The symlink should point to a directory");
|
||||
assertEqualInt(0, stat("dest2/dir", &st));
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
failure("The pre-existing directory should still be there");
|
||||
assertEqualInt(0, lstat("dest2/real_dir", &st2));
|
||||
assert(S_ISDIR(st2.st_mode));
|
||||
assertEqualInt(st.st_dev, st2.st_dev);
|
||||
failure("symlink should still point to the existing directory");
|
||||
assertEqualInt(st.st_ino, st2.st_ino);
|
||||
if (canSymlink()) {
|
||||
assertIsSymlink("dest2/dir", "real_dir");
|
||||
assertIsDir("dest2/real_dir", -1);
|
||||
}
|
||||
#else
|
||||
skipping("symlink does not work on this platform");
|
||||
#endif
|
||||
|
||||
/* Contents of 'dir' should be restored */
|
||||
assertEqualInt(0, lstat("dest2/dir/d", &st));
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
assertEqualInt(0, lstat("dest2/dir/f", &st));
|
||||
assert(S_ISREG(st.st_mode));
|
||||
assertEqualInt(3, st.st_size);
|
||||
assertIsDir("dest2/dir/d", -1);
|
||||
assertIsReg("dest2/dir/f", -1);
|
||||
assertFileSize("dest2/dir/f", 3);
|
||||
/* dest2/dir2 symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest2/dir2", &st));
|
||||
failure("Broken symlink wasn't replaced with dir");
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
assertIsDir("dest2/dir2", -1);
|
||||
/* dest2/dir3 symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest2/dir3", &st));
|
||||
failure("Symlink to non-dir wasn't replaced with dir");
|
||||
assert(S_ISDIR(st.st_mode));
|
||||
assertIsDir("dest2/dir3", -1);
|
||||
/* dest2/file symlink should be removed;
|
||||
* even -P shouldn't follow symlinks for files */
|
||||
assertEqualInt(0, lstat("dest2/file", &st));
|
||||
failure("Symlink to existing file should be removed");
|
||||
assert(S_ISREG(st.st_mode));
|
||||
assertIsReg("dest2/file", -1);
|
||||
/* dest2/file2 symlink should be removed */
|
||||
assertEqualInt(0, lstat("dest2/file2", &st));
|
||||
failure("Symlink to non-existing file should be removed");
|
||||
assert(S_ISREG(st.st_mode));
|
||||
assertIsReg("dest2/file2", -1);
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ DEFINE_TEST(test_version)
|
||||
/* Version message should start with name of program, then space. */
|
||||
assert(s > 6);
|
||||
failure("Version must start with 'bsdtar': ``%s''", p);
|
||||
assertEqualMem(q, "bsdtar ", 7);
|
||||
if (!assertEqualMem(q, "bsdtar ", 7))
|
||||
return;
|
||||
q += 7; s -= 7;
|
||||
/* Version number is a series of digits and periods. */
|
||||
while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
|
||||
|
@ -293,7 +293,7 @@ set_chdir(struct bsdtar *bsdtar, const char *newdir)
|
||||
free(old_pending);
|
||||
}
|
||||
if (bsdtar->pending_chdir == NULL)
|
||||
bsdtar_errc(1, errno, "No memory");
|
||||
lafe_errc(1, errno, "No memory");
|
||||
}
|
||||
|
||||
void
|
||||
@ -303,7 +303,7 @@ do_chdir(struct bsdtar *bsdtar)
|
||||
return;
|
||||
|
||||
if (chdir(bsdtar->pending_chdir) != 0) {
|
||||
bsdtar_errc(1, 0, "could not chdir to '%s'\n",
|
||||
lafe_errc(1, 0, "could not chdir to '%s'\n",
|
||||
bsdtar->pending_chdir);
|
||||
}
|
||||
free(bsdtar->pending_chdir);
|
||||
@ -367,7 +367,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
|
||||
#if HAVE_REGEX_H
|
||||
r = apply_substitution(bsdtar, name, &subst_name, 0);
|
||||
if (r == -1) {
|
||||
bsdtar_warnc(0, "Invalid substitution, skipping entry");
|
||||
lafe_warnc(0, "Invalid substitution, skipping entry");
|
||||
return 1;
|
||||
}
|
||||
if (r == 1) {
|
||||
@ -383,7 +383,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
|
||||
if (archive_entry_hardlink(entry)) {
|
||||
r = apply_substitution(bsdtar, archive_entry_hardlink(entry), &subst_name, 1);
|
||||
if (r == -1) {
|
||||
bsdtar_warnc(0, "Invalid substitution, skipping entry");
|
||||
lafe_warnc(0, "Invalid substitution, skipping entry");
|
||||
return 1;
|
||||
}
|
||||
if (r == 1) {
|
||||
@ -394,7 +394,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
|
||||
if (archive_entry_symlink(entry) != NULL) {
|
||||
r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1);
|
||||
if (r == -1) {
|
||||
bsdtar_warnc(0, "Invalid substitution, skipping entry");
|
||||
lafe_warnc(0, "Invalid substitution, skipping entry");
|
||||
return 1;
|
||||
}
|
||||
if (r == 1) {
|
||||
@ -468,11 +468,11 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
|
||||
if (p != name && !bsdtar->warned_lead_slash) {
|
||||
/* Generate a warning the first time this happens. */
|
||||
if (slashonly)
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Removing leading '%c' from member names",
|
||||
name[0]);
|
||||
else
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"Removing leading drive letter from "
|
||||
"member names");
|
||||
bsdtar->warned_lead_slash = 1;
|
||||
|
@ -169,7 +169,7 @@ tar_mode_c(struct bsdtar *bsdtar)
|
||||
int r;
|
||||
|
||||
if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
|
||||
bsdtar_errc(1, 0, "no files or directories specified");
|
||||
lafe_errc(1, 0, "no files or directories specified");
|
||||
|
||||
a = archive_write_new();
|
||||
|
||||
@ -223,21 +223,21 @@ tar_mode_c(struct bsdtar *bsdtar)
|
||||
r = archive_write_set_compression_compress(a);
|
||||
break;
|
||||
default:
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Unrecognized compression option -%c",
|
||||
bsdtar->create_compression);
|
||||
}
|
||||
if (r != ARCHIVE_OK) {
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Unsupported compression option -%c",
|
||||
bsdtar->create_compression);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
|
||||
bsdtar_errc(1, 0, "%s", archive_error_string(a));
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
if (ARCHIVE_OK != archive_write_open_file(a, bsdtar->filename))
|
||||
bsdtar_errc(1, 0, "%s", archive_error_string(a));
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
write_archive(a, bsdtar);
|
||||
}
|
||||
|
||||
@ -265,7 +265,7 @@ tar_mode_r(struct bsdtar *bsdtar)
|
||||
bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY, 0666);
|
||||
#endif
|
||||
if (bsdtar->fd < 0)
|
||||
bsdtar_errc(1, errno,
|
||||
lafe_errc(1, errno,
|
||||
"Cannot open %s", bsdtar->filename);
|
||||
|
||||
a = archive_read_new();
|
||||
@ -274,14 +274,14 @@ tar_mode_r(struct bsdtar *bsdtar)
|
||||
archive_read_support_format_gnutar(a);
|
||||
r = archive_read_open_fd(a, bsdtar->fd, 10240);
|
||||
if (r != ARCHIVE_OK)
|
||||
bsdtar_errc(1, archive_errno(a),
|
||||
lafe_errc(1, archive_errno(a),
|
||||
"Can't read archive %s: %s", bsdtar->filename,
|
||||
archive_error_string(a));
|
||||
while (0 == archive_read_next_header(a, &entry)) {
|
||||
if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
|
||||
archive_read_finish(a);
|
||||
close(bsdtar->fd);
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Cannot append to compressed archive.");
|
||||
}
|
||||
/* Keep going until we hit end-of-archive */
|
||||
@ -310,7 +310,7 @@ tar_mode_r(struct bsdtar *bsdtar)
|
||||
format &= ARCHIVE_FORMAT_BASE_MASK;
|
||||
if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
|
||||
&& format != ARCHIVE_FORMAT_EMPTY) {
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Format %s is incompatible with the archive %s.",
|
||||
bsdtar->create_format, bsdtar->filename);
|
||||
}
|
||||
@ -327,11 +327,11 @@ tar_mode_r(struct bsdtar *bsdtar)
|
||||
archive_write_set_format(a, format);
|
||||
}
|
||||
if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
|
||||
bsdtar_errc(1, errno, "Could not seek to archive end");
|
||||
lafe_errc(1, errno, "Could not seek to archive end");
|
||||
if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
|
||||
bsdtar_errc(1, 0, "%s", archive_error_string(a));
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
|
||||
bsdtar_errc(1, 0, "%s", archive_error_string(a));
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
|
||||
write_archive(a, bsdtar); /* XXX check return val XXX */
|
||||
|
||||
@ -359,7 +359,7 @@ tar_mode_u(struct bsdtar *bsdtar)
|
||||
|
||||
bsdtar->fd = open(bsdtar->filename, O_RDWR | O_BINARY);
|
||||
if (bsdtar->fd < 0)
|
||||
bsdtar_errc(1, errno,
|
||||
lafe_errc(1, errno,
|
||||
"Cannot open %s", bsdtar->filename);
|
||||
|
||||
a = archive_read_new();
|
||||
@ -369,7 +369,7 @@ tar_mode_u(struct bsdtar *bsdtar)
|
||||
if (archive_read_open_fd(a, bsdtar->fd,
|
||||
bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
|
||||
DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Can't open %s: %s", bsdtar->filename,
|
||||
archive_error_string(a));
|
||||
}
|
||||
@ -379,7 +379,7 @@ tar_mode_u(struct bsdtar *bsdtar)
|
||||
if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
|
||||
archive_read_finish(a);
|
||||
close(bsdtar->fd);
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Cannot append to compressed archive.");
|
||||
}
|
||||
add_dir_list(bsdtar, archive_entry_pathname(entry),
|
||||
@ -410,11 +410,11 @@ tar_mode_u(struct bsdtar *bsdtar)
|
||||
} else
|
||||
archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);
|
||||
if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
|
||||
bsdtar_errc(1, errno, "Could not seek to archive end");
|
||||
lafe_errc(1, errno, "Could not seek to archive end");
|
||||
if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
|
||||
bsdtar_errc(1, 0, "%s", archive_error_string(a));
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
|
||||
bsdtar_errc(1, 0, "%s", archive_error_string(a));
|
||||
lafe_errc(1, 0, "%s", archive_error_string(a));
|
||||
|
||||
write_archive(a, bsdtar);
|
||||
|
||||
@ -442,14 +442,14 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
|
||||
|
||||
/* Allocate a buffer for file data. */
|
||||
if ((bsdtar->buff = malloc(FILEDATABUFLEN)) == NULL)
|
||||
bsdtar_errc(1, 0, "cannot allocate memory");
|
||||
lafe_errc(1, 0, "cannot allocate memory");
|
||||
|
||||
if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL)
|
||||
bsdtar_errc(1, 0, "cannot create link resolver");
|
||||
lafe_errc(1, 0, "cannot create link resolver");
|
||||
archive_entry_linkresolver_set_strategy(bsdtar->resolver,
|
||||
archive_format(a));
|
||||
if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
|
||||
bsdtar_errc(1, 0, "Cannot create read_disk object");
|
||||
lafe_errc(1, 0, "Cannot create read_disk object");
|
||||
archive_read_disk_set_standard_lookup(bsdtar->diskreader);
|
||||
|
||||
if (bsdtar->names_from_file != NULL)
|
||||
@ -463,7 +463,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
|
||||
bsdtar->argv++;
|
||||
arg = *bsdtar->argv;
|
||||
if (arg == NULL) {
|
||||
bsdtar_warnc(0, "%s",
|
||||
lafe_warnc(0, "%s",
|
||||
"Missing argument for -C");
|
||||
bsdtar->return_value = 1;
|
||||
goto cleanup;
|
||||
@ -493,7 +493,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
|
||||
}
|
||||
|
||||
if (archive_write_close(a)) {
|
||||
bsdtar_warnc(0, "%s", archive_error_string(a));
|
||||
lafe_warnc(0, "%s", archive_error_string(a));
|
||||
bsdtar->return_value = 1;
|
||||
}
|
||||
|
||||
@ -543,7 +543,7 @@ archive_names_from_file(struct bsdtar *bsdtar, struct archive *a)
|
||||
}
|
||||
lafe_line_reader_free(lr);
|
||||
if (bsdtar->next_line_is_dir)
|
||||
bsdtar_errc(1, errno,
|
||||
lafe_errc(1, errno,
|
||||
"Unexpected end of filename list; "
|
||||
"directory expected after -C");
|
||||
}
|
||||
@ -569,7 +569,7 @@ append_archive_filename(struct bsdtar *bsdtar, struct archive *a,
|
||||
archive_read_support_format_all(ina);
|
||||
archive_read_support_compression_all(ina);
|
||||
if (archive_read_open_file(ina, filename, 10240)) {
|
||||
bsdtar_warnc(0, "%s", archive_error_string(ina));
|
||||
lafe_warnc(0, "%s", archive_error_string(ina));
|
||||
bsdtar->return_value = 1;
|
||||
return (0);
|
||||
}
|
||||
@ -577,7 +577,7 @@ append_archive_filename(struct bsdtar *bsdtar, struct archive *a,
|
||||
rc = append_archive(bsdtar, a, ina);
|
||||
|
||||
if (rc != ARCHIVE_OK) {
|
||||
bsdtar_warnc(0, "Error reading archive %s: %s",
|
||||
lafe_warnc(0, "Error reading archive %s: %s",
|
||||
filename, archive_error_string(ina));
|
||||
bsdtar->return_value = 1;
|
||||
}
|
||||
@ -610,7 +610,7 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
|
||||
e = archive_write_header(a, in_entry);
|
||||
if (e != ARCHIVE_OK) {
|
||||
if (!bsdtar->verbose)
|
||||
bsdtar_warnc(0, "%s: %s",
|
||||
lafe_warnc(0, "%s: %s",
|
||||
archive_entry_pathname(in_entry),
|
||||
archive_error_string(a));
|
||||
else
|
||||
@ -651,7 +651,7 @@ copy_file_data(struct bsdtar *bsdtar, struct archive *a,
|
||||
bytes_written = archive_write_data(a, bsdtar->buff,
|
||||
bytes_read);
|
||||
if (bytes_written < bytes_read) {
|
||||
bsdtar_warnc(0, "%s", archive_error_string(a));
|
||||
lafe_warnc(0, "%s", archive_error_string(a));
|
||||
return (-1);
|
||||
}
|
||||
progress += bytes_written;
|
||||
@ -678,7 +678,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
|
||||
tree = tree_open(path);
|
||||
|
||||
if (!tree) {
|
||||
bsdtar_warnc(errno, "%s: Cannot open", path);
|
||||
lafe_warnc(errno, "%s: Cannot open", path);
|
||||
bsdtar->return_value = 1;
|
||||
return;
|
||||
}
|
||||
@ -691,11 +691,11 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
|
||||
int descend;
|
||||
|
||||
if (tree_ret == TREE_ERROR_FATAL)
|
||||
bsdtar_errc(1, tree_errno(tree),
|
||||
lafe_errc(1, tree_errno(tree),
|
||||
"%s: Unable to continue traversing directory tree",
|
||||
name);
|
||||
if (tree_ret == TREE_ERROR_DIR) {
|
||||
bsdtar_warnc(errno,
|
||||
lafe_warnc(errno,
|
||||
"%s: Couldn't visit directory", name);
|
||||
bsdtar->return_value = 1;
|
||||
}
|
||||
@ -715,7 +715,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
|
||||
lst = tree_current_lstat(tree);
|
||||
if (lst == NULL) {
|
||||
/* Couldn't lstat(); must not exist. */
|
||||
bsdtar_warnc(errno, "%s: Cannot stat", name);
|
||||
lafe_warnc(errno, "%s: Cannot stat", name);
|
||||
/* Return error if files disappear during traverse. */
|
||||
bsdtar->return_value = 1;
|
||||
continue;
|
||||
@ -834,7 +834,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
|
||||
r = archive_read_disk_entry_from_file(bsdtar->diskreader,
|
||||
entry, -1, st);
|
||||
if (r != ARCHIVE_OK)
|
||||
bsdtar_warnc(archive_errno(bsdtar->diskreader),
|
||||
lafe_warnc(archive_errno(bsdtar->diskreader),
|
||||
"%s", archive_error_string(bsdtar->diskreader));
|
||||
if (r < ARCHIVE_WARN)
|
||||
continue;
|
||||
@ -929,7 +929,7 @@ write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
|
||||
if (fd == -1) {
|
||||
bsdtar->return_value = 1;
|
||||
if (!bsdtar->verbose)
|
||||
bsdtar_warnc(errno,
|
||||
lafe_warnc(errno,
|
||||
"%s: could not open file", pathname);
|
||||
else
|
||||
fprintf(stderr, ": %s", strerror(errno));
|
||||
@ -940,7 +940,7 @@ write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
|
||||
e = archive_write_header(a, entry);
|
||||
if (e != ARCHIVE_OK) {
|
||||
if (!bsdtar->verbose)
|
||||
bsdtar_warnc(0, "%s: %s",
|
||||
lafe_warnc(0, "%s: %s",
|
||||
archive_entry_pathname(entry),
|
||||
archive_error_string(a));
|
||||
else
|
||||
@ -1016,12 +1016,12 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a,
|
||||
bytes_read);
|
||||
if (bytes_written < 0) {
|
||||
/* Write failed; this is bad */
|
||||
bsdtar_warnc(0, "%s", archive_error_string(a));
|
||||
lafe_warnc(0, "%s", archive_error_string(a));
|
||||
return (-1);
|
||||
}
|
||||
if (bytes_written < bytes_read) {
|
||||
/* Write was truncated; warn but continue. */
|
||||
bsdtar_warnc(0,
|
||||
lafe_warnc(0,
|
||||
"%s: Truncated write; file may have grown while being archived.",
|
||||
archive_entry_pathname(entry));
|
||||
return (0);
|
||||
@ -1030,7 +1030,7 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a,
|
||||
bytes_read = read(fd, bsdtar->buff, FILEDATABUFLEN);
|
||||
}
|
||||
if (bytes_read < 0) {
|
||||
bsdtar_warnc(errno,
|
||||
lafe_warnc(errno,
|
||||
"%s: Read error",
|
||||
archive_entry_pathname(entry));
|
||||
bsdtar->return_value = 1;
|
||||
@ -1112,11 +1112,11 @@ add_dir_list(struct bsdtar *bsdtar, const char *path,
|
||||
|
||||
p = malloc(sizeof(*p));
|
||||
if (p == NULL)
|
||||
bsdtar_errc(1, ENOMEM, "Can't read archive directory");
|
||||
lafe_errc(1, ENOMEM, "Can't read archive directory");
|
||||
|
||||
p->name = strdup(path);
|
||||
if (p->name == NULL)
|
||||
bsdtar_errc(1, ENOMEM, "Can't read archive directory");
|
||||
lafe_errc(1, ENOMEM, "Can't read archive directory");
|
||||
p->mtime_sec = mtime_sec;
|
||||
p->mtime_nsec = mtime_nsec;
|
||||
p->next = NULL;
|
||||
@ -1134,26 +1134,26 @@ test_for_append(struct bsdtar *bsdtar)
|
||||
struct stat s;
|
||||
|
||||
if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
|
||||
bsdtar_errc(1, 0, "no files or directories specified");
|
||||
lafe_errc(1, 0, "no files or directories specified");
|
||||
if (bsdtar->filename == NULL)
|
||||
bsdtar_errc(1, 0, "Cannot append to stdout.");
|
||||
lafe_errc(1, 0, "Cannot append to stdout.");
|
||||
|
||||
if (bsdtar->create_compression != 0)
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Cannot append to %s with compression", bsdtar->filename);
|
||||
|
||||
if (stat(bsdtar->filename, &s) != 0)
|
||||
return;
|
||||
|
||||
if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode))
|
||||
bsdtar_errc(1, 0,
|
||||
lafe_errc(1, 0,
|
||||
"Cannot append to %s: not a regular file.",
|
||||
bsdtar->filename);
|
||||
|
||||
/* Is this an appropriate check here on Windows? */
|
||||
/*
|
||||
if (GetFileType(handle) != FILE_TYPE_DISK)
|
||||
bsdtar_errc(1, 0, "Cannot append");
|
||||
lafe_errc(1, 0, "Cannot append");
|
||||
*/
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user