Merge from libarchive.googlecode.com:
* Lots of new tests. * New -n / --numeric-uid-gid option * More sanity-checking of arguments * Various Windows portability improvements * Sync up version number to 2.7.0
This commit is contained in:
parent
4e8cb50d8b
commit
5853643ce6
@ -3,13 +3,13 @@
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= bsdcpio
|
||||
BSDCPIO_VERSION_STRING=1.1.0
|
||||
BSDCPIO_VERSION_STRING=2.7.0
|
||||
SRCS= cpio.c cmdline.c err.c matching.c pathmatch.c
|
||||
WARNS?= 6
|
||||
DPADD= ${LIBARCHIVE} ${LIBZ} ${LIBBZ2}
|
||||
CFLAGS+= -DBSDCPIO_VERSION_STRING=\"${BSDCPIO_VERSION_STRING}\"
|
||||
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
|
||||
LDADD+= -larchive -lz -lbz2
|
||||
LDADD+= -larchive -lz -lbz2 -lmd -lcrypto
|
||||
|
||||
.if ${MK_GNU_CPIO} != "yes"
|
||||
SYMLINKS=bsdcpio ${BINDIR}/cpio
|
||||
|
@ -167,6 +167,15 @@ instead of copying.
|
||||
(i and p modes)
|
||||
Set file modification time on created files to match
|
||||
those in the source.
|
||||
.It Fl n
|
||||
(i mode, only with
|
||||
.Fl t )
|
||||
Display numeric uid and gid.
|
||||
By default,
|
||||
.Nm
|
||||
displays the user and group names when they are provided in the
|
||||
archive, or looks up the user and group names in the system
|
||||
password database.
|
||||
.It Fl O Ar file
|
||||
Write archive to
|
||||
.Ar file .
|
||||
|
@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
/*
|
||||
* Short options for cpio. Please keep this sorted.
|
||||
*/
|
||||
static const char *short_options = "0AaBC:F:O:cdE:f:H:hijLlmopR:rtuvW:yZz";
|
||||
static const char *short_options = "0AaBC:F:O:cdE:f:H:hijLlmnopR:rtuvW:yZz";
|
||||
|
||||
/*
|
||||
* Long options for cpio. Please keep this sorted.
|
||||
@ -71,6 +71,7 @@ static const struct option {
|
||||
{ "make-directories", 0, 'd' },
|
||||
{ "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER },
|
||||
{ "null", 0, '0' },
|
||||
{ "numeric-uid-gid", 0, 'n' },
|
||||
{ "owner", 1, 'R' },
|
||||
{ "pass-through", 0, 'p' },
|
||||
{ "preserve-modification-time", 0, 'm' },
|
||||
|
@ -32,9 +32,15 @@ __FBSDID("$FreeBSD$");
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
@ -60,6 +66,12 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "cpio.h"
|
||||
#include "matching.h"
|
||||
@ -94,7 +106,7 @@ static void mode_in(struct cpio *);
|
||||
static void mode_list(struct cpio *);
|
||||
static void mode_out(struct cpio *);
|
||||
static void mode_pass(struct cpio *, const char *);
|
||||
static void restore_time(struct cpio *, struct archive_entry *,
|
||||
static int restore_time(struct cpio *, struct archive_entry *,
|
||||
const char *, int fd);
|
||||
static void usage(void);
|
||||
static void version(void);
|
||||
@ -112,12 +124,22 @@ main(int argc, char *argv[])
|
||||
memset(cpio, 0, sizeof(*cpio));
|
||||
cpio->buff = buff;
|
||||
cpio->buff_size = sizeof(buff);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure open() function will be used with a binary mode. */
|
||||
/* on cygwin, we need something similar, but instead link against */
|
||||
/* a special startup object, binmode.o */
|
||||
_set_fmode(_O_BINARY);
|
||||
#endif
|
||||
|
||||
/* Need cpio_progname before calling cpio_warnc. */
|
||||
if (*argv == NULL)
|
||||
cpio_progname = "bsdcpio";
|
||||
else {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
cpio_progname = strrchr(*argv, '\\');
|
||||
#else
|
||||
cpio_progname = strrchr(*argv, '/');
|
||||
#endif
|
||||
if (cpio_progname != NULL)
|
||||
cpio_progname++;
|
||||
else
|
||||
@ -132,8 +154,6 @@ main(int argc, char *argv[])
|
||||
cpio->mode = '\0';
|
||||
cpio->verbose = 0;
|
||||
cpio->compress = '\0';
|
||||
/* TODO: Implement old binary format in libarchive, use that here. */
|
||||
cpio->format = "odc"; /* Default format */
|
||||
cpio->extract_flags = ARCHIVE_EXTRACT_NO_AUTODIR;
|
||||
cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
|
||||
cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
|
||||
@ -141,7 +161,11 @@ main(int argc, char *argv[])
|
||||
cpio->extract_flags |= ARCHIVE_EXTRACT_PERM;
|
||||
cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
|
||||
cpio->extract_flags |= ARCHIVE_EXTRACT_ACL;
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (bsdcpio_is_privileged())
|
||||
#else
|
||||
if (geteuid() == 0)
|
||||
#endif
|
||||
cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
|
||||
cpio->bytes_per_block = 512;
|
||||
cpio->filename = NULL;
|
||||
@ -190,6 +214,9 @@ main(int argc, char *argv[])
|
||||
cpio->filename = cpio->optarg;
|
||||
break;
|
||||
case 'i': /* POSIX 1997 */
|
||||
if (cpio->mode != '\0')
|
||||
cpio_errc(1, 0,
|
||||
"Cannot use both -i and -%c", cpio->mode);
|
||||
cpio->mode = opt;
|
||||
break;
|
||||
case OPTION_INSECURE:
|
||||
@ -205,6 +232,9 @@ main(int argc, char *argv[])
|
||||
case 'm': /* POSIX 1997 */
|
||||
cpio->extract_flags |= ARCHIVE_EXTRACT_TIME;
|
||||
break;
|
||||
case 'n': /* GNU cpio */
|
||||
cpio->option_numeric_uid_gid = 1;
|
||||
break;
|
||||
case OPTION_NO_PRESERVE_OWNER: /* GNU cpio */
|
||||
cpio->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
|
||||
break;
|
||||
@ -212,9 +242,15 @@ main(int argc, char *argv[])
|
||||
cpio->filename = cpio->optarg;
|
||||
break;
|
||||
case 'o': /* POSIX 1997 */
|
||||
if (cpio->mode != '\0')
|
||||
cpio_errc(1, 0,
|
||||
"Cannot use both -o and -%c", cpio->mode);
|
||||
cpio->mode = opt;
|
||||
break;
|
||||
case 'p': /* POSIX 1997 */
|
||||
if (cpio->mode != '\0')
|
||||
cpio_errc(1, 0,
|
||||
"Cannot use both -p and -%c", cpio->mode);
|
||||
cpio->mode = opt;
|
||||
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
|
||||
break;
|
||||
@ -254,23 +290,56 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
#endif
|
||||
case 'y': /* tar convention */
|
||||
#if HAVE_LIBBZ2
|
||||
cpio->compress = opt;
|
||||
#else
|
||||
cpio_warnc(0, "bzip2 compression not supported by "
|
||||
"this version of bsdcpio");
|
||||
#endif
|
||||
break;
|
||||
case 'Z': /* tar convention */
|
||||
cpio->compress = opt;
|
||||
break;
|
||||
case 'z': /* tar convention */
|
||||
#if HAVE_LIBZ
|
||||
cpio->compress = opt;
|
||||
#else
|
||||
cpio_warnc(0, "gzip compression not supported by "
|
||||
"this version of bsdcpio");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Sanity-check args, error out on nonsensical combinations. */
|
||||
/*
|
||||
* Sanity-check args, error out on nonsensical combinations.
|
||||
*/
|
||||
/* -t implies -i if no mode was specified. */
|
||||
if (cpio->option_list && cpio->mode == '\0')
|
||||
cpio->mode = 'i';
|
||||
/* -t requires -i */
|
||||
if (cpio->option_list && cpio->mode != 'i')
|
||||
cpio_errc(1, 0, "Option -t requires -i", cpio->mode);
|
||||
/* -n requires -it */
|
||||
if (cpio->option_numeric_uid_gid && !cpio->option_list)
|
||||
cpio_errc(1, 0, "Option -n requires -it");
|
||||
/* Can only specify format when writing */
|
||||
if (cpio->format != NULL && cpio->mode != 'o')
|
||||
cpio_errc(1, 0, "Option --format requires -o");
|
||||
/* -l requires -p */
|
||||
if (cpio->option_link && cpio->mode != 'p')
|
||||
cpio_errc(1, 0, "Option -l requires -p");
|
||||
/* TODO: Flag other nonsensical combinations. */
|
||||
|
||||
switch (cpio->mode) {
|
||||
case 'o':
|
||||
/* TODO: Implement old binary format in libarchive,
|
||||
use that here. */
|
||||
if (cpio->format == NULL)
|
||||
cpio->format = "odc"; /* Default format */
|
||||
|
||||
mode_out(cpio);
|
||||
break;
|
||||
case 'i':
|
||||
@ -321,7 +390,12 @@ static const char *long_help_msg =
|
||||
"Common Options:\n"
|
||||
" -v Verbose\n"
|
||||
"Create: %p -o [options] < [list of files] > [archive]\n"
|
||||
" -z, -y Compress archive with gzip/bzip2\n"
|
||||
#ifdef HAVE_BZLIB_H
|
||||
" -y Compress archive with bzip2\n"
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB_H
|
||||
" -z Compress archive with gzip\n"
|
||||
#endif
|
||||
" --format {odc|newc|ustar} Select archive format\n"
|
||||
"List: %p -it < [archive]\n"
|
||||
"Extract: %p -i [options] < [archive]\n";
|
||||
@ -387,12 +461,16 @@ mode_out(struct cpio *cpio)
|
||||
if (cpio->archive == NULL)
|
||||
cpio_errc(1, 0, "Failed to allocate archive object");
|
||||
switch (cpio->compress) {
|
||||
#ifdef HAVE_BZLIB_H
|
||||
case 'j': case 'y':
|
||||
archive_write_set_compression_bzip2(cpio->archive);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB_H
|
||||
case 'z':
|
||||
archive_write_set_compression_gzip(cpio->archive);
|
||||
break;
|
||||
#endif
|
||||
case 'Z':
|
||||
archive_write_set_compression_compress(cpio->archive);
|
||||
break;
|
||||
@ -455,11 +533,15 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
struct archive_entry *entry, *spare;
|
||||
size_t len;
|
||||
const char *p;
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
int lnklen;
|
||||
#endif
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Create an archive_entry describing the source file.
|
||||
*
|
||||
* XXX TODO: rework to use archive_read_disk_entry_from_file()
|
||||
*/
|
||||
entry = archive_entry_new();
|
||||
if (entry == NULL)
|
||||
@ -483,6 +565,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
st.st_gid = cpio->uid_override;
|
||||
archive_entry_copy_stat(entry, &st);
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
/* If its a symlink, pull the target. */
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
lnklen = readlink(srcpath, cpio->buff, cpio->buff_size);
|
||||
@ -495,6 +578,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
cpio->buff[lnklen] = 0;
|
||||
archive_entry_set_symlink(entry, cpio->buff);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generate a destination path for this entry.
|
||||
@ -625,7 +709,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
|
||||
if (r != ARCHIVE_OK)
|
||||
cpio_warnc(archive_errno(cpio->archive),
|
||||
"%s: %s",
|
||||
destpath,
|
||||
srcpath,
|
||||
archive_error_string(cpio->archive));
|
||||
|
||||
if (r == ARCHIVE_FATAL)
|
||||
@ -647,7 +731,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
restore_time(cpio, entry, srcpath, fd);
|
||||
fd = restore_time(cpio, entry, srcpath, fd);
|
||||
|
||||
cleanup:
|
||||
if (cpio->verbose)
|
||||
@ -657,7 +741,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
restore_time(struct cpio *cpio, struct archive_entry *entry,
|
||||
const char *name, int fd)
|
||||
{
|
||||
@ -667,17 +751,20 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
|
||||
(void)cpio; /* UNUSED */
|
||||
(void)entry; /* UNUSED */
|
||||
(void)name; /* UNUSED */
|
||||
(void)fd; /* UNUSED */
|
||||
|
||||
if (!warned)
|
||||
cpio_warnc(0, "Can't restore access times on this platform");
|
||||
warned = 1;
|
||||
return;
|
||||
return (fd);
|
||||
#else
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
struct __timeval times[2];
|
||||
#else
|
||||
struct timeval times[2];
|
||||
#endif
|
||||
|
||||
if (!cpio->option_atime_restore)
|
||||
return;
|
||||
return (fd);
|
||||
|
||||
times[1].tv_sec = archive_entry_mtime(entry);
|
||||
times[1].tv_usec = archive_entry_mtime_nsec(entry) / 1000;
|
||||
@ -687,8 +774,16 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
|
||||
|
||||
#ifdef HAVE_FUTIMES
|
||||
if (fd >= 0 && futimes(fd, times) == 0)
|
||||
return;
|
||||
return (fd);
|
||||
#endif
|
||||
/*
|
||||
* Some platform cannot restore access times if the file descriptor
|
||||
* is still opened.
|
||||
*/
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LUTIMES
|
||||
if (lutimes(name, times) != 0)
|
||||
@ -697,6 +792,7 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
|
||||
#endif
|
||||
cpio_warnc(errno, "Can't update time for %s", name);
|
||||
#endif
|
||||
return (fd);
|
||||
}
|
||||
|
||||
|
||||
@ -858,6 +954,7 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
{
|
||||
char size[32];
|
||||
char date[32];
|
||||
char uids[16], gids[16];
|
||||
const char *uname, *gname;
|
||||
FILE *out = stdout;
|
||||
const struct stat *st;
|
||||
@ -870,15 +967,24 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
if (!now)
|
||||
time(&now);
|
||||
|
||||
/* Use uname if it's present, else uid. */
|
||||
uname = archive_entry_uname(entry);
|
||||
if (uname == NULL)
|
||||
uname = lookup_uname(cpio, archive_entry_uid(entry));
|
||||
|
||||
/* Use gname if it's present, else gid. */
|
||||
gname = archive_entry_gname(entry);
|
||||
if (gname == NULL)
|
||||
gname = lookup_gname(cpio, archive_entry_gid(entry));
|
||||
if (cpio->option_numeric_uid_gid) {
|
||||
/* Format numeric uid/gid for display. */
|
||||
snprintf(uids, sizeof(uids), "%jd",
|
||||
(intmax_t)archive_entry_uid(entry));
|
||||
uname = uids;
|
||||
snprintf(gids, sizeof(gids), "%jd",
|
||||
(intmax_t)archive_entry_gid(entry));
|
||||
gname = gids;
|
||||
} else {
|
||||
/* Use uname if it's present, else lookup name from uid. */
|
||||
uname = archive_entry_uname(entry);
|
||||
if (uname == NULL)
|
||||
uname = lookup_uname(cpio, archive_entry_uid(entry));
|
||||
/* Use gname if it's present, else lookup name from gid. */
|
||||
gname = archive_entry_gname(entry);
|
||||
if (gname == NULL)
|
||||
gname = lookup_gname(cpio, archive_entry_gid(entry));
|
||||
}
|
||||
|
||||
/* Print device number or file size. */
|
||||
if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
|
||||
@ -892,10 +998,18 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
|
||||
/* Format the time using 'ls -l' conventions. */
|
||||
tim = (time_t)st->st_mtime;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Windows' strftime function does not support %e format. */
|
||||
if (abs(tim - now) > (365/2)*86400)
|
||||
fmt = cpio->day_first ? "%d %b %Y" : "%b %d %Y";
|
||||
else
|
||||
fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M";
|
||||
#else
|
||||
if (abs(tim - now) > (365/2)*86400)
|
||||
fmt = cpio->day_first ? "%e %b %Y" : "%b %e %Y";
|
||||
else
|
||||
fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
|
||||
#endif
|
||||
strftime(date, sizeof(date), fmt, localtime(&tim));
|
||||
|
||||
fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
|
||||
|
@ -62,6 +62,7 @@ struct cpio {
|
||||
int option_follow_links; /* -L */
|
||||
int option_link; /* -l */
|
||||
int option_list; /* -t */
|
||||
int option_numeric_uid_gid; /* -n */
|
||||
int option_rename; /* -r */
|
||||
char *destdir;
|
||||
size_t pass_destpath_alloc;
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include PLATFORM_CONFIG_H
|
||||
#elif defined(HAVE_CONFIG_H)
|
||||
/* Most POSIX platforms use the 'configure' script to build config.h */
|
||||
#include "../config.h"
|
||||
#include "config.h"
|
||||
#else
|
||||
/* Warn if cpio hasn't been (automatically or manually) configured. */
|
||||
#error Oops: No config.h and no built-in configuration in cpio_platform.h.
|
||||
@ -48,7 +48,7 @@
|
||||
/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h> /* For __FBSDID */
|
||||
#else
|
||||
#elif !defined(__FBSDID)
|
||||
/* Just leaving this macro replacement empty leads to a dangling semicolon. */
|
||||
#define __FBSDID(a) struct _undefined_hack
|
||||
#endif
|
||||
@ -89,4 +89,10 @@
|
||||
#define __LA_DEAD
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
#include "cpio_cygwin.h"
|
||||
#elif defined(_WIN32) /* && !__CYGWIN__ */
|
||||
#include "cpio_windows.h"
|
||||
#endif
|
||||
|
||||
#endif /* !CPIO_PLATFORM_H_INCLUDED */
|
||||
|
@ -101,11 +101,10 @@ pm_list(const char *start, const char *end, const char c, int flags)
|
||||
*/
|
||||
static const char *
|
||||
pm_slashskip(const char *s) {
|
||||
while (*s == '.' || *s == '/') {
|
||||
if (s[0] != '/' && s[1] != '/')
|
||||
break;
|
||||
while ((*s == '/')
|
||||
|| (s[0] == '.' && s[1] == '/')
|
||||
|| (s[0] == '.' && s[1] == '\0'))
|
||||
++s;
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
@ -130,8 +129,6 @@ pm(const char *p, const char *s, int flags)
|
||||
return (1);
|
||||
/* "dir" == "dir/" == "dir/." */
|
||||
s = pm_slashskip(s);
|
||||
if (s[0] == '.' && s[1] == '\0')
|
||||
return (1);
|
||||
}
|
||||
return (*s == '\0');
|
||||
break;
|
||||
@ -176,19 +173,6 @@ pm(const char *p, const char *s, int flags)
|
||||
if (*p != *s)
|
||||
return (0);
|
||||
break;
|
||||
default:
|
||||
if (*p == *s)
|
||||
break;
|
||||
if ((*s == '\0') && (*p == '/')) {
|
||||
p = pm_slashskip(p);
|
||||
if (*p == '\0')
|
||||
return (1);
|
||||
if (p[0] == '.' && p[1] == '\0')
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
break;
|
||||
case '\\':
|
||||
/* Trailing '\\' matches itself. */
|
||||
if (p[1] == '\0') {
|
||||
@ -200,19 +184,34 @@ pm(const char *p, const char *s, int flags)
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* TODO: pattern of "\/\.\/" should not match plain "/",
|
||||
* it should only match explicit "/./".
|
||||
*/
|
||||
if (*p == '/')
|
||||
case '/':
|
||||
if (*s != '/' && *s != '\0')
|
||||
return (0);
|
||||
/* Note: pattern "/\./" won't match "/";
|
||||
* pm_slashskip() correctly stops at backslash. */
|
||||
p = pm_slashskip(p);
|
||||
else
|
||||
++p;
|
||||
if (*s == '/')
|
||||
s = pm_slashskip(s);
|
||||
else
|
||||
++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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,9 +235,9 @@ pathmatch(const char *p, const char *s, int flags)
|
||||
|
||||
/* If start is unanchored, try to match start of each path element. */
|
||||
if (flags & PATHMATCH_NO_ANCHOR_START) {
|
||||
for ( ; p != NULL; p = strchr(p, '/')) {
|
||||
if (*p == '/')
|
||||
p++;
|
||||
for ( ; s != NULL; s = strchr(s, '/')) {
|
||||
if (*s == '/')
|
||||
s++;
|
||||
if (pm(p, s, flags))
|
||||
return (1);
|
||||
}
|
||||
|
@ -29,9 +29,14 @@
|
||||
#ifndef PATHMATCH_H
|
||||
#define PATHMATCH_H
|
||||
|
||||
/* Don't anchor at beginning unless the pattern starts with "^" */
|
||||
#define PATHMATCH_NO_ANCHOR_START 1
|
||||
/* Don't anchor at end unless the pattern ends with "$" */
|
||||
#define PATHMATCH_NO_ANCHOR_END 2
|
||||
|
||||
/* Note that "^" and "$" are not special unless you set the corresponding
|
||||
* flag above. */
|
||||
|
||||
int pathmatch(const char *p, const char *s, int flags);
|
||||
|
||||
#endif
|
||||
|
@ -44,6 +44,7 @@
|
||||
#undef EXTRA_DUMP /* How to dump extra data */
|
||||
/* How to generate extra version info. */
|
||||
#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
|
||||
#define KNOWNREF "test_option_f.cpio.uu"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
@ -80,7 +81,7 @@ static int skips = 0;
|
||||
static int assertions = 0;
|
||||
|
||||
/* Directory where uuencoded reference files can be found. */
|
||||
static char *refdir;
|
||||
static const char *refdir;
|
||||
|
||||
/*
|
||||
* My own implementation of the standard assert() macro emits the
|
||||
@ -324,10 +325,10 @@ test_assert_equal_string(const char *file, int line,
|
||||
file, line);
|
||||
fprintf(stderr, " %s = ", e1);
|
||||
strdump(v1);
|
||||
fprintf(stderr, " (length %d)\n", v1 == NULL ? 0 : strlen(v1));
|
||||
fprintf(stderr, " (length %d)\n", v1 == NULL ? 0 : (int)strlen(v1));
|
||||
fprintf(stderr, " %s = ", e2);
|
||||
strdump(v2);
|
||||
fprintf(stderr, " (length %d)\n", v2 == NULL ? 0 : strlen(v2));
|
||||
fprintf(stderr, " (length %d)\n", v2 == NULL ? 0 : (int)strlen(v2));
|
||||
report_failure(extra);
|
||||
return (0);
|
||||
}
|
||||
@ -402,7 +403,7 @@ hexdump(const char *p, const char *ref, size_t l, size_t offset)
|
||||
char sep;
|
||||
|
||||
for(i=0; i < l; i+=16) {
|
||||
fprintf(stderr, "%04x", i + offset);
|
||||
fprintf(stderr, "%04x", (unsigned)(i + offset));
|
||||
sep = ' ';
|
||||
for (j = 0; j < 16 && i + j < l; j++) {
|
||||
if (ref != NULL && p[i + j] != ref[i + j])
|
||||
@ -497,6 +498,7 @@ test_assert_empty_file(const char *f1fmt, ...)
|
||||
s = sizeof(buff) < st.st_size ? sizeof(buff) : st.st_size;
|
||||
s = read(fd, buff, s);
|
||||
hexdump(buff, NULL, s, 0);
|
||||
close(fd);
|
||||
}
|
||||
report_failure(NULL);
|
||||
return (0);
|
||||
@ -525,11 +527,16 @@ test_assert_equal_file(const char *f1, const char *f2pattern, ...)
|
||||
n2 = read(fd2, buff2, sizeof(buff2));
|
||||
if (n1 != n2)
|
||||
break;
|
||||
if (n1 == 0 && n2 == 0)
|
||||
if (n1 == 0 && n2 == 0) {
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return (1);
|
||||
}
|
||||
if (memcmp(buff1, buff2, n1) != 0)
|
||||
break;
|
||||
}
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
failures ++;
|
||||
if (!verbose && previous_failures(test_filename, test_line))
|
||||
return (0);
|
||||
@ -600,6 +607,7 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
|
||||
fd = open(f, O_RDONLY);
|
||||
contents = malloc(s * 2 + 128);
|
||||
n = read(fd, contents, s * 2 + 128);
|
||||
close(fd);
|
||||
if (n == s && memcmp(buff, contents, s) == 0) {
|
||||
free(contents);
|
||||
return (1);
|
||||
@ -621,6 +629,60 @@ test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* assertTextFileContents() asserts the contents of a text file. */
|
||||
int
|
||||
test_assert_text_file_contents(const char *buff, const char *f)
|
||||
{
|
||||
char *contents;
|
||||
const char *btxt, *ftxt;
|
||||
int fd;
|
||||
int n, s;
|
||||
|
||||
fd = open(f, O_RDONLY);
|
||||
s = strlen(buff);
|
||||
contents = malloc(s * 2 + 128);
|
||||
n = read(fd, contents, s * 2 + 128 -1);
|
||||
if (n >= 0)
|
||||
contents[n] = '\0';
|
||||
close(fd);
|
||||
/* Compare texts. */
|
||||
btxt = buff;
|
||||
ftxt = (const char *)contents;
|
||||
while (*btxt != '\0' && *ftxt != '\0') {
|
||||
if (*btxt == *ftxt) {
|
||||
++btxt;
|
||||
++ftxt;
|
||||
continue;
|
||||
}
|
||||
if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') {
|
||||
/* Pass over different new line characters. */
|
||||
++btxt;
|
||||
ftxt += 2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*btxt == '\0' && *ftxt == '\0') {
|
||||
free(contents);
|
||||
return (1);
|
||||
}
|
||||
failures ++;
|
||||
if (!previous_failures(test_filename, test_line)) {
|
||||
fprintf(stderr, "%s:%d: File contents don't match\n",
|
||||
test_filename, test_line);
|
||||
fprintf(stderr, " file=\"%s\"\n", f);
|
||||
if (n > 0)
|
||||
hexdump(contents, buff, n, 0);
|
||||
else {
|
||||
fprintf(stderr, " File empty, contents should be:\n");
|
||||
hexdump(buff, NULL, s, 0);
|
||||
}
|
||||
report_failure(test_extra);
|
||||
}
|
||||
free(contents);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call standard system() call, but build up the command line using
|
||||
* sprintf() conventions.
|
||||
@ -750,7 +812,11 @@ static int test_run(int i, const char *tmpdir)
|
||||
/* If there were no failures, we can remove the work dir. */
|
||||
if (failures == failures_before) {
|
||||
if (!keep_temp_files && chdir(tmpdir) == 0) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
systemf("rmdir /S /Q %s", tests[i].name);
|
||||
#else
|
||||
systemf("rm -rf %s", tests[i].name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* Return appropriate status. */
|
||||
@ -843,23 +909,94 @@ extract_reference_file(const char *name)
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
get_refdir(void)
|
||||
{
|
||||
char tried[512] = { '\0' };
|
||||
char buff[128];
|
||||
char *pwd, *p;
|
||||
|
||||
/* Get the current dir. */
|
||||
pwd = getcwd(NULL, 0);
|
||||
while (pwd[strlen(pwd) - 1] == '\n')
|
||||
pwd[strlen(pwd) - 1] = '\0';
|
||||
printf("PWD: %s\n", pwd);
|
||||
|
||||
/* Look for a known file. */
|
||||
snprintf(buff, sizeof(buff), "%s", pwd);
|
||||
p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
|
||||
if (p != NULL) goto success;
|
||||
strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
|
||||
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
|
||||
|
||||
snprintf(buff, sizeof(buff), "%s/test", pwd);
|
||||
p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
|
||||
if (p != NULL) goto success;
|
||||
strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
|
||||
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
|
||||
|
||||
snprintf(buff, sizeof(buff), "%s/%s/test", pwd, PROGRAM);
|
||||
p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
|
||||
if (p != NULL) goto success;
|
||||
strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
|
||||
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
|
||||
|
||||
if (memcmp(pwd, "/usr/obj", 8) == 0) {
|
||||
snprintf(buff, sizeof(buff), "%s", pwd + 8);
|
||||
p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
|
||||
if (p != NULL) goto success;
|
||||
strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
|
||||
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
|
||||
|
||||
snprintf(buff, sizeof(buff), "%s/test", pwd + 8);
|
||||
p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
|
||||
if (p != NULL) goto success;
|
||||
strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
|
||||
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
|
||||
DebugBreak();
|
||||
#endif
|
||||
printf("Unable to locate known reference file %s\n", KNOWNREF);
|
||||
printf(" Checked following directories:\n%s\n", tried);
|
||||
exit(1);
|
||||
|
||||
success:
|
||||
free(p);
|
||||
free(pwd);
|
||||
return strdup(buff);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static const int limit = sizeof(tests) / sizeof(tests[0]);
|
||||
int i, tests_run = 0, tests_failed = 0, opt;
|
||||
time_t now;
|
||||
char *refdir_alloc = NULL;
|
||||
char *progname, *p;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
char *testprg;
|
||||
#endif
|
||||
const char *opt_arg, *progname, *p;
|
||||
char tmpdir[256];
|
||||
char tmpdir_timestamp[256];
|
||||
|
||||
(void)argc; /* UNUSED */
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure open() function will be used with a binary mode. */
|
||||
/* on cygwin, we need something similar, but instead link against */
|
||||
/* a special startup object, binmode.o */
|
||||
_set_fmode(_O_BINARY);
|
||||
#endif
|
||||
/*
|
||||
* Name of this program, used to build root of our temp directory
|
||||
* tree.
|
||||
*/
|
||||
progname = p = argv[0];
|
||||
while (*p != '\0') {
|
||||
if (*p == '/')
|
||||
/* Support \ or / dir separators for Windows compat. */
|
||||
if (*p == '/' || *p == '\\')
|
||||
progname = p + 1;
|
||||
++p;
|
||||
}
|
||||
@ -877,39 +1014,61 @@ int main(int argc, char **argv)
|
||||
refdir = getenv(ENVBASE "_TEST_FILES");
|
||||
|
||||
/*
|
||||
* Parse options.
|
||||
* Parse options, without using getopt(), which isn't available
|
||||
* on all platforms.
|
||||
*/
|
||||
while ((opt = getopt(argc, argv, "dkp:qr:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
dump_on_failure = 1;
|
||||
++argv; /* Skip program name */
|
||||
while (*argv != NULL) {
|
||||
if (**argv != '-')
|
||||
break;
|
||||
case 'k':
|
||||
keep_temp_files = 1;
|
||||
break;
|
||||
case 'p':
|
||||
p = *argv++;
|
||||
++p; /* Skip '-' */
|
||||
while (*p != '\0') {
|
||||
opt = *p++;
|
||||
opt_arg = NULL;
|
||||
/* If 'opt' takes an argument, parse that. */
|
||||
if (opt == 'p' || opt == 'r') {
|
||||
if (*p != '\0')
|
||||
opt_arg = p;
|
||||
else if (*argv == NULL) {
|
||||
fprintf(stderr,
|
||||
"Option -%c requires argument.\n",
|
||||
opt);
|
||||
usage(progname);
|
||||
} else
|
||||
opt_arg = *argv++;
|
||||
p = ""; /* End of this option word. */
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
dump_on_failure = 1;
|
||||
break;
|
||||
case 'k':
|
||||
keep_temp_files = 1;
|
||||
break;
|
||||
case 'p':
|
||||
#ifdef PROGRAM
|
||||
testprog = optarg;
|
||||
testprog = opt_arg;
|
||||
#else
|
||||
usage(progname);
|
||||
usage(progname);
|
||||
#endif
|
||||
break;
|
||||
case 'q':
|
||||
quiet_flag++;
|
||||
break;
|
||||
case 'r':
|
||||
refdir = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(progname);
|
||||
break;
|
||||
case 'q':
|
||||
quiet_flag++;
|
||||
break;
|
||||
case 'r':
|
||||
refdir = opt_arg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(progname);
|
||||
}
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* Sanity-check that our options make sense.
|
||||
@ -918,6 +1077,18 @@ int main(int argc, char **argv)
|
||||
if (testprog == NULL)
|
||||
usage(progname);
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/*
|
||||
* Command.exe cannot accept the command used '/' with drive
|
||||
* name such as c:/xxx/command.exe when use '|' pipe handling.
|
||||
*/
|
||||
testprg = strdup(testprog);
|
||||
for (i = 0; testprg[i] != '\0'; i++) {
|
||||
if (testprg[i] == '/')
|
||||
testprg[i] = '\\';
|
||||
}
|
||||
testprog = testprg;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create a temp directory for the following tests.
|
||||
@ -943,16 +1114,8 @@ int main(int argc, char **argv)
|
||||
* If the user didn't specify a directory for locating
|
||||
* reference files, use the current directory for that.
|
||||
*/
|
||||
if (refdir == NULL) {
|
||||
systemf("/bin/pwd > %s/refdir", tmpdir);
|
||||
refdir = refdir_alloc = slurpfile(NULL, "%s/refdir", tmpdir);
|
||||
p = refdir + strlen(refdir);
|
||||
while (p[-1] == '\n') {
|
||||
--p;
|
||||
*p = '\0';
|
||||
}
|
||||
systemf("rm %s/refdir", tmpdir);
|
||||
}
|
||||
if (refdir == NULL)
|
||||
refdir = refdir_alloc = get_refdir();
|
||||
|
||||
/*
|
||||
* Banner with basic information.
|
||||
@ -971,7 +1134,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Run some or all of the individual tests.
|
||||
*/
|
||||
if (argc == 0) {
|
||||
if (*argv == NULL) {
|
||||
/* Default: Run all tests. */
|
||||
for (i = 0; i < limit; i++) {
|
||||
if (test_run(i, tmpdir))
|
||||
|
@ -33,28 +33,45 @@
|
||||
*/
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
/* Most POSIX platforms use the 'configure' script to build config.h */
|
||||
#include "../../config.h"
|
||||
#include "config.h"
|
||||
#elif defined(__FreeBSD__)
|
||||
/* Building as part of FreeBSD system requires a pre-built config.h. */
|
||||
#include "../config_freebsd.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "config_freebsd.h"
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Win32 can't run the 'configure' script. */
|
||||
#include "../config_windows.h"
|
||||
#include "config_windows.h"
|
||||
#else
|
||||
/* Warn if the library hasn't been (automatically or manually) configured. */
|
||||
#error Oops: No config.h and no pre-built configuration in test.h.
|
||||
#endif
|
||||
|
||||
#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/stat.h>
|
||||
#ifndef _WIN32
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef USE_DMALLOC
|
||||
@ -65,7 +82,8 @@
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/cdefs.h> /* For __FBSDID */
|
||||
#else
|
||||
#define __FBSDID(a) /* null */
|
||||
#undef __FBSDID
|
||||
#define __FBSDID(a) struct _undefined_hack
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -107,6 +125,8 @@
|
||||
/* Assert that file contents match a string; supports printf-style arguments. */
|
||||
#define assertFileContents \
|
||||
test_setup(__FILE__, __LINE__);test_assert_file_contents
|
||||
#define assertTextFileContents \
|
||||
test_setup(__FILE__, __LINE__);test_assert_text_file_contents
|
||||
|
||||
/*
|
||||
* This would be simple with C99 variadic macros, but I don't want to
|
||||
@ -129,6 +149,7 @@ int test_assert_equal_string(const char *, int, const char *v1, const char *, co
|
||||
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 *, ...);
|
||||
|
||||
@ -147,4 +168,4 @@ void extract_reference_file(const char *);
|
||||
*/
|
||||
|
||||
/* Pathname of exe to be tested. */
|
||||
char *testprog;
|
||||
const char *testprog;
|
||||
|
@ -29,6 +29,11 @@ __FBSDID("$FreeBSD$");
|
||||
* This first test does basic sanity checks on the environment. For
|
||||
* most of these, we just exit on failure.
|
||||
*/
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define DEV_NULL "/dev/null"
|
||||
#else
|
||||
#define DEV_NULL "NUL"
|
||||
#endif
|
||||
|
||||
DEFINE_TEST(test_0)
|
||||
{
|
||||
@ -46,9 +51,9 @@ DEFINE_TEST(test_0)
|
||||
* Try to succesfully run the program; this requires that
|
||||
* we know some option that will succeed.
|
||||
*/
|
||||
if (0 == systemf("%s --version >/dev/null", testprog)) {
|
||||
if (0 == systemf("%s --version >" DEV_NULL, testprog)) {
|
||||
/* This worked. */
|
||||
} else if (0 == systemf("%s -W version >/dev/null", testprog)) {
|
||||
} else if (0 == systemf("%s -W version >" DEV_NULL, testprog)) {
|
||||
/* This worked. */
|
||||
} else {
|
||||
failure("Unable to successfully run any of the following:\n"
|
||||
|
@ -29,7 +29,9 @@ static void
|
||||
verify_files(const char *target)
|
||||
{
|
||||
struct stat st, st2;
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
char buff[128];
|
||||
#endif
|
||||
int r;
|
||||
|
||||
/*
|
||||
@ -42,7 +44,12 @@ verify_files(const char *target)
|
||||
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);
|
||||
@ -54,7 +61,12 @@ verify_files(const char *target)
|
||||
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);
|
||||
@ -69,6 +81,7 @@ verify_files(const char *target)
|
||||
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);
|
||||
@ -80,6 +93,7 @@ verify_files(const char *target)
|
||||
assertEqualString(buff, "file");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Another file with 1 link and different permissions. */
|
||||
r = lstat("file2", &st);
|
||||
@ -88,7 +102,13 @@ verify_files(const char *target)
|
||||
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);
|
||||
@ -100,7 +120,11 @@ verify_files(const char *target)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +149,7 @@ basic_cpio(const char *target,
|
||||
|
||||
/* Verify stderr. */
|
||||
failure("Expected: %s, options=%s", se, pack_options);
|
||||
assertFileContents(se, strlen(se), "pack.err");
|
||||
assertTextFileContents(se, "pack.err");
|
||||
|
||||
/*
|
||||
* Use cpio to unpack the archive into another directory.
|
||||
@ -137,7 +161,7 @@ basic_cpio(const char *target,
|
||||
|
||||
/* Verify stderr. */
|
||||
failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
|
||||
assertFileContents(se, strlen(se), "unpack.err");
|
||||
assertTextFileContents(se, "unpack.err");
|
||||
|
||||
verify_files(target);
|
||||
|
||||
@ -165,7 +189,7 @@ passthrough(const char *target)
|
||||
/* Verify stderr. */
|
||||
failure("Error invoking %s -p in dir %s",
|
||||
testprog, target);
|
||||
assertFileContents("1 block\n", 8, "stderr");
|
||||
assertTextFileContents("1 block\n", "stderr");
|
||||
|
||||
verify_files(target);
|
||||
chdir("..");
|
||||
@ -219,7 +243,16 @@ DEFINE_TEST(test_basic)
|
||||
basic_cpio("copy_odc", "--format=odc", "", "2 blocks\n");
|
||||
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
|
||||
/* Copy in one step using -p */
|
||||
passthrough("passthrough");
|
||||
|
||||
|
@ -112,7 +112,7 @@ DEFINE_TEST(test_format_newc)
|
||||
return;
|
||||
|
||||
/* Verify that nothing went to stderr. */
|
||||
assertFileContents("2 blocks\n", 9, "newc.err");
|
||||
assertTextFileContents("2 blocks\n", "newc.err");
|
||||
|
||||
/* Verify that stdout is a well-formed cpio file in "newc" format. */
|
||||
p = slurpfile(&s, "newc.out");
|
||||
@ -128,7 +128,12 @@ DEFINE_TEST(test_format_newc)
|
||||
assert(is_hex(e, 110)); /* Entire header is octal digits. */
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
ino = from_hex(e + 6, 8); /* ino */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Group members bits and others bits do not work. */
|
||||
assertEqualInt(0x8180, from_hex(e + 14, 8) & 0xffc0); /* Mode */
|
||||
#else
|
||||
assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */
|
||||
#endif
|
||||
assertEqualInt(from_hex(e + 22, 8), getuid()); /* uid */
|
||||
gid = from_hex(e + 30, 8); /* gid */
|
||||
assertEqualMem(e + 38, "00000003", 8); /* nlink */
|
||||
@ -160,14 +165,23 @@ DEFINE_TEST(test_format_newc)
|
||||
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(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;
|
||||
assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */
|
||||
@ -179,17 +193,26 @@ DEFINE_TEST(test_format_newc)
|
||||
ns += 3 & (-ns - 2);
|
||||
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));
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
assert(is_hex(e + 6, 8)); /* ino */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* 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 */
|
||||
#endif
|
||||
assertEqualInt(from_hex(e + 22, 8), getuid()); /* uid */
|
||||
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
|
||||
#ifndef NLINKS_INACCURATE_FOR_DIRS
|
||||
assertEqualMem(e + 38, "00000002", 8); /* nlink */
|
||||
#endif
|
||||
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. */
|
||||
@ -214,7 +237,12 @@ DEFINE_TEST(test_format_newc)
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
failure("If these aren't the same, then the hardlink detection failed to match them.");
|
||||
assertEqualInt(ino, from_hex(e + 6, 8)); /* ino */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Group members bits and others bits do not work. */
|
||||
assertEqualInt(0x8180, from_hex(e + 14, 8) & 0xffc0); /* Mode */
|
||||
#else
|
||||
assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */
|
||||
#endif
|
||||
assertEqualInt(from_hex(e + 22, 8), getuid()); /* uid */
|
||||
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
|
||||
assertEqualMem(e + 38, "00000003", 8); /* nlink */
|
||||
|
@ -25,12 +25,13 @@
|
||||
#include "test.h"
|
||||
__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. */
|
||||
@ -49,7 +50,7 @@ unpack_test(const char *from, const char *options, const char *se)
|
||||
|
||||
/* Verify that nothing went to stderr. */
|
||||
failure("Error invoking %s -i %s < %s", testprog, options, from);
|
||||
assertFileContents(se, strlen(se), "unpack.err");
|
||||
assertTextFileContents(se, "unpack.err");
|
||||
|
||||
/*
|
||||
* Verify unpacked files.
|
||||
@ -61,7 +62,11 @@ unpack_test(const char *from, const char *options, const char *se)
|
||||
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);
|
||||
@ -74,7 +79,11 @@ unpack_test(const char *from, const char *options, const char *se)
|
||||
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);
|
||||
@ -89,6 +98,7 @@ unpack_test(const char *from, const char *options, const char *se)
|
||||
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);
|
||||
@ -100,13 +110,18 @@ unpack_test(const char *from, const char *options, const char *se)
|
||||
assertEqualString(buff, "file");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
}
|
||||
|
||||
chdir("..");
|
||||
|
@ -23,7 +23,11 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <sys/utime.h>
|
||||
#else
|
||||
#include <utime.h>
|
||||
#endif
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static struct {
|
||||
@ -118,7 +122,7 @@ DEFINE_TEST(test_option_a)
|
||||
/* Copy the file without -a; should change the atime. */
|
||||
r = systemf("echo %s | %s -pd copy-no-a > copy-no-a.out 2>copy-no-a.err", files[1].name, testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertFileContents("1 block\n", 8, "copy-no-a.err");
|
||||
assertTextFileContents("1 block\n", "copy-no-a.err");
|
||||
assertEmptyFile("copy-no-a.out");
|
||||
assertEqualInt(0, stat(files[1].name, &st));
|
||||
failure("Copying file without -a should have changed atime.");
|
||||
@ -127,7 +131,7 @@ DEFINE_TEST(test_option_a)
|
||||
/* Archive the file without -a; should change the atime. */
|
||||
r = systemf("echo %s | %s -o > archive-no-a.out 2>archive-no-a.err", files[2].name, testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertFileContents("1 block\n", 8, "copy-no-a.err");
|
||||
assertTextFileContents("1 block\n", "copy-no-a.err");
|
||||
assertEqualInt(0, stat(files[2].name, &st));
|
||||
failure("Archiving file without -a should have changed atime.");
|
||||
assert(st.st_atime != files[2].atime_sec);
|
||||
@ -142,7 +146,7 @@ DEFINE_TEST(test_option_a)
|
||||
r = systemf("echo %s | %s -pad copy-a > copy-a.out 2>copy-a.err",
|
||||
files[3].name, testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertFileContents("1 block\n", 8, "copy-a.err");
|
||||
assertTextFileContents("1 block\n", "copy-a.err");
|
||||
assertEmptyFile("copy-a.out");
|
||||
assertEqualInt(0, stat(files[3].name, &st));
|
||||
failure("Copying file with -a should not have changed atime.");
|
||||
@ -152,7 +156,7 @@ DEFINE_TEST(test_option_a)
|
||||
r = systemf("echo %s | %s -oa > archive-a.out 2>archive-a.err",
|
||||
files[4].name, testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertFileContents("1 block\n", 8, "copy-a.err");
|
||||
assertTextFileContents("1 block\n", "copy-a.err");
|
||||
assertEqualInt(0, stat(files[4].name, &st));
|
||||
failure("Archiving file with -a should not have changed atime.");
|
||||
assertEqualInt(st.st_atime, files[4].atime_sec);
|
||||
|
@ -90,7 +90,7 @@ DEFINE_TEST(test_option_c)
|
||||
close(filelist);
|
||||
r = systemf("%s -oc <filelist >basic.out 2>basic.err", testprog);
|
||||
/* Verify that nothing went to stderr. */
|
||||
assertFileContents("1 block\n", 8, "basic.err");
|
||||
assertTextFileContents("1 block\n", "basic.err");
|
||||
|
||||
/* Assert that the program finished. */
|
||||
failure("%s -oc crashed", testprog);
|
||||
@ -114,7 +114,12 @@ DEFINE_TEST(test_option_c)
|
||||
dev = from_octal(e + 6, 6);
|
||||
assert(is_octal(e + 12, 6)); /* ino */
|
||||
ino = from_octal(e + 12, 6);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Group members bits and others bits do not work. */
|
||||
assertEqualMem(e + 18, "100666", 6); /* Mode */
|
||||
#else
|
||||
assertEqualMem(e + 18, "100644", 6); /* Mode */
|
||||
#endif
|
||||
assertEqualInt(from_octal(e + 24, 6), getuid()); /* uid */
|
||||
assert(is_octal(e + 30, 6)); /* gid */
|
||||
gid = from_octal(e + 30, 6);
|
||||
@ -136,7 +141,11 @@ DEFINE_TEST(test_option_c)
|
||||
assertEqualMem(e + 0, "070707", 6); /* Magic */
|
||||
assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */
|
||||
assert(dev != 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(gid, from_octal(e + 30, 6)); /* gid */
|
||||
assertEqualMem(e + 36, "000001", 6); /* nlink */
|
||||
@ -147,10 +156,21 @@ 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" */
|
||||
assert(is_octal(e, 76));
|
||||
@ -161,12 +181,19 @@ DEFINE_TEST(test_option_c)
|
||||
/* Ino must be different from first entry. */
|
||||
assert(is_octal(e + 12, 6)); /* ino */
|
||||
assert(dev != from_octal(e + 12, 6));
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Group members bits and others bits do not work. */
|
||||
assertEqualMem(e + 18, "040777", 6); /* Mode */
|
||||
#else
|
||||
assertEqualMem(e + 18, "040775", 6); /* Mode */
|
||||
#endif
|
||||
assertEqualInt(from_octal(e + 24, 6), getuid()); /* uid */
|
||||
/* Gid should be same as first entry. */
|
||||
assert(is_octal(e + 30, 6)); /* gid */
|
||||
assertEqualInt(gid, from_octal(e + 30, 6));
|
||||
#ifndef NLINKS_INACCURATE_FOR_DIRS
|
||||
assertEqualMem(e + 36, "000002", 6); /* Nlink */
|
||||
#endif
|
||||
t = from_octal(e + 48, 11); /* mtime */
|
||||
assert(t <= now); /* File wasn't created in future. */
|
||||
assert(t >= now - 2); /* File was created w/in last 2 secs. */
|
||||
|
@ -42,7 +42,7 @@ DEFINE_TEST(test_option_d)
|
||||
/* Create an archive. */
|
||||
r = systemf("echo dir/file | %s -o > archive.cpio 2>archive.err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertFileContents("1 block\n", 8, "archive.err");
|
||||
assertTextFileContents("1 block\n", "archive.err");
|
||||
assertEqualInt(0, stat("archive.cpio", &st));
|
||||
assertEqualInt(512, st.st_size);
|
||||
|
||||
@ -62,7 +62,7 @@ DEFINE_TEST(test_option_d)
|
||||
r = systemf("%s -id < ../archive.cpio >out 2>err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertEmptyFile("out");
|
||||
assertFileContents("1 block\n", 8, "err");
|
||||
assertTextFileContents("1 block\n", "err");
|
||||
/* And the file should be restored. */
|
||||
assertEqualInt(0, stat("dir/file", &st));
|
||||
}
|
||||
|
@ -51,14 +51,24 @@ DEFINE_TEST(test_option_f)
|
||||
assertEqualInt(0, access("t0/b234", F_OK));
|
||||
|
||||
/* Don't extract 'a*' files. */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Single quotes isn't used by command.exe. */
|
||||
unpack("t1", "-f a*");
|
||||
#else
|
||||
unpack("t1", "-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));
|
||||
|
||||
/* Don't extract 'b*' files. */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Single quotes isn't used by command.exe. */
|
||||
unpack("t2", "-f b*");
|
||||
#else
|
||||
unpack("t2", "-f 'b*'");
|
||||
#endif
|
||||
assertEqualInt(0, access("t2/a123", F_OK));
|
||||
assertEqualInt(0, access("t2/a234", F_OK));
|
||||
assert(0 != access("t2/b123", F_OK));
|
||||
|
@ -45,7 +45,7 @@ DEFINE_TEST(test_option_m)
|
||||
now = time(NULL);
|
||||
assertEqualInt(r, 0);
|
||||
assertEmptyFile("out");
|
||||
assertFileContents("1 block\n", 8, "err");
|
||||
assertTextFileContents("1 block\n", "err");
|
||||
assertEqualInt(0, stat("file", &st));
|
||||
/* Should have been created within the last few seconds. */
|
||||
assert(st.st_mtime <= now);
|
||||
@ -60,7 +60,7 @@ DEFINE_TEST(test_option_m)
|
||||
now = time(NULL);
|
||||
assertEqualInt(r, 0);
|
||||
assertEmptyFile("out");
|
||||
assertFileContents("1 block\n", 8, "err");
|
||||
assertTextFileContents("1 block\n", "err");
|
||||
assertEqualInt(0, stat("file", &st));
|
||||
/*
|
||||
* mtime in reference archive is '1' == 1 second after
|
||||
|
@ -28,20 +28,58 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_t)
|
||||
{
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
/* List reference archive, make sure the TOC is correct. */
|
||||
extract_reference_file("test_option_t.cpio");
|
||||
r = systemf("%s -it < test_option_t.cpio >t.out 2>t.err", testprog);
|
||||
r = systemf("%s -it < test_option_t.cpio >it.out 2>it.err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertFileContents("1 block\n", 8, "t.err");
|
||||
assertTextFileContents("1 block\n", "it.err");
|
||||
extract_reference_file("test_option_t.stdout");
|
||||
assertEqualFile("t.out", "test_option_t.stdout");
|
||||
p = slurpfile(NULL, "test_option_t.stdout");
|
||||
assertTextFileContents(p, "it.out");
|
||||
free(p);
|
||||
|
||||
/* We accept plain "-t" as a synonym for "-it" */
|
||||
r = systemf("%s -t < test_option_t.cpio >t.out 2>t.err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertTextFileContents("1 block\n", "t.err");
|
||||
extract_reference_file("test_option_t.stdout");
|
||||
p = slurpfile(NULL, "test_option_t.stdout");
|
||||
assertTextFileContents(p, "t.out");
|
||||
free(p);
|
||||
|
||||
/* But "-ot" is an error. */
|
||||
assert(0 != systemf("%s -ot < test_option_t.cpio >ot.out 2>ot.err",
|
||||
testprog));
|
||||
assertEmptyFile("ot.out");
|
||||
|
||||
/* List reference archive verbosely, make sure the TOC is correct. */
|
||||
r = systemf("%s -itv < test_option_t.cpio >tv.out 2>tv.err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertFileContents("1 block\n", 8, "tv.err");
|
||||
assertTextFileContents("1 block\n", "tv.err");
|
||||
extract_reference_file("test_option_tv.stdout");
|
||||
assertEqualFile("tv.out", "test_option_tv.stdout");
|
||||
|
||||
/* This doesn't work because the usernames on different systems
|
||||
* are different and cpio now looks up numeric UIDs on
|
||||
* the local system. */
|
||||
/* assertEqualFile("tv.out", "test_option_tv.stdout"); */
|
||||
|
||||
/* List reference archive with numeric IDs, verify TOC is correct. */
|
||||
r = systemf("%s -itnv < test_option_t.cpio >itnv.out 2>itnv.err",
|
||||
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"); */
|
||||
|
||||
/* But "-n" without "-t" is an error. */
|
||||
assert(0 != systemf("%s -in < test_option_t.cpio >in.out 2>in.err",
|
||||
testprog));
|
||||
assertEmptyFile("in.out");
|
||||
}
|
||||
|
@ -23,7 +23,11 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test.h"
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <sys/utime.h>
|
||||
#else
|
||||
#include <utime.h>
|
||||
#endif
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
DEFINE_TEST(test_option_u)
|
||||
|
@ -77,7 +77,11 @@ verify(const char *p, size_t s)
|
||||
/* All terminated by a newline. */
|
||||
assert(s >= 1);
|
||||
failure("Version: %s", p);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
assertEqualMem(q, "\r\n", 2);
|
||||
#else
|
||||
assertEqualMem(q, "\n", 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,10 +43,17 @@ DEFINE_TEST(test_option_y)
|
||||
testprog);
|
||||
failure("-y (bzip) option seems to be broken");
|
||||
if (assertEqualInt(r, 0)) {
|
||||
assertFileContents("1 block\n", 8, "archive.err");
|
||||
/* Check that the archive file has a bzip2 signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "BZh9", 4);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
if (strstr(p, "bzip2 compression not supported") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without bzip2 support");
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,9 +44,16 @@ DEFINE_TEST(test_option_z)
|
||||
failure("-z option seems to be broken");
|
||||
assertEqualInt(r, 0);
|
||||
if (r == 0) {
|
||||
/* Check that the archive file has a gzip signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x1f\x8b\x08\x00", 4);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
if (strstr(p, "gzip compression not supported") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without gzip support");
|
||||
} else {
|
||||
/* Check that the archive file has a gzip signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x1f\x8b\x08\x00", 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,24 +27,67 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "../cpio.h"
|
||||
|
||||
#if 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
|
||||
* their /etc/passwd. Likely values are 513 (None), 545 (Users),
|
||||
* or 544 (Administrators). Just check for one of those...
|
||||
* TODO: Handle non-English localizations...e.g. French 'Administrateur'
|
||||
* Use CreateWellKnownSID() and LookupAccountName()?
|
||||
*/
|
||||
#define ROOT "Administrator"
|
||||
#define ROOT_UID 500
|
||||
#define ROOT_GID1 513
|
||||
#define ROOT_GID2 545
|
||||
#define ROOT_GID3 544
|
||||
#else
|
||||
#define ROOT "root"
|
||||
#define ROOT_UID 0
|
||||
#define ROOT_GID 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");
|
||||
#else
|
||||
int uid, gid;
|
||||
|
||||
cpio_progname = "Ignore this message";
|
||||
|
||||
assertEqualInt(0, owner_parse("root", &uid, &gid));
|
||||
assertEqualInt(0, uid);
|
||||
assertEqualInt(0, owner_parse(ROOT, &uid, &gid));
|
||||
assertEqualInt(ROOT_UID, uid);
|
||||
assertEqualInt(-1, gid);
|
||||
|
||||
|
||||
assertEqualInt(0, owner_parse("root:", &uid, &gid));
|
||||
assertEqualInt(0, uid);
|
||||
assertEqualInt(0, gid);
|
||||
assertEqualInt(0, owner_parse(ROOT ":", &uid, &gid));
|
||||
assertEqualInt(ROOT_UID, uid);
|
||||
#if defined(__CYGWIN__)
|
||||
{
|
||||
int gidIsOneOf = (ROOT_GID1 == gid)
|
||||
|| (ROOT_GID2 == gid)
|
||||
|| (ROOT_GID3 == gid);
|
||||
assertEqualInt(1, gidIsOneOf);
|
||||
}
|
||||
#else
|
||||
assertEqualInt(ROOT_GID, gid);
|
||||
#endif
|
||||
|
||||
assertEqualInt(0, owner_parse("root.", &uid, &gid));
|
||||
assertEqualInt(0, uid);
|
||||
assertEqualInt(0, gid);
|
||||
assertEqualInt(0, owner_parse(ROOT ".", &uid, &gid));
|
||||
assertEqualInt(ROOT_UID, uid);
|
||||
#if defined(__CYGWIN__)
|
||||
{
|
||||
int gidIsOneOf = (ROOT_GID1 == gid)
|
||||
|| (ROOT_GID2 == gid)
|
||||
|| (ROOT_GID3 == gid);
|
||||
assertEqualInt(1, gidIsOneOf);
|
||||
}
|
||||
#else
|
||||
assertEqualInt(ROOT_GID, gid);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO: Lookup current user/group name, build strings and
|
||||
@ -62,7 +105,8 @@ DEFINE_TEST(test_owner_parse)
|
||||
*/
|
||||
|
||||
assertEqualInt(1, owner_parse(":nonexistentgroup", &uid, &gid));
|
||||
assertEqualInt(1, owner_parse("root:nonexistentgroup", &uid, &gid));
|
||||
assertEqualInt(1, owner_parse(ROOT ":nonexistentgroup", &uid, &gid));
|
||||
assertEqualInt(1,
|
||||
owner_parse("nonexistentuser:nonexistentgroup", &uid, &gid));
|
||||
#endif
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ DEFINE_TEST(test_passthrough_dotdot)
|
||||
assertEqualInt(0, chdir(".."));
|
||||
|
||||
/* Verify stderr and stdout. */
|
||||
assertFileContents("../.\n../file\n1 block\n", 21, "stderr");
|
||||
assertTextFileContents("../.\n../file\n1 block\n", "stderr");
|
||||
assertEmptyFile("stdout");
|
||||
|
||||
/* Regular file. */
|
||||
@ -80,7 +80,11 @@ DEFINE_TEST(test_passthrough_dotdot)
|
||||
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);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ DEFINE_TEST(test_passthrough_reverse)
|
||||
assertEqualInt(0, chdir("out"));
|
||||
|
||||
/* Verify stderr and stdout. */
|
||||
assertFileContents("out/dir/file\nout/dir\n1 block\n", 29,
|
||||
assertTextFileContents("out/dir/file\nout/dir\n1 block\n",
|
||||
"../stderr");
|
||||
assertEmptyFile("../stdout");
|
||||
|
||||
@ -85,7 +85,11 @@ DEFINE_TEST(test_passthrough_reverse)
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@ -95,7 +99,11 @@ DEFINE_TEST(test_passthrough_reverse)
|
||||
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);
|
||||
}
|
||||
|
@ -38,10 +38,22 @@ __FBSDID("$FreeBSD$");
|
||||
*
|
||||
* The specification in SUSv2 is a bit incomplete, I assume the following:
|
||||
* Trailing '-' in [...] is not special.
|
||||
*
|
||||
* TODO: Figure out if there's a good way to extend this to handle
|
||||
* Windows paths that use '\' as a path separator. <sigh>
|
||||
*/
|
||||
|
||||
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));
|
||||
|
||||
/* 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));
|
||||
@ -68,6 +80,8 @@ DEFINE_TEST(test_pathmatch)
|
||||
assertEqualInt(1, pathmatch("*a*", "defaaaaaaa", 0));
|
||||
assertEqualInt(0, pathmatch("a*", "defghi", 0));
|
||||
assertEqualInt(0, 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));
|
||||
@ -84,6 +98,7 @@ DEFINE_TEST(test_pathmatch)
|
||||
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));
|
||||
@ -95,6 +110,14 @@ DEFINE_TEST(test_pathmatch)
|
||||
assertEqualInt(0, pathmatch("abc[d-fh-k]", "abcl", 0));
|
||||
assertEqualInt(0, 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));
|
||||
|
||||
/* I assume: Trailing '-' is non-special. */
|
||||
assertEqualInt(0, pathmatch("abc[d-fh-]", "abcl", 0));
|
||||
assertEqualInt(1, pathmatch("abc[d-fh-]", "abch", 0));
|
||||
@ -138,12 +161,23 @@ DEFINE_TEST(test_pathmatch)
|
||||
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));
|
||||
|
||||
/*
|
||||
* Because '.' and '/' have special meanings, we can
|
||||
* identify many equivalent paths even if they're expressed
|
||||
* differently.
|
||||
* 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));
|
||||
@ -162,4 +196,48 @@ DEFINE_TEST(test_pathmatch)
|
||||
assertEqualInt(1, pathmatch("./abc/./def", "abc/def/./", 0));
|
||||
failure("Trailing '/.' is still the same directory.");
|
||||
assertEqualInt(1, pathmatch("./abc*/./def", "abc/def/.", 0));
|
||||
|
||||
/* Matches not anchored at beginning. */
|
||||
assertEqualInt(0,
|
||||
pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
|
||||
assertEqualInt(1,
|
||||
pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_START));
|
||||
assertEqualInt(0,
|
||||
pathmatch("^bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
|
||||
assertEqualInt(1,
|
||||
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));
|
||||
assertEqualInt(0,
|
||||
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));
|
||||
assertEqualInt(1,
|
||||
pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_END));
|
||||
assertEqualInt(1,
|
||||
pathmatch("abcd", "abcd/", PATHMATCH_NO_ANCHOR_END));
|
||||
assertEqualInt(1,
|
||||
pathmatch("abcd", "abcd/.", PATHMATCH_NO_ANCHOR_END));
|
||||
assertEqualInt(0,
|
||||
pathmatch("abc", "abcd", PATHMATCH_NO_ANCHOR_END));
|
||||
assertEqualInt(1,
|
||||
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));
|
||||
assertEqualInt(1,
|
||||
pathmatch("a/b/c$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
|
||||
assertEqualInt(1,
|
||||
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));
|
||||
assertEqualInt(0,
|
||||
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));
|
||||
assertEqualInt(1,
|
||||
pathmatch("a/b/c/$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
|
||||
assertEqualInt(0,
|
||||
pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user