Update bsdcpio to 2.8.4

Use common code from lib/libarchive/libarchive_fe

Approved by:	kientzle
MFC after:	2 weeks
This commit is contained in:
Martin Matuska 2011-07-17 21:42:22 +00:00
parent 2ad1419f1b
commit f305d4bef7
43 changed files with 2705 additions and 2295 deletions

View File

@ -3,17 +3,24 @@
.include <bsd.own.mk>
PROG= bsdcpio
BSDCPIO_VERSION_STRING=2.8.3
SRCS= cpio.c cmdline.c err.c line_reader.c matching.c pathmatch.c
BSDCPIO_VERSION_STRING=2.8.4
SRCS= cpio.c cmdline.c
.PATH: ${.CURDIR}/../../lib/libarchive/libarchive_fe
SRCS+= err.c line_reader.c matching.c pathmatch.c
CFLAGS+= -DBSDCPIO_VERSION_STRING=\"${BSDCPIO_VERSION_STRING}\"
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../lib/libarchive/libarchive_fe
.ifdef RELEASE_CRUNCH
# FreeBSD's installer uses cpio in crunched binaries that are
# statically linked, cannot use -lcrypto, and are size sensitive.
CFLAGS+= -DSMALLER
.endif
DPADD= ${LIBARCHIVE} ${LIBZ} ${LIBBZ2} ${LIBMD} ${LIBLZMA}
LDADD= -larchive -lz -lbz2 -lmd -llzma
DPADD= ${LIBARCHIVE} ${LIBZ} ${LIBBZ2} ${LIBMD} ${LIBLZMA} ${LIBBSDXML}
LDADD= -larchive -lz -lbz2 -lmd -llzma -lbsdxml
.if ${MK_OPENSSL} != "no"
DPADD+= ${LIBCRYPTO}
LDADD+= -lcrypto

View File

@ -175,7 +175,7 @@ cpio_getopt(struct cpio *cpio)
/* Otherwise, pick up the next word. */
opt_word = *cpio->argv;
if (opt_word == NULL) {
warnc(0,
lafe_warnc(0,
"Option -%c requires an argument",
opt);
return ('?');
@ -226,13 +226,13 @@ cpio_getopt(struct cpio *cpio)
/* Fail if there wasn't a unique match. */
if (match == NULL) {
warnc(0,
lafe_warnc(0,
"Option %s%s is not supported",
long_prefix, opt_word);
return ('?');
}
if (match2 != NULL) {
warnc(0,
lafe_warnc(0,
"Ambiguous option %s%s (matches --%s and --%s)",
long_prefix, opt_word, match->name, match2->name);
return ('?');
@ -244,7 +244,7 @@ cpio_getopt(struct cpio *cpio)
if (cpio->optarg == NULL) {
cpio->optarg = *cpio->argv;
if (cpio->optarg == NULL) {
warnc(0,
lafe_warnc(0,
"Option %s%s requires an argument",
long_prefix, match->name);
return ('?');
@ -255,7 +255,7 @@ cpio_getopt(struct cpio *cpio)
} else {
/* Argument forbidden: fail if there is one. */
if (cpio->optarg != NULL) {
warnc(0,
lafe_warnc(0,
"Option %s%s does not allow an argument",
long_prefix, match->name);
return ('?');

View File

@ -53,4 +53,5 @@
#define HAVE_UNSIGNED_LONG_LONG 1
#define HAVE_UTIME_H 1
#define HAVE_UTIMES 1
#define HAVE_WCSCMP 1

View File

@ -136,19 +136,19 @@ main(int argc, char *argv[])
cpio->buff = buff;
cpio->buff_size = sizeof(buff);
/* Need progname before calling warnc. */
/* Need lafe_progname before calling lafe_warnc. */
if (*argv == NULL)
progname = "bsdcpio";
lafe_progname = "bsdcpio";
else {
#if defined(_WIN32) && !defined(__CYGWIN__)
progname = strrchr(*argv, '\\');
lafe_progname = strrchr(*argv, '\\');
#else
progname = strrchr(*argv, '/');
lafe_progname = strrchr(*argv, '/');
#endif
if (progname != NULL)
progname++;
if (lafe_progname != NULL)
lafe_progname++;
else
progname = *argv;
lafe_progname = *argv;
}
cpio->uid_override = -1;
@ -189,7 +189,7 @@ main(int argc, char *argv[])
case 'C': /* NetBSD/OpenBSD */
cpio->bytes_per_block = atoi(cpio->optarg);
if (cpio->bytes_per_block <= 0)
errc(1, 0, "Invalid blocksize %s", cpio->optarg);
lafe_errc(1, 0, "Invalid blocksize %s", cpio->optarg);
break;
case 'c': /* POSIX 1997 */
cpio->format = "odc";
@ -198,14 +198,14 @@ main(int argc, char *argv[])
cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR;
break;
case 'E': /* NetBSD/OpenBSD */
include_from_file(&cpio->matching,
lafe_include_from_file(&cpio->matching,
cpio->optarg, cpio->option_null);
break;
case 'F': /* NetBSD/OpenBSD/GNU cpio */
cpio->filename = cpio->optarg;
break;
case 'f': /* POSIX 1997 */
exclude(&cpio->matching, cpio->optarg);
lafe_exclude(&cpio->matching, cpio->optarg);
break;
case 'H': /* GNU cpio (also --format) */
cpio->format = cpio->optarg;
@ -218,7 +218,7 @@ main(int argc, char *argv[])
break;
case 'i': /* POSIX 1997 */
if (cpio->mode != '\0')
errc(1, 0,
lafe_errc(1, 0,
"Cannot use both -i and -%c", cpio->mode);
cpio->mode = opt;
break;
@ -255,13 +255,13 @@ main(int argc, char *argv[])
break;
case 'o': /* POSIX 1997 */
if (cpio->mode != '\0')
errc(1, 0,
lafe_errc(1, 0,
"Cannot use both -o and -%c", cpio->mode);
cpio->mode = opt;
break;
case 'p': /* POSIX 1997 */
if (cpio->mode != '\0')
errc(1, 0,
lafe_errc(1, 0,
"Cannot use both -p and -%c", cpio->mode);
cpio->mode = opt;
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
@ -277,7 +277,7 @@ main(int argc, char *argv[])
* also; use that to set [ug]name_override. */
errmsg = owner_parse(cpio->optarg, &uid, &gid);
if (errmsg) {
warnc(-1, "%s", errmsg);
lafe_warnc(-1, "%s", errmsg);
usage();
}
if (uid != -1) {
@ -335,16 +335,16 @@ main(int argc, char *argv[])
cpio->mode = 'i';
/* -t requires -i */
if (cpio->option_list && cpio->mode != 'i')
errc(1, 0, "Option -t requires -i");
lafe_errc(1, 0, "Option -t requires -i");
/* -n requires -it */
if (cpio->option_numeric_uid_gid && !cpio->option_list)
errc(1, 0, "Option -n requires -it");
lafe_errc(1, 0, "Option -n requires -it");
/* Can only specify format when writing */
if (cpio->format != NULL && cpio->mode != 'o')
errc(1, 0, "Option --format requires -o");
lafe_errc(1, 0, "Option --format requires -o");
/* -l requires -p */
if (cpio->option_link && cpio->mode != 'p')
errc(1, 0, "Option -l requires -p");
lafe_errc(1, 0, "Option -l requires -p");
/* TODO: Flag other nonsensical combinations. */
switch (cpio->mode) {
@ -358,7 +358,7 @@ main(int argc, char *argv[])
break;
case 'i':
while (*cpio->argv != NULL) {
include(&cpio->matching, *cpio->argv);
lafe_include(&cpio->matching, *cpio->argv);
--cpio->argc;
++cpio->argv;
}
@ -369,12 +369,12 @@ main(int argc, char *argv[])
break;
case 'p':
if (*cpio->argv == NULL || **cpio->argv == '\0')
errc(1, 0,
lafe_errc(1, 0,
"-p mode requires a target directory");
mode_pass(cpio, *cpio->argv);
break;
default:
errc(1, 0,
lafe_errc(1, 0,
"Must specify at least one of -i, -o, or -p");
}
@ -388,7 +388,7 @@ usage(void)
{
const char *p;
p = progname;
p = lafe_progname;
fprintf(stderr, "Brief Usage:\n");
fprintf(stderr, " List: %s -it < archive\n", p);
@ -426,7 +426,7 @@ long_help(void)
const char *prog;
const char *p;
prog = progname;
prog = lafe_progname;
fflush(stderr);
@ -459,16 +459,16 @@ static void
mode_out(struct cpio *cpio)
{
struct archive_entry *entry, *spare;
struct line_reader *lr;
struct lafe_line_reader *lr;
const char *p;
int r;
if (cpio->option_append)
errc(1, 0, "Append mode not yet supported.");
lafe_errc(1, 0, "Append mode not yet supported.");
cpio->archive_read_disk = archive_read_disk_new();
if (cpio->archive_read_disk == NULL)
errc(1, 0, "Failed to allocate archive object");
lafe_errc(1, 0, "Failed to allocate archive object");
if (cpio->option_follow_links)
archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
else
@ -477,7 +477,7 @@ mode_out(struct cpio *cpio)
cpio->archive = archive_write_new();
if (cpio->archive == NULL)
errc(1, 0, "Failed to allocate archive object");
lafe_errc(1, 0, "Failed to allocate archive object");
switch (cpio->compress) {
case 'J':
r = archive_write_set_compression_xz(cpio->archive);
@ -499,10 +499,10 @@ mode_out(struct cpio *cpio)
break;
}
if (r < ARCHIVE_WARN)
errc(1, 0, "Requested compression not available");
lafe_errc(1, 0, "Requested compression not available");
r = archive_write_set_format_by_name(cpio->archive, cpio->format);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(cpio->archive));
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block);
cpio->linkresolver = archive_entry_linkresolver_new();
archive_entry_linkresolver_set_strategy(cpio->linkresolver,
@ -513,11 +513,11 @@ mode_out(struct cpio *cpio)
*/
r = archive_write_open_file(cpio->archive, cpio->filename);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(cpio->archive));
lr = line_reader("-", cpio->option_null);
while ((p = line_reader_next(lr)) != NULL)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
lr = lafe_line_reader("-", cpio->option_null);
while ((p = lafe_line_reader_next(lr)) != NULL)
file_to_archive(cpio, p);
line_reader_free(lr);
lafe_line_reader_free(lr);
/*
* The hardlink detection may have queued up a couple of entries
@ -534,7 +534,7 @@ mode_out(struct cpio *cpio)
r = archive_write_close(cpio->archive);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(cpio->archive));
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
if (!cpio->quiet) {
int64_t blocks =
@ -566,15 +566,15 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
*/
entry = archive_entry_new();
if (entry == NULL)
errc(1, 0, "Couldn't allocate entry");
lafe_errc(1, 0, "Couldn't allocate entry");
archive_entry_copy_sourcepath(entry, srcpath);
r = archive_read_disk_entry_from_file(cpio->archive_read_disk,
entry, -1, NULL);
if (r < ARCHIVE_FAILED)
errc(1, 0, "%s",
lafe_errc(1, 0, "%s",
archive_error_string(cpio->archive_read_disk));
if (r < ARCHIVE_OK)
warnc(0, "%s",
lafe_warnc(0, "%s",
archive_error_string(cpio->archive_read_disk));
if (r <= ARCHIVE_FAILED) {
cpio->return_value = 1;
@ -607,7 +607,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
free(cpio->pass_destpath);
cpio->pass_destpath = malloc(cpio->pass_destpath_alloc);
if (cpio->pass_destpath == NULL)
errc(1, ENOMEM,
lafe_errc(1, ENOMEM,
"Can't allocate path buffer");
}
strcpy(cpio->pass_destpath, cpio->destdir);
@ -673,7 +673,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
/* Save the original entry in case we need it later. */
t = archive_entry_clone(entry);
if (t == NULL)
errc(1, ENOMEM, "Can't create link");
lafe_errc(1, ENOMEM, "Can't create link");
/* Note: link(2) doesn't create parent directories,
* so we use archive_write_header() instead as a
* convenience. */
@ -683,7 +683,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
r = archive_write_header(cpio->archive, t);
archive_entry_free(t);
if (r != ARCHIVE_OK)
warnc(archive_errno(cpio->archive),
lafe_warnc(archive_errno(cpio->archive),
"%s", archive_error_string(cpio->archive));
if (r == ARCHIVE_FATAL)
exit(1);
@ -691,7 +691,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
if (r != ARCHIVE_OK && archive_errno(cpio->archive) == EXDEV) {
/* Cross-device link: Just fall through and use
* the original entry to copy the file over. */
warnc(0, "Copying file instead");
lafe_warnc(0, "Copying file instead");
} else
#endif
return (0);
@ -705,7 +705,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
if (archive_entry_size(entry) > 0) {
fd = open(srcpath, O_RDONLY | O_BINARY);
if (fd < 0) {
warnc(errno,
lafe_warnc(errno,
"%s: could not open file", srcpath);
goto cleanup;
}
@ -717,7 +717,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
r = archive_write_header(cpio->archive, entry);
if (r != ARCHIVE_OK)
warnc(archive_errno(cpio->archive),
lafe_warnc(archive_errno(cpio->archive),
"%s: %s",
srcpath,
archive_error_string(cpio->archive));
@ -731,10 +731,10 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
r = archive_write_data(cpio->archive,
cpio->buff, bytes_read);
if (r < 0)
errc(1, archive_errno(cpio->archive),
lafe_errc(1, archive_errno(cpio->archive),
"%s", archive_error_string(cpio->archive));
if (r < bytes_read) {
warnc(0,
lafe_warnc(0,
"Truncated write; file may have grown while being archived.");
}
bytes_read = read(fd, cpio->buff, cpio->buff_size);
@ -763,7 +763,7 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
(void)name; /* UNUSED */
if (!warned)
warnc(0, "Can't restore access times on this platform");
lafe_warnc(0, "Can't restore access times on this platform");
warned = 1;
return (fd);
#else
@ -801,7 +801,7 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
if ((AE_IFLNK != archive_entry_filetype(entry))
&& utimes(name, times) != 0)
#endif
warnc(errno, "Can't update time for %s", name);
lafe_warnc(errno, "Can't update time for %s", name);
#endif
return (fd);
}
@ -818,28 +818,28 @@ mode_in(struct cpio *cpio)
ext = archive_write_disk_new();
if (ext == NULL)
errc(1, 0, "Couldn't allocate restore object");
lafe_errc(1, 0, "Couldn't allocate restore object");
r = archive_write_disk_set_options(ext, cpio->extract_flags);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(ext));
lafe_errc(1, 0, "%s", archive_error_string(ext));
a = archive_read_new();
if (a == NULL)
errc(1, 0, "Couldn't allocate archive object");
lafe_errc(1, 0, "Couldn't allocate archive object");
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
errc(1, archive_errno(a),
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK) {
errc(1, archive_errno(a),
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
}
if (excluded(cpio->matching, archive_entry_pathname(entry)))
if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
continue;
if (cpio->option_rename) {
destpath = cpio_rename(archive_entry_pathname(entry));
@ -867,10 +867,10 @@ mode_in(struct cpio *cpio)
}
r = archive_read_close(a);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(a));
lafe_errc(1, 0, "%s", archive_error_string(a));
r = archive_write_close(ext);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(ext));
lafe_errc(1, 0, "%s", archive_error_string(ext));
if (!cpio->quiet) {
int64_t blocks = (archive_position_uncompressed(a) + 511)
/ 512;
@ -899,13 +899,13 @@ extract_data(struct archive *ar, struct archive *aw)
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK) {
warnc(archive_errno(ar),
lafe_warnc(archive_errno(ar),
"%s", archive_error_string(ar));
exit(1);
}
r = archive_write_data_block(aw, block, size, offset);
if (r != ARCHIVE_OK) {
warnc(archive_errno(aw),
lafe_warnc(archive_errno(aw),
"%s", archive_error_string(aw));
return (r);
}
@ -921,22 +921,22 @@ mode_list(struct cpio *cpio)
a = archive_read_new();
if (a == NULL)
errc(1, 0, "Couldn't allocate archive object");
lafe_errc(1, 0, "Couldn't allocate archive object");
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
errc(1, archive_errno(a),
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK) {
errc(1, archive_errno(a),
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
}
if (excluded(cpio->matching, archive_entry_pathname(entry)))
if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
continue;
if (cpio->verbose)
list_item_verbose(cpio, entry);
@ -945,7 +945,7 @@ mode_list(struct cpio *cpio)
}
r = archive_read_close(a);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(a));
lafe_errc(1, 0, "%s", archive_error_string(a));
if (!cpio->quiet) {
int64_t blocks = (archive_position_uncompressed(a) + 511)
/ 512;
@ -1040,7 +1040,7 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
static void
mode_pass(struct cpio *cpio, const char *destdir)
{
struct line_reader *lr;
struct lafe_line_reader *lr;
const char *p;
int r;
@ -1052,31 +1052,31 @@ mode_pass(struct cpio *cpio, const char *destdir)
cpio->archive = archive_write_disk_new();
if (cpio->archive == NULL)
errc(1, 0, "Failed to allocate archive object");
lafe_errc(1, 0, "Failed to allocate archive object");
r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(cpio->archive));
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
cpio->linkresolver = archive_entry_linkresolver_new();
archive_write_disk_set_standard_lookup(cpio->archive);
cpio->archive_read_disk = archive_read_disk_new();
if (cpio->archive_read_disk == NULL)
errc(1, 0, "Failed to allocate archive object");
lafe_errc(1, 0, "Failed to allocate archive object");
if (cpio->option_follow_links)
archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
else
archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
archive_read_disk_set_standard_lookup(cpio->archive_read_disk);
lr = line_reader("-", cpio->option_null);
while ((p = line_reader_next(lr)) != NULL)
lr = lafe_line_reader("-", cpio->option_null);
while ((p = lafe_line_reader_next(lr)) != NULL)
file_to_archive(cpio, p);
line_reader_free(lr);
lafe_line_reader_free(lr);
archive_entry_linkresolver_free(cpio->linkresolver);
r = archive_write_close(cpio->archive);
if (r != ARCHIVE_OK)
errc(1, 0, "%s", archive_error_string(cpio->archive));
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
if (!cpio->quiet) {
int64_t blocks =
@ -1160,7 +1160,7 @@ lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
if (*name_cache_variable == NULL) {
*name_cache_variable = malloc(sizeof(struct name_cache));
if (*name_cache_variable == NULL)
errc(1, ENOMEM, "No more memory");
lafe_errc(1, ENOMEM, "No more memory");
memset(*name_cache_variable, 0, sizeof(struct name_cache));
(*name_cache_variable)->size = name_cache_size;
}
@ -1217,7 +1217,7 @@ lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
if (pwent == NULL) {
*name = NULL;
if (errno != 0 && errno != ENOENT)
warnc(errno, "getpwuid(%d) failed", id);
lafe_warnc(errno, "getpwuid(%d) failed", id);
return (errno);
}
@ -1244,7 +1244,7 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
if (grent == NULL) {
*name = NULL;
if (errno != 0)
warnc(errno, "getgrgid(%d) failed", id);
lafe_warnc(errno, "getgrgid(%d) failed", id);
return (errno);
}

View File

@ -88,7 +88,7 @@ struct cpio {
struct name_cache *gname_cache;
/* Work data. */
struct matching *matching;
struct lafe_matching *matching;
char *buff;
size_t buff_size;
};

View File

@ -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 "cpio_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 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 line_reader *
line_reader(const char *pathname, int nullSeparator)
{
struct line_reader *lr;
lr = calloc(1, sizeof(*lr));
if (lr == NULL)
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)
errc(1, errno, "Couldn't open %s", pathname);
lr->buff_length = 8192;
lr->buff = malloc(lr->buff_length);
if (lr->buff == NULL)
errc(1, ENOMEM, "Can't read %s", pathname);
lr->line_start = lr->line_end = lr->buff_end = lr->buff;
return (lr);
}
const char *
line_reader_next(struct 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)
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)
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))
errc(1, errno, "Can't read %s", lr->pathname);
if (feof(lr->f)) {
if (lr->f != stdin)
fclose(lr->f);
lr->f = NULL;
}
}
}
void
line_reader_free(struct line_reader *lr)
{
free(lr->buff);
free(lr->pathname);
free(lr);
}

View File

@ -1,284 +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 "cpio_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 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 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
exclude(struct matching **matching, const char *pattern)
{
if (*matching == NULL)
initialize_matching(matching);
add_pattern(&((*matching)->exclusions), pattern);
(*matching)->exclusions_count++;
return (0);
}
int
exclude_from_file(struct matching **matching, const char *pathname)
{
struct line_reader *lr;
const char *p;
int ret = 0;
lr = line_reader(pathname, 0);
while ((p = line_reader_next(lr)) != NULL) {
if (exclude(matching, p) != 0)
ret = -1;
}
line_reader_free(lr);
return (ret);
}
int
include(struct 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
include_from_file(struct matching **matching, const char *pathname,
int nullSeparator)
{
struct line_reader *lr;
const char *p;
int ret = 0;
lr = line_reader(pathname, nullSeparator);
while ((p = line_reader_next(lr)) != NULL) {
if (include(matching, p) != 0)
ret = -1;
}
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)
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
excluded(struct matching *matching, const char *pathname)
{
struct match *match;
struct match *matched;
if (matching == NULL)
return (0);
/* Exclusions take priority */
for (match = matching->exclusions; match != NULL; match = match->next){
if (match_exclusion(match, pathname))
return (1);
}
/* Then check for inclusions */
matched = NULL;
for (match = matching->inclusions; match != NULL; match = match->next){
if (match_inclusion(match, pathname)) {
/*
* If this pattern has never been matched,
* then we're done.
*/
if (match->matches == 0) {
match->matches++;
matching->inclusions_unmatched_count--;
return (0);
}
/*
* Otherwise, remember the match but keep checking
* in case we can tick off an unmatched pattern.
*/
matched = match;
}
}
/*
* We didn't find a pattern that had never been matched, but
* we did find a match, so count it and exit.
*/
if (matched != NULL) {
matched->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 (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)
{
#if 0
return (pathmatch(match->pattern, pathname, 0));
#else
return (pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
#endif
}
void
cleanup_exclusions(struct 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 matching **matching)
{
*matching = calloc(sizeof(**matching), 1);
if (*matching == NULL)
errc(1, errno, "No memory");
}
int
unmatched_inclusions(struct matching *matching)
{
if (matching == NULL)
return (0);
return (matching->inclusions_unmatched_count);
}
int
unmatched_inclusions_warn(struct 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)
warnc(0, "%s: %s", p->pattern, msg);
}
return (matching->inclusions_unmatched_count);
}

View File

@ -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 matching;
int exclude(struct matching **matching, const char *pattern);
int exclude_from_file(struct matching **matching,
const char *pathname);
int include(struct matching **matching, const char *pattern);
int include_from_file(struct matching **matching,
const char *pathname, int nullSeparator);
int excluded(struct matching *, const char *pathname);
void cleanup_exclusions(struct matching **);
int unmatched_inclusions(struct matching *);
int unmatched_inclusions_warn(struct matching *, const char *msg);
#endif

View File

@ -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 "cpio_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 '!' 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 < 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 (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
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));
}

View File

@ -2,24 +2,30 @@
# Where to find the cpio sources (for the internal unit tests)
CPIO_SRCDIR=${.CURDIR}/..
.PATH: ${CPIO_SRCDIR}
# Some cpio sources are pulled in for white-box tests
CPIO_SRCS= cmdline.c err.c pathmatch.c
.PATH: ${CPIO_SRCDIR}
CPIO_SRCS= cmdline.c
.PATH: ${.CURDIR}/../../../lib/libarchive/libarchive_fe
TAR_SRCS= err.c pathmatch.c
TESTS= \
test_0.c \
test_basic.c \
test_format_newc.c \
test_gcpio_compat.c \
test_option_B_upper.c \
test_option_C_upper.c \
test_option_J_upper.c \
test_option_L_upper.c \
test_option_Z_upper.c \
test_option_a.c \
test_option_B.c \
test_option_c.c \
test_option_d.c \
test_option_f.c \
test_option_help.c \
test_option_L.c \
test_option_ell.c \
test_option_l.c \
test_option_lzma.c \
test_option_m.c \
test_option_t.c \
test_option_u.c \
@ -34,6 +40,7 @@ TESTS= \
# Build the test program
SRCS= list.h \
${CPIO_SRCS} \
${TAR_SRCS} \
${TESTS} \
main.c
@ -46,9 +53,11 @@ DPADD=${LIBARCHIVE} ${LIBBZ2} ${LIBZ} ${LIBLZMA}
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
CFLAGS+= -I..
LDADD= -larchive -lz -lbz2 -llzma
CFLAGS+= -static -g -O2 -Wall
#CFLAGS+= -static -g -O2 -Wall
CFLAGS+= -g -O2 -Wall
CFLAGS+= -I${.OBJDIR}
CFLAGS+= -I${CPIO_SRCDIR}
CFLAGS+= -I${.CURDIR}/../../../lib/libarchive/libarchive_fe
# Uncomment to link against dmalloc
#LDADD+= -L/usr/local/lib -ldmalloc

File diff suppressed because it is too large Load Diff

View File

@ -45,47 +45,84 @@
#error Oops: No config.h and no pre-built configuration in test.h.
#endif
#if !defined(_WIN32) || defined(__CYGWIN__)
#include <dirent.h>
#else
#include "../cpio_windows.h"
#endif
#if defined(__CYGWIN__)
/* In cygwin-1.7.x, the .nlinks field of directories is
* deliberately inaccurate, because to populate it requires
* stat'ing every file in the directory, which is slow.
* So, as an optimization cygwin doesn't do that in newer
* releases; all correct applications on any platform should
* never rely on it being > 1, so this optimization doesn't
* impact the operation of correctly coded applications.
* Therefore, the cpio test should not check its accuracy
*/
# define NLINKS_INACCURATE_FOR_DIRS
#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 <time.h>
#include <wchar.h>
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif
#if HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#define dirent direct
#endif
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_IO_H
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <wchar.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
#ifdef __FreeBSD__
#include <sys/cdefs.h> /* For __FBSDID */
/*
* System-specific tweaks. We really want to minimize these
* as much as possible, since they make it harder to understand
* the mainline code.
*/
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "../cpio_windows.h"
#if !defined(__BORLANDC__)
#define strdup _strdup
#endif
#define LOCALE_DE "deu"
#else
#undef __FBSDID
#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
/*
* Redefine DEFINE_TEST for use in defining the test functions.
*/
@ -93,40 +130,81 @@
#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)
assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* Assert two strings are the same. Reports value of each one if not. */
#define assertEqualString(v1,v2) \
test_assert_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but v1 and v2 are wchar_t * */
#define assertEqualWString(v1,v2) \
test_assert_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but raw blocks of bytes. */
#define assertEqualMem(v1, v2, l) \
test_assert_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
/* Assert two files are the same; allow printf-style expansion of second name.
* See below for comments about variable arguments here...
*/
#define assertEqualFile \
test_setup(__FILE__, __LINE__);test_assert_equal_file
assertion_setup(__FILE__, __LINE__);assertion_equal_file
/* Assert that a file is empty; supports printf-style arguments. */
#define assertEmptyFile \
test_setup(__FILE__, __LINE__);test_assert_empty_file
assertion_setup(__FILE__, __LINE__);assertion_empty_file
/* Assert that a file is not empty; supports printf-style arguments. */
#define assertNonEmptyFile \
assertion_setup(__FILE__, __LINE__);assertion_non_empty_file
#define assertFileAtime(pathname, sec, nsec) \
assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileAtimeRecent(pathname) \
assertion_file_atime_recent(__FILE__, __LINE__, pathname)
#define assertFileBirthtime(pathname, sec, nsec) \
assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileBirthtimeRecent(pathname) \
assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
/* Assert that a file exists; supports printf-style arguments. */
#define assertFileExists \
test_setup(__FILE__, __LINE__);test_assert_file_exists
assertion_setup(__FILE__, __LINE__);assertion_file_exists
/* Assert that a file exists; supports printf-style arguments. */
#define assertFileNotExists \
test_setup(__FILE__, __LINE__);test_assert_file_not_exists
assertion_setup(__FILE__, __LINE__);assertion_file_not_exists
/* Assert that file contents match a string; supports printf-style arguments. */
#define assertFileContents \
test_setup(__FILE__, __LINE__);test_assert_file_contents
assertion_setup(__FILE__, __LINE__);assertion_file_contents
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
#define assertFileNLinks(pathname, nlinks) \
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
#define assertTextFileContents \
test_setup(__FILE__, __LINE__);test_assert_text_file_contents
assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
#define assertIsDir(pathname, mode) \
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
#define assertIsHardlink(path1, path2) \
assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsNotHardlink(path1, path2) \
assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsReg(pathname, mode) \
assertion_is_reg(__FILE__, __LINE__, pathname, mode)
#define assertIsSymlink(pathname, contents) \
assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
/* Create a directory, report error if it fails. */
#define assertMakeDir(dirname, mode) \
assertion_make_dir(__FILE__, __LINE__, dirname, mode)
#define assertMakeFile(path, mode, contents) \
assertion_make_file(__FILE__, __LINE__, path, mode, contents)
#define assertMakeHardlink(newfile, oldfile) \
assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
#define assertMakeSymlink(newfile, linkto) \
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
#define assertUmask(mask) \
assertion_umask(__FILE__, __LINE__, mask)
/*
* This would be simple with C99 variadic macros, but I don't want to
@ -135,27 +213,60 @@
* 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_contents(const void *, int, const char *, ...);
int assertion_file_exists(const char *, ...);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
int assertion_file_not_exists(const char *, ...);
int assertion_file_size(const char *, int, const char *, long);
int assertion_is_dir(const char *, int, const char *, int);
int assertion_is_hardlink(const char *, int, const char *, const char *);
int assertion_is_not_hardlink(const char *, int, const char *, const char *);
int assertion_is_reg(const char *, int, const char *, int);
int assertion_is_symlink(const char *, int, const char *, const char *);
int assertion_make_dir(const char *, int, const char *, int);
int assertion_make_file(const char *, int, const char *, int, const char *);
int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
int assertion_make_symlink(const char *, int, const char *newpath, const char *);
int assertion_non_empty_file(const char *, ...);
int assertion_text_file_contents(const char *buff, const char *f);
int assertion_umask(const char *, int, int);
void assertion_setup(const char *, int);
void test_skipping(const char *fmt, ...);
int test_assert(const char *, int, int, const char *, void *);
int test_assert_empty_file(const char *, ...);
int test_assert_equal_file(const char *, const char *, ...);
int test_assert_equal_int(const char *, int, int, const char *, int, const char *, void *);
int test_assert_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
int test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
int test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *);
int test_assert_file_contents(const void *, int, const char *, ...);
int test_assert_text_file_contents(const char *buff, const char *f);
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, ...);
@ -168,4 +279,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;

View File

@ -39,11 +39,11 @@ DEFINE_TEST(test_0)
{
struct stat st;
failure("File %s does not exist?!", testprog);
if (!assertEqualInt(0, stat(testprog, &st)))
failure("File %s does not exist?!", testprogfile);
if (!assertEqualInt(0, stat(testprogfile, &st)))
exit(1);
failure("%s is not executable?!", testprog);
failure("%s is not executable?!", testprogfile);
if (!assert((st.st_mode & 0111) != 0))
exit(1);

View File

@ -26,106 +26,32 @@
__FBSDID("$FreeBSD$");
static void
verify_files(const char *target)
verify_files(const char *msg)
{
struct stat st, st2;
#if !defined(_WIN32) || defined(__CYGWIN__)
char buff[128];
#endif
int r;
/*
* Verify unpacked files.
*/
/* 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__)
/* Group members bits and others bits do not work. */
assertEqualInt(0600, st.st_mode & 0700);
#else
assertEqualInt(0644, st.st_mode & 0777);
#endif
assertEqualInt(10, st.st_size);
failure("file %s/file should have 2 links", target);
assertEqualInt(2, st.st_nlink);
}
assertIsReg("file", 0644);
failure(msg);
assertFileSize("file", 10);
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__)
/* Group members bits and others bits do not work. */
assertEqualInt(0600, st2.st_mode & 0700);
#else
assertEqualInt(0644, st2.st_mode & 0777);
#endif
assertEqualInt(10, st2.st_size);
failure("file %s/linkfile should have 2 links", 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 should be hardlinked",
target, target);
assertEqualInt(st.st_ino, st2.st_ino);
}
assertIsHardlink("linkfile", "file");
/* Symlink */
r = lstat("symlink", &st);
failure("Failed to stat file %s/symlink, errno=%d", target, errno);
assertEqualInt(r, 0);
#if !defined(_WIN32) || defined(__CYGWIN__)
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");
/* Another file with 1 link and different permissions. */
r = lstat("file2", &st);
failure("Failed to stat file %s/file2, errno=%d", target, errno);
assertEqualInt(r, 0);
if (r == 0) {
assert(S_ISREG(st.st_mode));
failure("%s/file2: st.st_mode = %o", target, st.st_mode);
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Execution bit and group members bits and others
* bits do not work. */
assertEqualInt(0600, st.st_mode & 0700);
#else
assertEqualInt(0777, st.st_mode & 0777);
#endif
assertEqualInt(10, st.st_size);
failure("file %s/file2 should have 1 link", target);
assertEqualInt(1, st.st_nlink);
}
assertIsReg("file2", 0777);
assertFileSize("file2", 10);
assertFileNLinks("file2", 1);
/* dir */
r = lstat("dir", &st);
if (r == 0) {
assertEqualInt(r, 0);
assert(S_ISDIR(st.st_mode));
failure("%s/dir: st.st_mode = %o", target, st.st_mode);
#if defined(_WIN32) && !defined(__CYGWIN__)
assertEqualInt(0700, st.st_mode & 0700);
#else
assertEqualInt(0775, st.st_mode & 0777);
#endif
}
assertIsDir("dir", 0775);
}
static void
@ -136,7 +62,7 @@ basic_cpio(const char *target,
{
int r;
if (!assertEqualInt(0, mkdir(target, 0775)))
if (!assertMakeDir(target, 0775))
return;
/* Use the cpio program to create an archive. */
@ -145,7 +71,7 @@ basic_cpio(const char *target,
failure("Error invoking %s -o %s", testprog, pack_options);
assertEqualInt(r, 0);
chdir(target);
assertChdir(target);
/* Verify stderr. */
failure("Expected: %s, options=%s", se, pack_options);
@ -163,9 +89,9 @@ basic_cpio(const char *target,
failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
assertTextFileContents(se, "unpack.err");
verify_files(target);
verify_files(pack_options);
chdir("..");
assertChdir("..");
}
static void
@ -173,7 +99,7 @@ passthrough(const char *target)
{
int r;
if (!assertEqualInt(0, mkdir(target, 0775)))
if (!assertMakeDir(target, 0775))
return;
/*
@ -184,77 +110,64 @@ passthrough(const char *target)
failure("Error invoking %s -p", testprog);
assertEqualInt(r, 0);
chdir(target);
assertChdir(target);
/* Verify stderr. */
failure("Error invoking %s -p in dir %s",
testprog, target);
assertTextFileContents("1 block\n", "stderr");
verify_files(target);
chdir("..");
verify_files("passthrough");
assertChdir("..");
}
DEFINE_TEST(test_basic)
{
int fd;
int filelist;
int oldumask;
FILE *filelist;
const char *msg;
oldumask = umask(0);
assertUmask(0);
/*
* Create an assortment of files on disk.
*/
filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
filelist = fopen("filelist", "w");
/* 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);
assertMakeFile("file", 0644, "1234567890");
fprintf(filelist, "file\n");
/* hardlink to above file. */
assertEqualInt(0, link("file", "linkfile"));
write(filelist, "linkfile\n", 9);
assertMakeHardlink("linkfile", "file");
fprintf(filelist, "linkfile\n");
/* Symlink to above file. */
assertEqualInt(0, symlink("file", "symlink"));
write(filelist, "symlink\n", 8);
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
fprintf(filelist, "symlink\n");
}
/* Another file with different permissions. */
fd = open("file2", O_CREAT | O_WRONLY, 0777);
assert(fd >= 0);
assertEqualInt(10, write(fd, "123456789", 10));
close(fd);
write(filelist, "file2\n", 6);
assertMakeFile("file2", 0777, "1234567890");
fprintf(filelist, "file2\n");
/* Directory. */
assertEqualInt(0, mkdir("dir", 0775));
write(filelist, "dir\n", 4);
assertMakeDir("dir", 0775);
fprintf(filelist, "dir\n");
/* All done. */
close(filelist);
fclose(filelist);
umask(022);
assertUmask(022);
/* Archive/dearchive with a variety of options. */
basic_cpio("copy", "", "", "2 blocks\n");
basic_cpio("copy_odc", "--format=odc", "", "2 blocks\n");
msg = canSymlink() ? "2 blocks\n" : "1 block\n";
basic_cpio("copy", "", "", msg);
basic_cpio("copy_odc", "--format=odc", "", msg);
basic_cpio("copy_newc", "-H newc", "", "2 blocks\n");
basic_cpio("copy_cpio", "-H odc", "", "2 blocks\n");
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
* On Windows, symbolic link does not work.
* Currentry copying file instead. therefore block size is
* different.
*/
basic_cpio("copy_ustar", "-H ustar", "", "10 blocks\n");
#else
basic_cpio("copy_ustar", "-H ustar", "", "9 blocks\n");
#endif
basic_cpio("copy_cpio", "-H odc", "", msg);
msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
basic_cpio("copy_ustar", "-H ustar", "", msg);
/* Copy in one step using -p */
passthrough("passthrough");
umask(oldumask);
}

View File

@ -0,0 +1,107 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD$");
/*
* Test the command-line parsing.
*/
DEFINE_TEST(test_cmdline)
{
FILE *f;
/* Create an empty file. */
f = fopen("empty", "wb");
assert(f != NULL);
fclose(f);
failure("-Q is an invalid option on every cpio program I know of");
assert(0 != systemf("%s -i -Q <empty >1.out 2>1.err", testprog));
assertEmptyFile("1.out");
failure("-f requires an argument");
assert(0 != systemf("%s -if <empty >2.out 2>2.err", testprog));
assertEmptyFile("2.out");
failure("-f requires an argument");
assert(0 != systemf("%s -i -f <empty >3.out 2>3.err", testprog));
assertEmptyFile("3.out");
failure("--format requires an argument");
assert(0 != systemf("%s -i --format <empty >4.out 2>4.err", testprog));
assertEmptyFile("4.out");
failure("--badopt is an invalid option");
assert(0 != systemf("%s -i --badop <empty >5.out 2>5.err", testprog));
assertEmptyFile("5.out");
failure("--badopt is an invalid option");
assert(0 != systemf("%s -i --badopt <empty >6.out 2>6.err", testprog));
assertEmptyFile("6.out");
failure("--n is ambiguous");
assert(0 != systemf("%s -i --n <empty >7.out 2>7.err", testprog));
assertEmptyFile("7.out");
failure("--create forbids an argument");
assert(0 != systemf("%s --create=arg <empty >8.out 2>8.err", testprog));
assertEmptyFile("8.out");
failure("-i with empty input should succeed");
assert(0 == systemf("%s -i <empty >9.out 2>9.err", testprog));
assertEmptyFile("9.out");
failure("-o with empty input should succeed");
assert(0 == systemf("%s -o <empty >10.out 2>10.err", testprog));
failure("-i -p is nonsense");
assert(0 != systemf("%s -i -p <empty >11.out 2>11.err", testprog));
assertEmptyFile("11.out");
failure("-p -i is nonsense");
assert(0 != systemf("%s -p -i <empty >12.out 2>12.err", testprog));
assertEmptyFile("12.out");
failure("-i -o is nonsense");
assert(0 != systemf("%s -i -o <empty >13.out 2>13.err", testprog));
assertEmptyFile("13.out");
failure("-o -i is nonsense");
assert(0 != systemf("%s -o -i <empty >14.out 2>14.err", testprog));
assertEmptyFile("14.out");
failure("-o -p is nonsense");
assert(0 != systemf("%s -o -p <empty >15.out 2>15.err", testprog));
assertEmptyFile("15.out");
failure("-p -o is nonsense");
assert(0 != systemf("%s -p -o <empty >16.out 2>16.err", testprog));
assertEmptyFile("16.out");
failure("-p with empty input should fail");
assert(0 != systemf("%s -p <empty >17.out 2>17.err", testprog));
assertEmptyFile("17.out");
}

View File

@ -25,6 +25,13 @@
#include "test.h"
__FBSDID("$FreeBSD$");
/* Number of bytes needed to pad 'n' to multiple of 'block', assuming
* that 'block' is a power of two. This trick can be more easily
* remembered as -n & (block - 1), but many compilers quite reasonably
* warn about "-n" when n is an unsigned value. (~(n) + 1) is the
* same thing, but written in a way that won't offend anyone. */
#define PAD(n, block) ((~(n) + 1) & ((block) - 1))
static int
is_hex(const char *p, size_t l)
{
@ -63,60 +70,67 @@ from_hex(const char *p, size_t l)
DEFINE_TEST(test_format_newc)
{
int fd, list;
FILE *list;
int r;
int devmajor, devminor, ino, gid;
int uid = -1;
time_t t, t2, now;
char *p, *e;
size_t s, fs, ns;
mode_t oldmask;
oldmask = umask(0);
assertUmask(0);
#if !defined(_WIN32)
uid = getuid();
#endif
/*
* Create an assortment of files.
* TODO: Extend this to cover more filetypes.
*/
list = open("list", O_CREAT | O_WRONLY, 0644);
list = fopen("list", "w");
/* "file1" */
fd = open("file1", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(10, write(fd, "123456789", 10));
close(fd);
assertEqualInt(6, write(list, "file1\n", 6));
assertMakeFile("file1", 0644, "1234567890");
fprintf(list, "file1\n");
/* "hardlink" */
assertEqualInt(0, link("file1", "hardlink"));
assertEqualInt(9, write(list, "hardlink\n", 9));
assertMakeHardlink("hardlink", "file1");
fprintf(list, "hardlink\n");
/* Another hardlink, but this one won't be archived. */
assertEqualInt(0, link("file1", "hardlink2"));
assertMakeHardlink("hardlink2", "file1");
/* "symlink" */
assertEqualInt(0, symlink("file1", "symlink"));
assertEqualInt(8, write(list, "symlink\n", 8));
if (canSymlink()) {
assertMakeSymlink("symlink", "file1");
fprintf(list, "symlink\n");
}
/* "dir" */
assertEqualInt(0, mkdir("dir", 0775));
assertEqualInt(4, write(list, "dir\n", 4));
assertMakeDir("dir", 0775);
fprintf(list, "dir\n");
/* Record some facts about what we just created: */
now = time(NULL); /* They were all created w/in last two seconds. */
/* Use the cpio program to create an archive. */
close(list);
fclose(list);
r = systemf("%s -o --format=newc <list >newc.out 2>newc.err",
testprog);
if (!assertEqualInt(r, 0))
return;
/* Verify that nothing went to stderr. */
if (canSymlink()) {
assertTextFileContents("2 blocks\n", "newc.err");
} else {
assertTextFileContents("1 block\n", "newc.err");
}
/* Verify that stdout is a well-formed cpio file in "newc" format. */
p = slurpfile(&s, "newc.out");
assertEqualInt(s, 1024);
assertEqualInt(s, canSymlink() ? 1024 : 512);
e = p;
/*
@ -134,7 +148,9 @@ DEFINE_TEST(test_format_newc)
#else
assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */
#endif
assertEqualInt(from_hex(e + 22, 8), getuid()); /* uid */
if (uid < 0)
uid = from_hex(e + 22, 8);
assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
gid = from_hex(e + 30, 8); /* gid */
assertEqualMem(e + 38, "00000003", 8); /* nlink */
t = from_hex(e + 46, 8); /* mtime */
@ -147,56 +163,47 @@ DEFINE_TEST(test_format_newc)
" field should be zero");
assertEqualInt(0, from_hex(e + 54, 8)); /* File size */
fs = from_hex(e + 54, 8);
fs += 3 & -fs;
fs += PAD(fs, 4);
devmajor = from_hex(e + 62, 8); /* devmajor */
devminor = from_hex(e + 70, 8); /* devminor */
assert(is_hex(e + 78, 8)); /* rdevmajor */
assert(is_hex(e + 86, 8)); /* rdevminor */
assertEqualMem(e + 94, "00000006", 8); /* Name size */
ns = from_hex(e + 94, 8);
ns += 3 & (-ns - 2);
ns += PAD(ns + 2, 4);
assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
assertEqualMem(e + 110, "file1\0", 6); /* Name contents */
/* Since there's another link, no file contents here. */
/* But add in file size so that an error here doesn't cascade. */
e += 110 + fs + ns;
if (canSymlink()) {
/* "symlink" pointing to "file1" */
assert(is_hex(e, 110));
assertEqualMem(e + 0, "070701", 6); /* Magic */
assert(is_hex(e + 6, 8)); /* ino */
#if !defined(_WIN32) || defined(__CYGWIN__)
/* On Windows, symbolic link and group members bits and
* others bits do not work. */
assertEqualInt(0xa1ff, from_hex(e + 14, 8)); /* Mode */
#endif
assertEqualInt(from_hex(e + 22, 8), getuid()); /* uid */
assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
assertEqualMem(e + 38, "00000001", 8); /* nlink */
t2 = from_hex(e + 46, 8); /* mtime */
failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Symbolic link does not work. */
assertEqualMem(e + 54, "0000000a", 8); /* File size */
#else
assertEqualMem(e + 54, "00000005", 8); /* File size */
#endif
fs = from_hex(e + 54, 8);
fs += 3 & -fs;
fs += PAD(fs, 4);
assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */
assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */
assert(is_hex(e + 78, 8)); /* rdevmajor */
assert(is_hex(e + 86, 8)); /* rdevminor */
assertEqualMem(e + 94, "00000008", 8); /* Name size */
ns = from_hex(e + 94, 8);
ns += 3 & (-ns - 2);
ns += PAD(ns + 2, 4);
assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
assertEqualMem(e + 110, "symlink\0\0\0", 10); /* Name contents */
#if !defined(_WIN32) || defined(__CYGWIN__)
assertEqualMem(e + 110 + ns, "file1\0\0\0", 8); /* symlink target */
#endif
e += 110 + fs + ns;
}
/* "dir" */
assert(is_hex(e, 110));
@ -206,9 +213,10 @@ DEFINE_TEST(test_format_newc)
/* Group members bits and others bits do not work. */
assertEqualInt(0x41c0, from_hex(e + 14, 8) & 0xffc0); /* Mode */
#else
assertEqualInt(0x41fd, from_hex(e + 14, 8)); /* Mode */
/* Mode: sgid bit sometimes propagates from parent dirs, ignore it. */
assertEqualInt(040775, from_hex(e + 14, 8) & ~02000);
#endif
assertEqualInt(from_hex(e + 22, 8), getuid()); /* uid */
assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
#ifndef NLINKS_INACCURATE_FOR_DIRS
assertEqualMem(e + 38, "00000002", 8); /* nlink */
@ -218,14 +226,14 @@ DEFINE_TEST(test_format_newc)
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualMem(e + 54, "00000000", 8); /* File size */
fs = from_hex(e + 54, 8);
fs += 3 & -fs;
fs += PAD(fs, 4);
assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */
assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */
assert(is_hex(e + 78, 8)); /* rdevmajor */
assert(is_hex(e + 86, 8)); /* rdevminor */
assertEqualMem(e + 94, "00000004", 8); /* Name size */
ns = from_hex(e + 94, 8);
ns += 3 & (-ns - 2);
ns += PAD(ns + 2, 4);
assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
assertEqualMem(e + 110, "dir\0\0\0", 6); /* Name contents */
e += 110 + fs + ns;
@ -243,7 +251,7 @@ DEFINE_TEST(test_format_newc)
#else
assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */
#endif
assertEqualInt(from_hex(e + 22, 8), getuid()); /* uid */
assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
assertEqualMem(e + 38, "00000003", 8); /* nlink */
t2 = from_hex(e + 46, 8); /* mtime */
@ -251,17 +259,17 @@ DEFINE_TEST(test_format_newc)
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualInt(10, from_hex(e + 54, 8)); /* File size */
fs = from_hex(e + 54, 8);
fs += 3 & -fs;
fs += PAD(fs, 4);
assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */
assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */
assert(is_hex(e + 78, 8)); /* rdevmajor */
assert(is_hex(e + 86, 8)); /* rdevminor */
assertEqualMem(e + 94, "00000009", 8); /* Name size */
ns = from_hex(e + 94, 8);
ns += 3 & (-ns - 2);
ns += PAD(ns + 2, 4);
assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
assertEqualMem(e + 110, "hardlink\0\0", 10); /* Name contents */
assertEqualMem(e + 110 + ns, "123456789\0\0\0", 12); /* File contents */
assertEqualMem(e + 110 + ns, "1234567890\0\0", 12); /* File contents */
e += 110 + ns + fs;
/* Last entry is end-of-archive marker. */
@ -283,6 +291,4 @@ DEFINE_TEST(test_format_newc)
assertEqualMem(e + 110, "TRAILER!!!\0\0", 12); /* Name */
free(p);
umask(oldmask);
}

View File

@ -28,15 +28,11 @@ __FBSDID("$FreeBSD$");
static void
unpack_test(const char *from, const char *options, const char *se)
{
struct stat st, st2;
#if !defined(_WIN32) || defined(__CYGWIN__)
char buff[128];
#endif
int r;
/* Create a work dir named after the file we're unpacking. */
assertEqualInt(0, mkdir(from, 0775));
chdir(from);
assertMakeDir(from, 0775);
assertChdir(from);
/*
* Use cpio to unpack the sample archive
@ -49,96 +45,64 @@ unpack_test(const char *from, const char *options, const char *se)
assertEqualInt(r, 0);
/* Verify that nothing went to stderr. */
failure("Error invoking %s -i %s < %s", testprog, options, from);
if (canSymlink()) {
failure("Error invoking %s -i %s < %s",
testprog, options, from);
assertTextFileContents(se, "unpack.err");
}
/*
* Verify unpacked files.
*/
/* Regular file with 2 links. */
r = lstat("file", &st);
failure("Failed to stat file %s/file, errno=%d", from, errno);
assertEqualInt(r, 0);
if (r == 0) {
assert(S_ISREG(st.st_mode));
#if defined(_WIN32) && !defined(__CYGWIN__)
assertEqualInt(0600, st.st_mode & 0700);
#else
assertEqualInt(0644, st.st_mode & 0777);
#endif
failure("file %s/file", from);
assertEqualInt(10, st.st_size);
failure("file %s/file", from);
assertEqualInt(2, st.st_nlink);
}
assertIsReg("file", 0644);
failure("%s", from);
assertFileSize("file", 10);
assertFileSize("linkfile", 10);
failure("%s", from);
assertFileNLinks("file", 2);
/* Another name for the same file. */
r = lstat("linkfile", &st2);
failure("Failed to stat file %s/linkfile, errno=%d", from, errno);
assertEqualInt(r, 0);
if (r == 0) {
assert(S_ISREG(st2.st_mode));
#if defined(_WIN32) && !defined(__CYGWIN__)
assertEqualInt(0600, st2.st_mode & 0700);
#else
assertEqualInt(0644, st2.st_mode & 0777);
#endif
failure("file %s/file", from);
assertEqualInt(10, st2.st_size);
failure("file %s/file", from);
assertEqualInt(2, st2.st_nlink);
failure("file and linkfile should be hardlinked");
assertEqualInt(st.st_dev, st2.st_dev);
failure("file %s/file", from);
assertEqualInt(st.st_ino, st2.st_ino);
}
failure("%s", from);
assertIsHardlink("linkfile", "file");
assertFileSize("file", 10);
assertFileSize("linkfile", 10);
/* Symlink */
r = lstat("symlink", &st);
failure("Failed to stat file %s/symlink, errno=%d", from, errno);
assertEqualInt(r, 0);
#if !defined(_WIN32) || defined(__CYGWIN__)
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(0700, st.st_mode & 0700);
#else
assertEqualInt(0775, st.st_mode & 0777);
#endif
}
assertIsDir("dir", 0775);
chdir("..");
assertChdir("..");
}
DEFINE_TEST(test_gcpio_compat)
{
int oldumask;
oldumask = umask(0);
assertUmask(0);
/* Dearchive sample files with a variety of options. */
unpack_test("test_gcpio_compat_ref.bin", "", "1 block\n");
unpack_test("test_gcpio_compat_ref.crc", "", "2 blocks\n");
unpack_test("test_gcpio_compat_ref.newc", "", "2 blocks\n");
if (canSymlink()) {
unpack_test("test_gcpio_compat_ref.bin",
"--no-preserve-owner", "1 block\n");
unpack_test("test_gcpio_compat_ref.crc",
"--no-preserve-owner", "2 blocks\n");
unpack_test("test_gcpio_compat_ref.newc",
"--no-preserve-owner", "2 blocks\n");
/* gcpio-2.9 only reads 6 blocks here */
unpack_test("test_gcpio_compat_ref.ustar", "", "7 blocks\n");
umask(oldumask);
unpack_test("test_gcpio_compat_ref.ustar",
"--no-preserve-owner", "7 blocks\n");
} else {
unpack_test("test_gcpio_compat_ref_nosym.bin",
"--no-preserve-owner", "1 block\n");
unpack_test("test_gcpio_compat_ref_nosym.crc",
"--no-preserve-owner", "2 blocks\n");
unpack_test("test_gcpio_compat_ref_nosym.newc",
"--no-preserve-owner", "2 blocks\n");
/* gcpio-2.9 only reads 6 blocks here */
unpack_test("test_gcpio_compat_ref_nosym.ustar",
"--no-preserve-owner", "7 blocks\n");
}
}

View File

@ -0,0 +1,17 @@
$FreeBSD$
begin 644 test_gcpio_compat_ref_nosym.bin
MQW%4`-[Z_4'H`^@#`@`VNZU*NQX$``````!D:7(`QW%4`-SZI('H`^@#`@`G
MNZU*NQX%````"@!F:6QE```Q,C,T-38W.#D*QW%4`-SZI('H`^@#`@`GNZU*
MNQX)````"@!L:6YK9FEL90``,3(S-#4V-S@Y"L=Q``````````````$`````
M````"P``````5%)!24Q%4B$A(0``````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
1````````````````````````
`
end

View File

@ -0,0 +1,17 @@
$FreeBSD$
begin 644 test_gcpio_compat_ref_nosym.crc
M,#<P-S`R,#`U-D9!1$4P,#`P-#%&1#`P,#`P,T4X,#`P,#`S13@P,#`P,#`P
M,C1!040Q14)",#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4T,#`P,#`P0D(P,35"
M,#`S-C`P,#`P,#`T,#`P,#`P,#!D:7(````P-S`W,#(P,#4V1D%$0S`P,#`X
M,4$T,#`P,#`S13@P,#`P,#-%.#`P,#`P,#`R-$%!1#%%0D(P,#`P,#`P,#`P
M,#`P,#`P,#`P,#`P-30P,#`P,#!"0C`Q-4(P,#(W,#`P,#`P,#4P,#`P,#`P
M,&9I;&4``#`W,#<P,C`P-39&041#,#`P,#@Q030P,#`P,#-%.#`P,#`P,T4X
M,#`P,#`P,#(T04%$,45"0C`P,#`P,#!!,#`P,#`P,#`P,#`P,#`U-#`P,#`P
M,$)",#$U0C`P,C<P,#`P,#`P.3`P,#`P,44W;&EN:V9I;&4``#$R,S0U-C<X
M.0H``#`W,#<P,C`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
M,#`P,#$P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
M,#`P,#`P,#`P,#`P,#`P0C`P,#`P,#`P5%)!24Q%4B$A(0``````````````
1````````````````````````
`
end

View File

@ -0,0 +1,17 @@
$FreeBSD$
begin 644 test_gcpio_compat_ref_nosym.newc
M,#<P-S`Q,#`U-D9!1$4P,#`P-#%&1#`P,#`P,T4X,#`P,#`S13@P,#`P,#`P
M,C1!040Q14)",#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4T,#`P,#`P0D(P,35"
M,#`S-C`P,#`P,#`T,#`P,#`P,#!D:7(````P-S`W,#$P,#4V1D%$0S`P,#`X
M,4$T,#`P,#`S13@P,#`P,#-%.#`P,#`P,#`R-$%!1#%%0D(P,#`P,#`P,#`P
M,#`P,#`P,#`P,#`P-30P,#`P,#!"0C`Q-4(P,#(W,#`P,#`P,#4P,#`P,#`P
M,&9I;&4``#`W,#<P,3`P-39&041#,#`P,#@Q030P,#`P,#-%.#`P,#`P,T4X
M,#`P,#`P,#(T04%$,45"0C`P,#`P,#!!,#`P,#`P,#`P,#`P,#`U-#`P,#`P
M,$)",#$U0C`P,C<P,#`P,#`P.3`P,#`P,#`P;&EN:V9I;&4``#$R,S0U-C<X
M.0H``#`W,#<P,3`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
M,#`P,#$P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
M,#`P,#`P,#`P,#`P,#`P0C`P,#`P,#`P5%)!24Q%4B$A(0``````````````
1````````````````````````
`
end

View File

@ -0,0 +1,74 @@
$FreeBSD$
begin 644 test_gcpio_compat_ref_nosym.ustar
M9&ER+P``````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`W-S4`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`P,#`P
M`#$Q,C4S,C$W,C<S`#`P,3$S-3$`-0``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
M````````````````````````````````````=&EM````````````````````
M```````````````````P,#`P,C<S`#8V,#`P-C8`````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````!F:6QE````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````,#`P,#8T-``P,#`Q-S4P`#`P
M,#$W-3``,#`P,#`P,#`P,3(`,3$R-3,R,3<R-S,`,#`Q,30R,P`P````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````'5S=&%R`#`P=&EM``````````````````````````````````````!T
M:6T``````````````````````````````````````#`P,#`R-S,`-C8P,#`T
M-P``````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````#$R,S0U-C<X.0H`
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````;&EN:V9I;&4`````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P
M,#`P,#`P`#$Q,C4S,C$W,C<S`#`P,3,Q,S<`,69I;&4`````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!U<W1A<@`P
M,'1I;0``````````````````````````````````````=&EM````````````
M```````````````````````````P,#`P,C<S`#8V,#`P-#<`````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
,````````````````
`
end

View File

@ -26,29 +26,27 @@
__FBSDID("$FreeBSD$");
DEFINE_TEST(test_option_B)
DEFINE_TEST(test_option_B_upper)
{
struct stat st;
int r, fd;
int r;
/*
* Create a file on disk.
*/
fd = open("file", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
close(fd);
assertMakeFile("file", 0644, NULL);
/* Create an archive without -B; this should be 512 bytes. */
r = systemf("echo file | %s -o > small.cpio 2>small.err", testprog);
assertEqualInt(r, 0);
assertFileContents("1 block\n", 8, "small.err");
assertTextFileContents("1 block\n", "small.err");
assertEqualInt(0, stat("small.cpio", &st));
assertEqualInt(512, st.st_size);
/* Create an archive with -B; this should be 5120 bytes. */
r = systemf("echo file | %s -oB > large.cpio 2>large.err", testprog);
assertEqualInt(r, 0);
assertFileContents("1 block\n", 8, "large.err");
assertTextFileContents("1 block\n", "large.err");
assertEqualInt(0, stat("large.cpio", &st));
assertEqualInt(5120, st.st_size);
}

View File

@ -6,8 +6,7 @@
* 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.
* 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.
@ -22,21 +21,42 @@
* 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_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
DEFINE_TEST(test_option_C_upper)
{
int r;
/* Note that "^" and "$" are not special unless you set the corresponding
* flag above. */
/*
* Create a file on disk.
*/
assertMakeFile("file", 0644, NULL);
int pathmatch(const char *p, const char *s, int flags);
/* Create an archive without -C; this should be 512 bytes. */
r = systemf("echo file | %s -o > small.cpio 2>small.err", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "small.err");
assertFileSize("small.cpio", 512);
#endif
/* Create an archive with -C 513; this should be 513 bytes. */
r = systemf("echo file | %s -o -C 513 > 513.cpio 2>513.err",
testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "513.err");
assertFileSize("513.cpio", 513);
/* Create an archive with -C 12345; this should be 12345 bytes. */
r = systemf("echo file | %s -o -C12345 > 12345.cpio 2>12345.err",
testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "12345.err");
assertFileSize("12345.cpio", 12345);
/* Create an archive with invalid -C request */
assert(0 != systemf("echo file | %s -o -C > bad.cpio 2>bad.err",
testprog));
assertEmptyFile("bad.cpio");
}

View File

@ -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,36 @@
* 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
DEFINE_TEST(test_option_J_upper)
{
char *p;
int r;
size_t s;
#if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
#define __LA_DEAD __attribute__((__noreturn__))
#else
#define __LA_DEAD
#endif
/* Create a file. */
assertMakeFile("f", 0644, "a");
extern const char *progname;
void warnc(int code, const char *fmt, ...);
void errc(int eval, int code, const char *fmt, ...) __LA_DEAD;
#endif
/* Archive it with xz compression. */
r = systemf("echo f | %s -o -J >archive.out 2>archive.err",
testprog);
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (r != 0) {
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without xz support");
return;
}
failure("-J option is broken");
assertEqualInt(r, 0);
return;
}
/* Check that the archive file has an xz signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\3757zXZ", 5);
}

View File

@ -25,60 +25,77 @@
#include "test.h"
__FBSDID("$FreeBSD$");
DEFINE_TEST(test_option_L)
/* This is a little pointless, as Windows doesn't support symlinks
* (except for the seriously crippled CreateSymbolicLink API) so these
* tests won't run on Windows. */
#if defined(_WIN32) && !defined(__CYGWIN__)
#define CAT "type"
#else
#define CAT "cat"
#endif
DEFINE_TEST(test_option_L_upper)
{
struct stat st;
int fd, filelist;
FILE *filelist;
int r;
filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
if (!canSymlink()) {
skipping("Symlink tests");
return;
}
filelist = fopen("filelist", "w");
/* Create a file and a symlink to the file. */
fd = open("file", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(10, write(fd, "123456789", 10));
close(fd);
write(filelist, "file\n", 5);
assertMakeFile("file", 0644, "1234567890");
fprintf(filelist, "file\n");
/* Symlink to above file. */
assertEqualInt(0, symlink("file", "symlink"));
write(filelist, "symlink\n", 8);
assertMakeSymlink("symlink", "file");
fprintf(filelist, "symlink\n");
close(filelist);
fclose(filelist);
r = systemf("cat filelist | %s -pd copy >copy.out 2>copy.err", testprog);
r = systemf(CAT " filelist | %s -pd copy >copy.out 2>copy.err", testprog);
assertEqualInt(r, 0);
assertEqualInt(0, lstat("copy/symlink", &st));
failure("Regular -p without -L should preserve symlinks.");
assert(S_ISLNK(st.st_mode));
assertTextFileContents("1 block\n", "copy.err");
r = systemf("cat filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog);
failure("Regular -p without -L should preserve symlinks.");
assertIsSymlink("copy/symlink", NULL);
r = systemf(CAT " filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("copy-L.out");
assertFileContents("1 block\n", 8, "copy-L.err");
assertEqualInt(0, lstat("copy-L/symlink", &st));
assertTextFileContents("1 block\n", "copy-L.err");
failure("-pdL should dereference symlinks and turn them into files.");
assert(!S_ISLNK(st.st_mode));
assertIsReg("copy-L/symlink", -1);
r = systemf("cat filelist | %s -o >archive.out 2>archive.err", testprog);
r = systemf(CAT " filelist | %s -o >archive.out 2>archive.err", testprog);
failure("Error invoking %s -o ", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "archive.err");
assertEqualInt(0, mkdir("unpack", 0755));
r = systemf("cat archive.out | (cd unpack ; %s -i >unpack.out 2>unpack.err)", testprog);
assertMakeDir("unpack", 0755);
assertChdir("unpack");
r = systemf(CAT " ../archive.out | %s -i >unpack.out 2>unpack.err", testprog);
failure("Error invoking %s -i", testprog);
assertEqualInt(r, 0);
assertEqualInt(0, lstat("unpack/symlink", &st));
assert(S_ISLNK(st.st_mode));
assertTextFileContents("1 block\n", "unpack.err");
assertChdir("..");
r = systemf("cat filelist | %s -oL >archive-L.out 2>archive-L.err", testprog);
assertIsSymlink("unpack/symlink", NULL);
r = systemf(CAT " filelist | %s -oL >archive-L.out 2>archive-L.err", testprog);
failure("Error invoking %s -oL", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "archive-L.err");
assertEqualInt(0, mkdir("unpack-L", 0755));
r = systemf("cat archive-L.out | (cd unpack-L ; %s -i >unpack-L.out 2>unpack-L.err)", testprog);
assertMakeDir("unpack-L", 0755);
assertChdir("unpack-L");
r = systemf(CAT " ../archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
failure("Error invoking %s -i < archive-L.out", testprog);
assertEqualInt(r, 0);
assertEqualInt(0, lstat("unpack-L/symlink", &st));
assert(!S_ISLNK(st.st_mode));
assertTextFileContents("1 block\n", "unpack-L.err");
assertChdir("..");
assertIsReg("unpack-L/symlink", -1);
}

View File

@ -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,17 +21,36 @@
* 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_LINE_READER_H
#define LAFE_LINE_READER_H
DEFINE_TEST(test_option_Z_upper)
{
char *p;
int r;
size_t s;
struct line_reader;
/* Create a file. */
assertMakeFile("f", 0644, "a");
struct line_reader *line_reader(const char *, int nullSeparator);
const char *line_reader_next(struct line_reader *);
void line_reader_free(struct line_reader *);
#endif
/* Archive it with compress compression. */
r = systemf("echo f | %s -oZ >archive.out 2>archive.err",
testprog);
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (r != 0) {
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without compress support");
return;
}
failure("-Z option is broken");
assertEqualInt(r, 0);
return;
}
/* Check that the archive file has a compress signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x1f\x9d", 2);
}

View File

@ -23,10 +23,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <sys/utime.h>
#else
#if defined(HAVE_UTIME_H)
#include <utime.h>
#elif defined(HAVE_SYS_UTIME_H)
#include <sys/utime.h>
#endif
__FBSDID("$FreeBSD$");
@ -57,19 +57,15 @@ test_create(void)
struct utimbuf times;
static const int numfiles = sizeof(files) / sizeof(files[0]);
int i;
int fd;
for (i = 0; i < numfiles; ++i) {
fd = open(files[i].name, O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
/*
* Note: Have to write at least one byte to the file.
* cpio doesn't bother reading the file if it's zero length,
* so the atime never gets changed in that case, which
* makes the tests below rather pointless.
*/
assertEqualInt(1, write(fd, "a", 1));
close(fd);
assertMakeFile(files[i].name, 0644, "a");
/* If utime() isn't supported on your platform, just
* #ifdef this section out. Most of the test below is
@ -87,26 +83,21 @@ test_create(void)
}
/* Wait until the atime on the last file is actually in the past. */
/* If utime() is supported above, there's no sleep here which
* makes the test faster. */
while (files[numfiles - 1].atime_sec >= time(NULL))
sleep(1);
sleepUntilAfter(files[numfiles - 1].atime_sec);
}
DEFINE_TEST(test_option_a)
{
struct stat st;
int r;
int f;
char buff[64];
char *p;
/* Create all of the test files. */
test_create();
/* Sanity check; verify that atimes really do get modified. */
f = open(files[0].name, O_RDONLY);
assertEqualInt(1, read(f,buff, 1));
assertEqualInt(0, close(f));
assert((p = slurpfile(NULL, "f0")) != NULL);
free(p);
assertEqualInt(0, stat("f0", &st));
if (st.st_atime == files[0].atime_sec) {
skipping("Cannot verify -a option\n"

View File

@ -53,41 +53,44 @@ from_octal(const char *p, size_t l)
DEFINE_TEST(test_option_c)
{
int fd, filelist;
FILE *filelist;
int r;
int uid = -1;
int dev, ino, gid;
time_t t, now;
char *p, *e;
size_t s;
mode_t oldmask;
oldmask = umask(0);
assertUmask(0);
#if !defined(_WIN32)
uid = getuid();
#endif
/*
* Create an assortment of files.
* TODO: Extend this to cover more filetypes.
*/
filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
filelist = fopen("filelist", "w");
/* "file" */
fd = open("file", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(10, write(fd, "123456789", 10));
close(fd);
assertEqualInt(5, write(filelist, "file\n", 5));
assertMakeFile("file", 0644, "1234567890");
fprintf(filelist, "file\n");
/* "symlink" */
assertEqualInt(0, symlink("file", "symlink"));
assertEqualInt(8, write(filelist, "symlink\n", 8));
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
fprintf(filelist, "symlink\n");
}
/* "dir" */
assertEqualInt(0, mkdir("dir", 0775));
assertMakeDir("dir", 0775);
/* Record some facts about what we just created: */
now = time(NULL); /* They were all created w/in last two seconds. */
assertEqualInt(4, write(filelist, "dir\n", 4));
fprintf(filelist, "dir\n");
/* Use the cpio program to create an archive. */
close(filelist);
fclose(filelist);
r = systemf("%s -oc <filelist >basic.out 2>basic.err", testprog);
/* Verify that nothing went to stderr. */
assertTextFileContents("1 block\n", "basic.err");
@ -120,7 +123,9 @@ DEFINE_TEST(test_option_c)
#else
assertEqualMem(e + 18, "100644", 6); /* Mode */
#endif
assertEqualInt(from_octal(e + 24, 6), getuid()); /* uid */
if (uid < 0)
uid = from_octal(e + 24, 6);
assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
assert(is_octal(e + 30, 6)); /* gid */
gid = from_octal(e + 30, 6);
assertEqualMem(e + 36, "000001", 6); /* nlink */
@ -133,20 +138,21 @@ DEFINE_TEST(test_option_c)
assertEqualMem(e + 59, "000005", 6); /* Name size */
assertEqualMem(e + 65, "00000000012", 11); /* File size */
assertEqualMem(e + 76, "file\0", 5); /* Name contents */
assertEqualMem(e + 81, "123456789\0", 10); /* File contents */
assertEqualMem(e + 81, "1234567890", 10); /* File contents */
e += 91;
/* Second entry is "symlink" pointing to "file" */
/* "symlink" pointing to "file" */
if (canSymlink()) {
assert(is_octal(e, 76)); /* Entire header is octal digits. */
assertEqualMem(e + 0, "070707", 6); /* Magic */
assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */
assert(dev != from_octal(e + 12, 6)); /* ino */
assert(ino != from_octal(e + 12, 6)); /* ino */
#if !defined(_WIN32) || defined(__CYGWIN__)
/* On Windows, symbolic link and group members bits and
* others bits do not work. */
assertEqualMem(e + 18, "120777", 6); /* Mode */
#endif
assertEqualInt(from_octal(e + 24, 6), getuid()); /* uid */
assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
assertEqualInt(gid, from_octal(e + 30, 6)); /* gid */
assertEqualMem(e + 36, "000001", 6); /* nlink */
failure("file entries should have rdev == 0 (dev was 0%o)",
@ -156,23 +162,13 @@ DEFINE_TEST(test_option_c)
assert(t <= now); /* File wasn't created in future. */
assert(t >= now - 2); /* File was created w/in last 2 secs. */
assertEqualMem(e + 59, "000010", 6); /* Name size */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* On Windows, symbolic link does not work. */
assertEqualMem(e + 65, "00000000012", 11); /* File size */
#else
assertEqualMem(e + 65, "00000000004", 11); /* File size */
#endif
assertEqualMem(e + 76, "symlink\0", 8); /* Name contents */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* On Windows, symbolic link does not work. */
assertEqualMem(e + 84, "123456789\0", 10); /* File contents. */
e += 94;
#else
assertEqualMem(e + 84, "file", 4); /* Symlink target. */
e += 88;
#endif
}
/* Second entry is "dir" */
/* "dir" */
assert(is_octal(e, 76));
assertEqualMem(e + 0, "070707", 6); /* Magic */
/* Dev should be same as first entry. */
@ -185,9 +181,11 @@ DEFINE_TEST(test_option_c)
/* Group members bits and others bits do not work. */
assertEqualMem(e + 18, "040777", 6); /* Mode */
#else
/* Accept 042775 to accomodate systems where sgid bit propagates. */
if (memcmp(e + 18, "042775", 6) != 0)
assertEqualMem(e + 18, "040775", 6); /* Mode */
#endif
assertEqualInt(from_octal(e + 24, 6), getuid()); /* uid */
assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
/* Gid should be same as first entry. */
assert(is_octal(e + 30, 6)); /* gid */
assertEqualInt(gid, from_octal(e + 30, 6));
@ -220,6 +218,4 @@ DEFINE_TEST(test_option_c)
assertEqualMem(e + 76, "TRAILER!!!\0", 11); /* Name */
free(p);
umask(oldmask);
}

View File

@ -28,41 +28,37 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_option_d)
{
struct stat st;
int r, fd;
int r;
/*
* Create a file in a directory.
*/
assertEqualInt(0, mkdir("dir", 0755));
fd = open("dir/file", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
close(fd);
assertMakeDir("dir", 0755);
assertMakeFile("dir/file", 0644, NULL);
/* Create an archive. */
r = systemf("echo dir/file | %s -o > archive.cpio 2>archive.err", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "archive.err");
assertEqualInt(0, stat("archive.cpio", &st));
assertEqualInt(512, st.st_size);
assertFileSize("archive.cpio", 512);
/* Dearchive without -d, this should fail. */
assertEqualInt(0, mkdir("without-d", 0755));
assertEqualInt(0, chdir("without-d"));
assertMakeDir("without-d", 0755);
assertChdir("without-d");
r = systemf("%s -i < ../archive.cpio >out 2>err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("out");
/* And the file should not be restored. */
assert(0 != stat("dir/file", &st));
assertFileNotExists("dir/file");
/* Dearchive with -d, this should succeed. */
assertEqualInt(0, chdir(".."));
assertEqualInt(0, mkdir("with-d", 0755));
assertEqualInt(0, chdir("with-d"));
assertChdir("..");
assertMakeDir("with-d", 0755);
assertChdir("with-d");
r = systemf("%s -id < ../archive.cpio >out 2>err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("out");
assertTextFileContents("1 block\n", "err");
/* And the file should be restored. */
assertEqualInt(0, stat("dir/file", &st));
assertFileExists("dir/file");
}

View File

@ -33,44 +33,44 @@ unpack(const char *dirname, const char *option)
{
int r;
assertEqualInt(0, mkdir(dirname, 0755));
assertEqualInt(0, chdir(dirname));
assertMakeDir(dirname, 0755);
assertChdir(dirname);
extract_reference_file("test_option_f.cpio");
r = systemf("%s -i %s < test_option_f.cpio > copy-no-a.out 2>copy-no-a.err", testprog, option);
assertEqualInt(0, r);
assertEqualInt(0, chdir(".."));
assertChdir("..");
}
DEFINE_TEST(test_option_f)
{
/* Calibrate: No -f option, so everything should be extracted. */
unpack("t0", "");
assertEqualInt(0, access("t0/a123", F_OK));
assertEqualInt(0, access("t0/a234", F_OK));
assertEqualInt(0, access("t0/b123", F_OK));
assertEqualInt(0, access("t0/b234", F_OK));
unpack("t0", "--no-preserve-owner");
assertFileExists("t0/a123");
assertFileExists("t0/a234");
assertFileExists("t0/b123");
assertFileExists("t0/b234");
/* Don't extract 'a*' files. */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Single quotes isn't used by command.exe. */
unpack("t1", "-f a*");
unpack("t1", "--no-preserve-owner -f a*");
#else
unpack("t1", "-f 'a*'");
unpack("t1", "--no-preserve-owner -f 'a*'");
#endif
assert(0 != access("t1/a123", F_OK));
assert(0 != access("t1/a234", F_OK));
assertEqualInt(0, access("t1/b123", F_OK));
assertEqualInt(0, access("t1/b234", F_OK));
assertFileNotExists("t1/a123");
assertFileNotExists("t1/a234");
assertFileExists("t1/b123");
assertFileExists("t1/b234");
/* Don't extract 'b*' files. */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Single quotes isn't used by command.exe. */
unpack("t2", "-f b*");
unpack("t2", "--no-preserve-owner -f b*");
#else
unpack("t2", "-f 'b*'");
unpack("t2", "--no-preserve-owner -f 'b*'");
#endif
assertEqualInt(0, access("t2/a123", F_OK));
assertEqualInt(0, access("t2/a234", F_OK));
assert(0 != access("t2/b123", F_OK));
assert(0 != access("t2/b234", F_OK));
assertFileExists("t2/a123");
assertFileExists("t2/a234");
assertFileNotExists("t2/b123");
assertFileNotExists("t2/b234");
}

View File

@ -51,6 +51,7 @@ DEFINE_TEST(test_option_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_option_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_option_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");

View File

@ -25,26 +25,12 @@
#include "test.h"
__FBSDID("$FreeBSD$");
/*
* This is called "test_option_ell" instead of "test_option_l" to
* avoid any conflicts with "test_option_L" on case-insensitive
* filesystems.
*/
DEFINE_TEST(test_option_ell)
DEFINE_TEST(test_option_l)
{
struct stat st, st2;
int fd;
int r;
/* Create a file. */
fd = open("f", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(1, write(fd, "a", 1));
close(fd);
/* Stat it. */
assertEqualInt(0, stat("f", &st));
assertMakeFile("f", 0644, "a");
/* Copy the file to the "copy" dir. */
r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
@ -52,8 +38,7 @@ DEFINE_TEST(test_option_ell)
assertEqualInt(r, 0);
/* Check that the copy is a true copy and not a link. */
assertEqualInt(0, stat("copy/f", &st2));
assert(st2.st_ino != st.st_ino);
assertIsNotHardlink("f", "copy/f");
/* Copy the file to the "link" dir with the -l option. */
r = systemf("echo f | %s -pld link >link.out 2>link.err",
@ -61,6 +46,5 @@ DEFINE_TEST(test_option_ell)
assertEqualInt(r, 0);
/* Check that this is a link and not a copy. */
assertEqualInt(0, stat("link/f", &st2));
assert(st2.st_ino == st.st_ino);
assertIsHardlink("f", "link/f");
}

View File

@ -6,8 +6,7 @@
* 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.
* 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.
@ -23,52 +22,35 @@
* (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 "cpio_platform.h"
#include "test.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 *progname;
static void
vwarnc(int code, const char *fmt, va_list ap)
DEFINE_TEST(test_option_lzma)
{
fprintf(stderr, "%s: ", progname);
vfprintf(stderr, fmt, ap);
if (code != 0)
fprintf(stderr, ": %s", strerror(code));
fprintf(stderr, "\n");
char *p;
int r;
size_t s;
/* Create a file. */
assertMakeFile("f", 0644, "a");
/* Archive it with lzma compression. */
r = systemf("echo f | %s -o --lzma >archive.out 2>archive.err",
testprog);
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (r != 0) {
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without lzma support");
return;
}
void
warnc(int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnc(code, fmt, ap);
va_end(ap);
failure("--lzma option is broken");
assertEqualInt(r, 0);
return;
}
void
errc(int eval, int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnc(code, fmt, ap);
va_end(ap);
exit(eval);
/* Check that the archive file has an lzma signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x5d\00\00", 3);
}

View File

@ -28,9 +28,7 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_option_m)
{
struct stat st;
int r;
time_t now;
/*
* The reference archive has one file with an mtime in 1970, 1
@ -38,33 +36,28 @@ DEFINE_TEST(test_option_m)
*/
/* Restored without -m, the result should have a current mtime. */
assertEqualInt(0, mkdir("without-m", 0755));
assertEqualInt(0, chdir("without-m"));
assertMakeDir("without-m", 0755);
assertChdir("without-m");
extract_reference_file("test_option_m.cpio");
r = systemf("%s -i < test_option_m.cpio >out 2>err", testprog);
now = time(NULL);
r = systemf("%s --no-preserve-owner -i < test_option_m.cpio >out 2>err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("out");
assertTextFileContents("1 block\n", "err");
assertEqualInt(0, stat("file", &st));
/* Should have been created within the last few seconds. */
assert(st.st_mtime <= now);
assert(st.st_mtime > now - 5);
assertFileMtimeRecent("file");
/* With -m, it should have an mtime in 1970. */
assertEqualInt(0, chdir(".."));
assertEqualInt(0, mkdir("with-m", 0755));
assertEqualInt(0, chdir("with-m"));
assertChdir("..");
assertMakeDir("with-m", 0755);
assertChdir("with-m");
extract_reference_file("test_option_m.cpio");
r = systemf("%s -im < test_option_m.cpio >out 2>err", testprog);
now = time(NULL);
r = systemf("%s --no-preserve-owner -im < test_option_m.cpio >out 2>err", testprog);
assertEqualInt(r, 0);
assertEmptyFile("out");
assertTextFileContents("1 block\n", "err");
assertEqualInt(0, stat("file", &st));
/*
* mtime in reference archive is '1' == 1 second after
* midnight Jan 1, 1970 UTC.
*/
assertEqualInt(1, st.st_mtime);
assertFileMtime("file", 1, 0);
}

View File

@ -71,12 +71,22 @@ DEFINE_TEST(test_option_t)
testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "itnv.err");
extract_reference_file("test_option_tnv.stdout");
/* This does work because numeric IDs come from archive. */
/* Unfortunately, the timestamp still gets localized, so
* we can't just compare against a fixed result. */
/* TODO: Fix this. */
/* assertEqualFile("itnv.out", "test_option_tnv.stdout"); */
p = slurpfile(NULL, "itnv.out");
/* Since -n uses numeric UID/GID, this part should be the
* same on every system. */
assertEqualMem(p, "-rw-r--r-- 1 1000 1000 0 ",42);
/* Date varies depending on local timezone. */
if (memcmp(p + 42, "Dec 31 1969", 12) == 0) {
/* East of Greenwich we get Dec 31, 1969. */
} else {
/* West of Greenwich get Jan 1, 1970 */
assertEqualMem(p + 42, "Jan ", 4);
/* Some systems format "Jan 01", some "Jan 1" */
assert(p[46] == ' ' || p[46] == '0');
assertEqualMem(p + 47, "1 1970 ", 8);
}
assertEqualMem(p + 54, " file", 5);
free(p);
/* But "-n" without "-t" is an error. */
assert(0 != systemf("%s -in < test_option_t.cpio >in.out 2>in.err",

View File

@ -23,10 +23,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <sys/utime.h>
#else
#if defined(HAVE_UTIME_H)
#include <utime.h>
#elif defined(HAVE_SYS_UTIME_H)
#include <sys/utime.h>
#endif
__FBSDID("$FreeBSD$");
@ -35,14 +35,10 @@ DEFINE_TEST(test_option_u)
struct utimbuf times;
char *p;
size_t s;
int fd;
int r;
/* Create a file. */
fd = open("f", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(1, write(fd, "a", 1));
close(fd);
assertMakeFile("f", 0644, "a");
/* Copy the file to the "copy" dir. */
r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
@ -55,10 +51,7 @@ DEFINE_TEST(test_option_u)
assertEqualMem(p, "a", 1);
/* Recreate the file with a single "b" */
fd = open("f", O_CREAT | O_TRUNC | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(1, write(fd, "b", 1));
close(fd);
assertMakeFile("f", 0644, "b");
/* Set the mtime to the distant past. */
memset(&times, 0, sizeof(times));

View File

@ -74,14 +74,14 @@ verify(const char *p, size_t s)
/* Skip a single trailing a,b,c, or d. */
if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
++q;
/* All terminated by a newline. */
/* All terminated by end-of-line: \r, \r\n, or \n */
assert(s >= 1);
failure("Version: %s", p);
#if defined(_WIN32) && !defined(__CYGWIN__)
assertEqualMem(q, "\r\n", 2);
#else
assertEqualMem(q, "\n", 1);
#endif
if (*q == '\x0d') {
if (q[1] != '\0')
assertEqualMem(q, "\x0d\x0a", 2);
} else
assertEqualMem(q, "\x0a", 1);
}

View File

@ -28,32 +28,30 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_option_y)
{
char *p;
int fd;
int r;
size_t s;
/* Create a file. */
fd = open("f", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(1, write(fd, "a", 1));
close(fd);
assertMakeFile("f", 0644, "a");
/* Archive it with bzip2 compression. */
r = systemf("echo f | %s -oy >archive.out 2>archive.err",
testprog);
failure("-y (bzip) option seems to be broken");
if (assertEqualInt(r, 0)) {
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (strstr(p, "bzip2 compression not supported") != NULL) {
if (r != 0) {
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without bzip2 support");
} else {
return;
}
failure("-y option is broken");
assertEqualInt(r, 0);
return;
}
assertTextFileContents("1 block\n", "archive.err");
/* Check that the archive file has a bzip2 signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "BZh9", 4);
}
}
}

View File

@ -28,32 +28,29 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_option_z)
{
char *p;
int fd;
int r;
size_t s;
/* Create a file. */
fd = open("f", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(1, write(fd, "a", 1));
close(fd);
assertMakeFile("f", 0644, "a");
/* Archive it with gzip compression. */
r = systemf("echo f | %s -oz >archive.out 2>archive.err",
testprog);
failure("-z option seems to be broken");
assertEqualInt(r, 0);
if (r == 0) {
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (strstr(p, "gzip compression not supported") != NULL) {
if (r != 0) {
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without gzip support");
} else {
return;
}
failure("-z option is broken");
assertEqualInt(r, 0);
return;
}
/* Check that the archive file has a gzip signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assert(s > 4);
assertEqualMem(p, "\x1f\x8b\x08\x00", 4);
}
}
}

View File

@ -28,7 +28,12 @@ __FBSDID("$FreeBSD$");
#include "../cpio.h"
#include "err.h"
#if defined(__CYGWIN__)
#if !defined(_WIN32)
#define ROOT "root"
static int root_uids[] = { 0 };
/* Solaris 9 root has gid 1 (other) */
static int root_gids[] = { 0, 1 };
#elif defined(__CYGWIN__)
/* On cygwin, the Administrator user most likely exists (unless
* it has been renamed or is in a non-English localization), but
* its primary group membership depends on how the user set up
@ -40,12 +45,9 @@ __FBSDID("$FreeBSD$");
#define ROOT "Administrator"
static int root_uids[] = { 500 };
static int root_gids[] = { 513, 545, 544 };
#else
#define ROOT "root"
static int root_uids[] = { 0 };
static int root_gids[] = { 0 };
#endif
#if defined(ROOT)
static int
int_in_list(int i, int *l, size_t n)
{
@ -55,54 +57,54 @@ int_in_list(int i, int *l, size_t n)
failure("%d", i);
return (0);
}
#endif
DEFINE_TEST(test_owner_parse)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
/* TODO: Does this need cygwin style handling of uid/gid ? */
skipping("Windows cannot handle uid/gid as UNIX like system");
#if !defined(ROOT)
skipping("No uid/gid configuration for this OS");
#else
int uid, gid;
assertEqualInt(0, owner_parse(ROOT, &uid, &gid));
assert(NULL == owner_parse(ROOT, &uid, &gid));
assert(int_in_list(uid, root_uids,
sizeof(root_uids)/sizeof(root_uids[0])));
assertEqualInt(-1, gid);
assertEqualInt(0, owner_parse(ROOT ":", &uid, &gid));
assert(NULL == owner_parse(ROOT ":", &uid, &gid));
assert(int_in_list(uid, root_uids,
sizeof(root_uids)/sizeof(root_uids[0])));
assert(int_in_list(gid, root_gids,
sizeof(root_gids)/sizeof(root_gids[0])));
assertEqualInt(0, owner_parse(ROOT ".", &uid, &gid));
assert(NULL == owner_parse(ROOT ".", &uid, &gid));
assert(int_in_list(uid, root_uids,
sizeof(root_uids)/sizeof(root_uids[0])));
assert(int_in_list(gid, root_gids,
sizeof(root_gids)/sizeof(root_gids[0])));
assertEqualInt(0, owner_parse("111", &uid, &gid));
assert(NULL == owner_parse("111", &uid, &gid));
assertEqualInt(111, uid);
assertEqualInt(-1, gid);
assertEqualInt(0, owner_parse("112:", &uid, &gid));
assert(NULL == owner_parse("112:", &uid, &gid));
assertEqualInt(112, uid);
/* Can't assert gid, since we don't know gid for user #112. */
assertEqualInt(0, owner_parse("113.", &uid, &gid));
assert(NULL == owner_parse("113.", &uid, &gid));
assertEqualInt(113, uid);
/* Can't assert gid, since we don't know gid for user #113. */
assertEqualInt(0, owner_parse(":114", &uid, &gid));
assert(NULL == owner_parse(":114", &uid, &gid));
assertEqualInt(-1, uid);
assertEqualInt(114, gid);
assertEqualInt(0, owner_parse(".115", &uid, &gid));
assert(NULL == owner_parse(".115", &uid, &gid));
assertEqualInt(-1, uid);
assertEqualInt(115, gid);
assertEqualInt(0, owner_parse("116:117", &uid, &gid));
assert(NULL == owner_parse("116:117", &uid, &gid));
assertEqualInt(116, uid);
assertEqualInt(117, gid);
@ -112,19 +114,9 @@ DEFINE_TEST(test_owner_parse)
* users.
*/
/*
* TODO: Rework owner_parse to either return a char * pointing
* to an error message or accept a function pointer to an
* error-reporting routine so that the following tests don't
* generate any output.
*
* Alternatively, redirect stderr temporarily to suppress the output.
*/
cpio_progname = "Ignore this message";
assertEqualInt(1, owner_parse(":nonexistentgroup", &uid, &gid));
assertEqualInt(1, owner_parse(ROOT ":nonexistentgroup", &uid, &gid));
assertEqualInt(1,
assert(NULL != owner_parse(":nonexistentgroup", &uid, &gid));
assert(NULL != owner_parse(ROOT ":nonexistentgroup", &uid, &gid));
assert(NULL !=
owner_parse("nonexistentuser:nonexistentgroup", &uid, &gid));
#endif
}

View File

@ -31,33 +31,28 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_passthrough_dotdot)
{
struct stat st;
int fd, r;
int filelist;
int oldumask;
int r;
FILE *filelist;
oldumask = umask(0);
assertUmask(0);
/*
* Create an assortment of files on disk.
*/
filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
filelist = fopen("filelist", "w");
/* Directory. */
assertEqualInt(0, mkdir("dir", 0755));
assertEqualInt(0, chdir("dir"));
assertMakeDir("dir", 0755);
assertChdir("dir");
write(filelist, ".\n", 2);
fprintf(filelist, ".\n");
/* File with 10 bytes content. */
fd = open("file", O_CREAT | O_WRONLY, 0642);
assert(fd >= 0);
assertEqualInt(10, write(fd, "123456789", 10));
close(fd);
write(filelist, "file\n", 5);
assertMakeFile("file", 0642, "1234567890");
fprintf(filelist, "file\n");
/* All done. */
close(filelist);
fclose(filelist);
/*
@ -68,26 +63,14 @@ DEFINE_TEST(test_passthrough_dotdot)
failure("Error invoking %s -pd ..", testprog);
assertEqualInt(r, 0);
assertEqualInt(0, chdir(".."));
assertChdir("..");
/* Verify stderr and stdout. */
assertTextFileContents("../.\n../file\n1 block\n", "stderr");
assertEmptyFile("stdout");
/* Regular file. */
r = lstat("file", &st);
failure("Failed to stat file, errno=%d", errno);
assertEqualInt(r, 0);
if (r == 0) {
assert(S_ISREG(st.st_mode));
#if defined(_WIN32) && !defined(__CYGWIN__)
assertEqualInt(0600, st.st_mode & 0700);
#else
assertEqualInt(0642, st.st_mode & 0777);
#endif
assertEqualInt(10, st.st_size);
assertEqualInt(1, st.st_nlink);
}
umask(oldumask);
assertIsReg("file", 0642);
assertFileSize("file", 10);
assertFileNLinks("file", 1);
}

View File

@ -36,33 +36,28 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_passthrough_reverse)
{
struct stat st;
int fd, r;
int filelist;
int oldumask;
int r;
FILE *filelist;
oldumask = umask(0);
assertUmask(0);
/*
* Create an assortment of files on disk.
*/
filelist = open("filelist", O_CREAT | O_WRONLY, 0644);
filelist = fopen("filelist", "w");
/* Directory. */
assertEqualInt(0, mkdir("dir", 0743));
assertMakeDir("dir", 0743);
/* File with 10 bytes content. */
fd = open("dir/file", O_CREAT | O_WRONLY, 0644);
assert(fd >= 0);
assertEqualInt(10, write(fd, "123456789", 10));
close(fd);
write(filelist, "dir/file\n", 9);
assertMakeFile("dir/file", 0644, "1234567890");
fprintf(filelist, "dir/file\n");
/* Write dir last. */
write(filelist, "dir\n", 4);
fprintf(filelist, "dir\n");
/* All done. */
close(filelist);
fclose(filelist);
/*
@ -72,7 +67,7 @@ DEFINE_TEST(test_passthrough_reverse)
failure("Error invoking %s -pd out", testprog);
assertEqualInt(r, 0);
assertEqualInt(0, chdir("out"));
assertChdir("out");
/* Verify stderr and stdout. */
assertTextFileContents("out/dir/file\nout/dir\n1 block\n",
@ -80,33 +75,11 @@ DEFINE_TEST(test_passthrough_reverse)
assertEmptyFile("../stdout");
/* dir */
r = lstat("dir", &st);
if (r == 0) {
assertEqualInt(r, 0);
assert(S_ISDIR(st.st_mode));
failure("st.st_mode=0%o", st.st_mode);
#if defined(_WIN32) && !defined(__CYGWIN__)
assertEqualInt(0700, st.st_mode & 0700);
#else
assertEqualInt(0743, st.st_mode & 0777);
#endif
}
assertIsDir("dir", 0743);
/* Regular file. */
r = lstat("dir/file", &st);
failure("Failed to stat dir/file, errno=%d", errno);
assertEqualInt(r, 0);
if (r == 0) {
assert(S_ISREG(st.st_mode));
#if defined(_WIN32) && !defined(__CYGWIN__)
assertEqualInt(0600, st.st_mode & 0700);
#else
assertEqualInt(0644, st.st_mode & 0777);
#endif
assertEqualInt(10, st.st_size);
assertEqualInt(1, st.st_nlink);
}
umask(oldumask);
assertIsReg("dir/file", 0644);
assertFileSize("dir/file", 10);
assertFileNLinks("dir/file", 1);
}

View File

@ -25,7 +25,7 @@
#include "test.h"
__FBSDID("$FreeBSD$");
#include "../pathmatch.h"
#include "pathmatch.h"
/*
* Verify that the pattern matcher implements the wildcard logic specified
@ -45,126 +45,126 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_pathmatch)
{
assertEqualInt(1, pathmatch("a/b/c", "a/b/c", 0));
assertEqualInt(0, pathmatch("a/b/", "a/b/c", 0));
assertEqualInt(0, pathmatch("a/b", "a/b/c", 0));
assertEqualInt(0, pathmatch("a/b/c", "a/b/", 0));
assertEqualInt(0, pathmatch("a/b/c", "a/b", 0));
assertEqualInt(1, lafe_pathmatch("a/b/c", "a/b/c", 0));
assertEqualInt(0, lafe_pathmatch("a/b/", "a/b/c", 0));
assertEqualInt(0, lafe_pathmatch("a/b", "a/b/c", 0));
assertEqualInt(0, lafe_pathmatch("a/b/c", "a/b/", 0));
assertEqualInt(0, lafe_pathmatch("a/b/c", "a/b", 0));
/* Empty pattern only matches empty string. */
assertEqualInt(1, pathmatch("","", 0));
assertEqualInt(0, pathmatch("","a", 0));
assertEqualInt(1, pathmatch("*","", 0));
assertEqualInt(1, pathmatch("*","a", 0));
assertEqualInt(1, pathmatch("*","abcd", 0));
assertEqualInt(1, lafe_pathmatch("","", 0));
assertEqualInt(0, lafe_pathmatch("","a", 0));
assertEqualInt(1, lafe_pathmatch("*","", 0));
assertEqualInt(1, lafe_pathmatch("*","a", 0));
assertEqualInt(1, lafe_pathmatch("*","abcd", 0));
/* SUSv2: * matches / */
assertEqualInt(1, pathmatch("*","abcd/efgh/ijkl", 0));
assertEqualInt(1, pathmatch("abcd*efgh/ijkl","abcd/efgh/ijkl", 0));
assertEqualInt(1, pathmatch("abcd***efgh/ijkl","abcd/efgh/ijkl", 0));
assertEqualInt(1, pathmatch("abcd***/efgh/ijkl","abcd/efgh/ijkl", 0));
assertEqualInt(0, pathmatch("?", "", 0));
assertEqualInt(0, pathmatch("?", "\0", 0));
assertEqualInt(1, pathmatch("?", "a", 0));
assertEqualInt(0, pathmatch("?", "ab", 0));
assertEqualInt(1, pathmatch("?", ".", 0));
assertEqualInt(1, pathmatch("?", "?", 0));
assertEqualInt(1, pathmatch("a", "a", 0));
assertEqualInt(0, pathmatch("a", "ab", 0));
assertEqualInt(0, pathmatch("a", "ab", 0));
assertEqualInt(1, pathmatch("a?c", "abc", 0));
assertEqualInt(1, lafe_pathmatch("*","abcd/efgh/ijkl", 0));
assertEqualInt(1, lafe_pathmatch("abcd*efgh/ijkl","abcd/efgh/ijkl", 0));
assertEqualInt(1, lafe_pathmatch("abcd***efgh/ijkl","abcd/efgh/ijkl", 0));
assertEqualInt(1, lafe_pathmatch("abcd***/efgh/ijkl","abcd/efgh/ijkl", 0));
assertEqualInt(0, lafe_pathmatch("?", "", 0));
assertEqualInt(0, lafe_pathmatch("?", "\0", 0));
assertEqualInt(1, lafe_pathmatch("?", "a", 0));
assertEqualInt(0, lafe_pathmatch("?", "ab", 0));
assertEqualInt(1, lafe_pathmatch("?", ".", 0));
assertEqualInt(1, lafe_pathmatch("?", "?", 0));
assertEqualInt(1, lafe_pathmatch("a", "a", 0));
assertEqualInt(0, lafe_pathmatch("a", "ab", 0));
assertEqualInt(0, lafe_pathmatch("a", "ab", 0));
assertEqualInt(1, lafe_pathmatch("a?c", "abc", 0));
/* SUSv2: ? matches / */
assertEqualInt(1, pathmatch("a?c", "a/c", 0));
assertEqualInt(1, pathmatch("a?*c*", "a/c", 0));
assertEqualInt(1, pathmatch("*a*", "a/c", 0));
assertEqualInt(1, pathmatch("*a*", "/a/c", 0));
assertEqualInt(1, pathmatch("*a*", "defaaaaaaa", 0));
assertEqualInt(0, pathmatch("a*", "defghi", 0));
assertEqualInt(0, pathmatch("*a*", "defghi", 0));
assertEqualInt(1, lafe_pathmatch("a?c", "a/c", 0));
assertEqualInt(1, lafe_pathmatch("a?*c*", "a/c", 0));
assertEqualInt(1, lafe_pathmatch("*a*", "a/c", 0));
assertEqualInt(1, lafe_pathmatch("*a*", "/a/c", 0));
assertEqualInt(1, lafe_pathmatch("*a*", "defaaaaaaa", 0));
assertEqualInt(0, lafe_pathmatch("a*", "defghi", 0));
assertEqualInt(0, lafe_pathmatch("*a*", "defghi", 0));
/* Character classes */
assertEqualInt(1, pathmatch("abc[def", "abc[def", 0));
assertEqualInt(0, pathmatch("abc[def]", "abc[def", 0));
assertEqualInt(0, pathmatch("abc[def", "abcd", 0));
assertEqualInt(1, pathmatch("abc[def]", "abcd", 0));
assertEqualInt(1, pathmatch("abc[def]", "abce", 0));
assertEqualInt(1, pathmatch("abc[def]", "abcf", 0));
assertEqualInt(0, pathmatch("abc[def]", "abcg", 0));
assertEqualInt(1, pathmatch("abc[d*f]", "abcd", 0));
assertEqualInt(1, pathmatch("abc[d*f]", "abc*", 0));
assertEqualInt(0, pathmatch("abc[d*f]", "abcdefghi", 0));
assertEqualInt(0, pathmatch("abc[d*", "abcdefghi", 0));
assertEqualInt(1, pathmatch("abc[d*", "abc[defghi", 0));
assertEqualInt(1, pathmatch("abc[d-f]", "abcd", 0));
assertEqualInt(1, pathmatch("abc[d-f]", "abce", 0));
assertEqualInt(1, pathmatch("abc[d-f]", "abcf", 0));
assertEqualInt(0, pathmatch("abc[d-f]", "abcg", 0));
assertEqualInt(0, pathmatch("abc[d-fh-k]", "abca", 0));
assertEqualInt(1, pathmatch("abc[d-fh-k]", "abcd", 0));
assertEqualInt(1, pathmatch("abc[d-fh-k]", "abce", 0));
assertEqualInt(1, pathmatch("abc[d-fh-k]", "abcf", 0));
assertEqualInt(0, pathmatch("abc[d-fh-k]", "abcg", 0));
assertEqualInt(1, pathmatch("abc[d-fh-k]", "abch", 0));
assertEqualInt(1, pathmatch("abc[d-fh-k]", "abci", 0));
assertEqualInt(1, pathmatch("abc[d-fh-k]", "abcj", 0));
assertEqualInt(1, pathmatch("abc[d-fh-k]", "abck", 0));
assertEqualInt(0, pathmatch("abc[d-fh-k]", "abcl", 0));
assertEqualInt(0, pathmatch("abc[d-fh-k]", "abc-", 0));
assertEqualInt(1, lafe_pathmatch("abc[def", "abc[def", 0));
assertEqualInt(0, lafe_pathmatch("abc[def]", "abc[def", 0));
assertEqualInt(0, lafe_pathmatch("abc[def", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[def]", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[def]", "abce", 0));
assertEqualInt(1, lafe_pathmatch("abc[def]", "abcf", 0));
assertEqualInt(0, lafe_pathmatch("abc[def]", "abcg", 0));
assertEqualInt(1, lafe_pathmatch("abc[d*f]", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[d*f]", "abc*", 0));
assertEqualInt(0, lafe_pathmatch("abc[d*f]", "abcdefghi", 0));
assertEqualInt(0, lafe_pathmatch("abc[d*", "abcdefghi", 0));
assertEqualInt(1, lafe_pathmatch("abc[d*", "abc[defghi", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abce", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abcf", 0));
assertEqualInt(0, lafe_pathmatch("abc[d-f]", "abcg", 0));
assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abca", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abce", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcf", 0));
assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abcg", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abch", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abci", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcj", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abck", 0));
assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abcl", 0));
assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abc-", 0));
/* [] matches nothing, [!] is the same as ? */
assertEqualInt(0, pathmatch("abc[]efg", "abcdefg", 0));
assertEqualInt(0, pathmatch("abc[]efg", "abcqefg", 0));
assertEqualInt(0, pathmatch("abc[]efg", "abcefg", 0));
assertEqualInt(1, pathmatch("abc[!]efg", "abcdefg", 0));
assertEqualInt(1, pathmatch("abc[!]efg", "abcqefg", 0));
assertEqualInt(0, pathmatch("abc[!]efg", "abcefg", 0));
assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcdefg", 0));
assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcqefg", 0));
assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcefg", 0));
assertEqualInt(1, lafe_pathmatch("abc[!]efg", "abcdefg", 0));
assertEqualInt(1, lafe_pathmatch("abc[!]efg", "abcqefg", 0));
assertEqualInt(0, lafe_pathmatch("abc[!]efg", "abcefg", 0));
/* I assume: Trailing '-' is non-special. */
assertEqualInt(0, pathmatch("abc[d-fh-]", "abcl", 0));
assertEqualInt(1, pathmatch("abc[d-fh-]", "abch", 0));
assertEqualInt(1, pathmatch("abc[d-fh-]", "abc-", 0));
assertEqualInt(1, pathmatch("abc[d-fh-]", "abc-", 0));
assertEqualInt(0, lafe_pathmatch("abc[d-fh-]", "abcl", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abch", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abc-", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abc-", 0));
/* ']' can be backslash-quoted within a character class. */
assertEqualInt(1, pathmatch("abc[\\]]", "abc]", 0));
assertEqualInt(1, pathmatch("abc[\\]d]", "abc]", 0));
assertEqualInt(1, pathmatch("abc[\\]d]", "abcd", 0));
assertEqualInt(1, pathmatch("abc[d\\]]", "abc]", 0));
assertEqualInt(1, pathmatch("abc[d\\]]", "abcd", 0));
assertEqualInt(1, pathmatch("abc[d]e]", "abcde]", 0));
assertEqualInt(1, pathmatch("abc[d\\]e]", "abc]", 0));
assertEqualInt(0, pathmatch("abc[d\\]e]", "abcd]e", 0));
assertEqualInt(0, pathmatch("abc[d]e]", "abc]", 0));
assertEqualInt(1, lafe_pathmatch("abc[\\]]", "abc]", 0));
assertEqualInt(1, lafe_pathmatch("abc[\\]d]", "abc]", 0));
assertEqualInt(1, lafe_pathmatch("abc[\\]d]", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[d\\]]", "abc]", 0));
assertEqualInt(1, lafe_pathmatch("abc[d\\]]", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[d]e]", "abcde]", 0));
assertEqualInt(1, lafe_pathmatch("abc[d\\]e]", "abc]", 0));
assertEqualInt(0, lafe_pathmatch("abc[d\\]e]", "abcd]e", 0));
assertEqualInt(0, lafe_pathmatch("abc[d]e]", "abc]", 0));
/* backslash-quoted chars can appear as either end of a range. */
assertEqualInt(1, pathmatch("abc[\\d-f]gh", "abcegh", 0));
assertEqualInt(0, pathmatch("abc[\\d-f]gh", "abcggh", 0));
assertEqualInt(0, pathmatch("abc[\\d-f]gh", "abc\\gh", 0));
assertEqualInt(1, pathmatch("abc[d-\\f]gh", "abcegh", 0));
assertEqualInt(1, pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
assertEqualInt(1, pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
assertEqualInt(1, lafe_pathmatch("abc[\\d-f]gh", "abcegh", 0));
assertEqualInt(0, lafe_pathmatch("abc[\\d-f]gh", "abcggh", 0));
assertEqualInt(0, lafe_pathmatch("abc[\\d-f]gh", "abc\\gh", 0));
assertEqualInt(1, lafe_pathmatch("abc[d-\\f]gh", "abcegh", 0));
assertEqualInt(1, lafe_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
assertEqualInt(1, lafe_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
/* backslash-quoted '-' isn't special. */
assertEqualInt(0, pathmatch("abc[d\\-f]gh", "abcegh", 0));
assertEqualInt(1, pathmatch("abc[d\\-f]gh", "abc-gh", 0));
assertEqualInt(0, lafe_pathmatch("abc[d\\-f]gh", "abcegh", 0));
assertEqualInt(1, lafe_pathmatch("abc[d\\-f]gh", "abc-gh", 0));
/* Leading '!' negates a character class. */
assertEqualInt(0, pathmatch("abc[!d]", "abcd", 0));
assertEqualInt(1, pathmatch("abc[!d]", "abce", 0));
assertEqualInt(1, pathmatch("abc[!d]", "abcc", 0));
assertEqualInt(0, pathmatch("abc[!d-z]", "abcq", 0));
assertEqualInt(1, pathmatch("abc[!d-gi-z]", "abch", 0));
assertEqualInt(1, pathmatch("abc[!fgijkl]", "abch", 0));
assertEqualInt(0, pathmatch("abc[!fghijkl]", "abch", 0));
assertEqualInt(0, lafe_pathmatch("abc[!d]", "abcd", 0));
assertEqualInt(1, lafe_pathmatch("abc[!d]", "abce", 0));
assertEqualInt(1, lafe_pathmatch("abc[!d]", "abcc", 0));
assertEqualInt(0, lafe_pathmatch("abc[!d-z]", "abcq", 0));
assertEqualInt(1, lafe_pathmatch("abc[!d-gi-z]", "abch", 0));
assertEqualInt(1, lafe_pathmatch("abc[!fgijkl]", "abch", 0));
assertEqualInt(0, lafe_pathmatch("abc[!fghijkl]", "abch", 0));
/* Backslash quotes next character. */
assertEqualInt(0, pathmatch("abc\\[def]", "abc\\d", 0));
assertEqualInt(1, pathmatch("abc\\[def]", "abc[def]", 0));
assertEqualInt(0, pathmatch("abc\\\\[def]", "abc[def]", 0));
assertEqualInt(0, pathmatch("abc\\\\[def]", "abc\\[def]", 0));
assertEqualInt(1, pathmatch("abc\\\\[def]", "abc\\d", 0));
assertEqualInt(1, pathmatch("abcd\\", "abcd\\", 0));
assertEqualInt(0, pathmatch("abcd\\", "abcd\\[", 0));
assertEqualInt(0, pathmatch("abcd\\", "abcde", 0));
assertEqualInt(0, pathmatch("abcd\\[", "abcd\\", 0));
assertEqualInt(0, lafe_pathmatch("abc\\[def]", "abc\\d", 0));
assertEqualInt(1, lafe_pathmatch("abc\\[def]", "abc[def]", 0));
assertEqualInt(0, lafe_pathmatch("abc\\\\[def]", "abc[def]", 0));
assertEqualInt(0, lafe_pathmatch("abc\\\\[def]", "abc\\[def]", 0));
assertEqualInt(1, lafe_pathmatch("abc\\\\[def]", "abc\\d", 0));
assertEqualInt(1, lafe_pathmatch("abcd\\", "abcd\\", 0));
assertEqualInt(0, lafe_pathmatch("abcd\\", "abcd\\[", 0));
assertEqualInt(0, lafe_pathmatch("abcd\\", "abcde", 0));
assertEqualInt(0, lafe_pathmatch("abcd\\[", "abcd\\", 0));
/*
* Because '.' and '/' have special meanings, we can
@ -172,72 +172,72 @@ DEFINE_TEST(test_pathmatch)
* differently. (But quoting a character with '\\' suppresses
* special meanings!)
*/
assertEqualInt(0, pathmatch("a/b/", "a/bc", 0));
assertEqualInt(1, pathmatch("a/./b", "a/b", 0));
assertEqualInt(0, pathmatch("a\\/./b", "a/b", 0));
assertEqualInt(0, pathmatch("a/\\./b", "a/b", 0));
assertEqualInt(0, pathmatch("a/.\\/b", "a/b", 0));
assertEqualInt(0, pathmatch("a\\/\\.\\/b", "a/b", 0));
assertEqualInt(1, pathmatch("./abc/./def/", "abc/def/", 0));
assertEqualInt(1, pathmatch("abc/def", "./././abc/./def", 0));
assertEqualInt(1, pathmatch("abc/def/././//", "./././abc/./def/", 0));
assertEqualInt(1, pathmatch(".////abc/.//def", "./././abc/./def", 0));
assertEqualInt(1, pathmatch("./abc?def/", "abc/def/", 0));
assertEqualInt(0, lafe_pathmatch("a/b/", "a/bc", 0));
assertEqualInt(1, lafe_pathmatch("a/./b", "a/b", 0));
assertEqualInt(0, lafe_pathmatch("a\\/./b", "a/b", 0));
assertEqualInt(0, lafe_pathmatch("a/\\./b", "a/b", 0));
assertEqualInt(0, lafe_pathmatch("a/.\\/b", "a/b", 0));
assertEqualInt(0, lafe_pathmatch("a\\/\\.\\/b", "a/b", 0));
assertEqualInt(1, lafe_pathmatch("./abc/./def/", "abc/def/", 0));
assertEqualInt(1, lafe_pathmatch("abc/def", "./././abc/./def", 0));
assertEqualInt(1, lafe_pathmatch("abc/def/././//", "./././abc/./def/", 0));
assertEqualInt(1, lafe_pathmatch(".////abc/.//def", "./././abc/./def", 0));
assertEqualInt(1, lafe_pathmatch("./abc?def/", "abc/def/", 0));
failure("\"?./\" is not the same as \"/./\"");
assertEqualInt(0, pathmatch("./abc?./def/", "abc/def/", 0));
assertEqualInt(0, lafe_pathmatch("./abc?./def/", "abc/def/", 0));
failure("Trailing '/' should match no trailing '/'");
assertEqualInt(1, pathmatch("./abc/./def/", "abc/def", 0));
assertEqualInt(1, lafe_pathmatch("./abc/./def/", "abc/def", 0));
failure("Trailing '/./' is still the same directory.");
assertEqualInt(1, pathmatch("./abc/./def/./", "abc/def", 0));
assertEqualInt(1, lafe_pathmatch("./abc/./def/./", "abc/def", 0));
failure("Trailing '/.' is still the same directory.");
assertEqualInt(1, pathmatch("./abc/./def/.", "abc/def", 0));
assertEqualInt(1, pathmatch("./abc/./def", "abc/def/", 0));
assertEqualInt(1, lafe_pathmatch("./abc/./def/.", "abc/def", 0));
assertEqualInt(1, lafe_pathmatch("./abc/./def", "abc/def/", 0));
failure("Trailing '/./' is still the same directory.");
assertEqualInt(1, pathmatch("./abc/./def", "abc/def/./", 0));
assertEqualInt(1, lafe_pathmatch("./abc/./def", "abc/def/./", 0));
failure("Trailing '/.' is still the same directory.");
assertEqualInt(1, pathmatch("./abc*/./def", "abc/def/.", 0));
assertEqualInt(1, lafe_pathmatch("./abc*/./def", "abc/def/.", 0));
/* Matches not anchored at beginning. */
assertEqualInt(0,
pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
lafe_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
assertEqualInt(1,
pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_START));
lafe_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_START));
assertEqualInt(0,
pathmatch("^bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
lafe_pathmatch("^bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
assertEqualInt(1,
pathmatch("b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
lafe_pathmatch("b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
assertEqualInt(0,
pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
lafe_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
assertEqualInt(0,
pathmatch("^b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
lafe_pathmatch("^b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
/* Matches not anchored at end. */
assertEqualInt(0,
pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("abcd", "abcd/", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("abcd", "abcd/", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("abcd", "abcd/.", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("abcd", "abcd/.", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(0,
pathmatch("abc", "abcd", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("abc", "abcd", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(0,
pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("a/b/c$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("a/b/c$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("a/b/c/", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c/", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(0,
pathmatch("a/b/c/$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c/$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("a/b/c/$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c/$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(1,
pathmatch("a/b/c/$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("a/b/c/$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
assertEqualInt(0,
pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
lafe_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
}