svn commit: r191192 - in head/usr.bin/cpio: . test
Tim Kientzle
kientzle at FreeBSD.org
Fri Apr 17 04:04:58 UTC 2009
Author: kientzle
Date: Fri Apr 17 04:04:57 2009
New Revision: 191192
URL: http://svn.freebsd.org/changeset/base/191192
Log:
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
Modified:
head/usr.bin/cpio/Makefile
head/usr.bin/cpio/bsdcpio.1
head/usr.bin/cpio/cmdline.c
head/usr.bin/cpio/cpio.c
head/usr.bin/cpio/cpio.h
head/usr.bin/cpio/cpio_platform.h
head/usr.bin/cpio/pathmatch.c
head/usr.bin/cpio/pathmatch.h
head/usr.bin/cpio/test/main.c
head/usr.bin/cpio/test/test.h
head/usr.bin/cpio/test/test_0.c
head/usr.bin/cpio/test/test_basic.c
head/usr.bin/cpio/test/test_format_newc.c
head/usr.bin/cpio/test/test_gcpio_compat.c
head/usr.bin/cpio/test/test_option_a.c
head/usr.bin/cpio/test/test_option_c.c
head/usr.bin/cpio/test/test_option_d.c
head/usr.bin/cpio/test/test_option_f.c
head/usr.bin/cpio/test/test_option_m.c
head/usr.bin/cpio/test/test_option_t.c
head/usr.bin/cpio/test/test_option_u.c
head/usr.bin/cpio/test/test_option_version.c
head/usr.bin/cpio/test/test_option_y.c
head/usr.bin/cpio/test/test_option_z.c
head/usr.bin/cpio/test/test_owner_parse.c
head/usr.bin/cpio/test/test_passthrough_dotdot.c
head/usr.bin/cpio/test/test_passthrough_reverse.c
head/usr.bin/cpio/test/test_pathmatch.c
Modified: head/usr.bin/cpio/Makefile
==============================================================================
--- head/usr.bin/cpio/Makefile Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/Makefile Fri Apr 17 04:04:57 2009 (r191192)
@@ -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
Modified: head/usr.bin/cpio/bsdcpio.1
==============================================================================
--- head/usr.bin/cpio/bsdcpio.1 Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/bsdcpio.1 Fri Apr 17 04:04:57 2009 (r191192)
@@ -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 .
Modified: head/usr.bin/cpio/cmdline.c
==============================================================================
--- head/usr.bin/cpio/cmdline.c Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/cmdline.c Fri Apr 17 04:04:57 2009 (r191192)
@@ -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' },
Modified: head/usr.bin/cpio/cpio.c
==============================================================================
--- head/usr.bin/cpio/cpio.c Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/cpio.c Fri Apr 17 04:04:57 2009 (r191192)
@@ -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
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
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
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, stru
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, stru
}
}
- restore_time(cpio, entry, srcpath, fd);
+ fd = restore_time(cpio, entry, srcpath, fd);
cleanup:
if (cpio->verbose)
@@ -657,7 +741,7 @@ cleanup:
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 a
(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 a
#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 a
#endif
cpio_warnc(errno, "Can't update time for %s", name);
#endif
+ return (fd);
}
@@ -858,6 +954,7 @@ list_item_verbose(struct cpio *cpio, str
{
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, str
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, str
/* 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",
Modified: head/usr.bin/cpio/cpio.h
==============================================================================
--- head/usr.bin/cpio/cpio.h Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/cpio.h Fri Apr 17 04:04:57 2009 (r191192)
@@ -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;
Modified: head/usr.bin/cpio/cpio_platform.h
==============================================================================
--- head/usr.bin/cpio/cpio_platform.h Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/cpio_platform.h Fri Apr 17 04:04:57 2009 (r191192)
@@ -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 */
Modified: head/usr.bin/cpio/pathmatch.c
==============================================================================
--- head/usr.bin/cpio/pathmatch.c Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/pathmatch.c Fri Apr 17 04:04:57 2009 (r191192)
@@ -101,11 +101,10 @@ pm_list(const char *start, const char *e
*/
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 fla
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 fla
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 fla
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,
/* 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);
}
Modified: head/usr.bin/cpio/pathmatch.h
==============================================================================
--- head/usr.bin/cpio/pathmatch.h Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/pathmatch.h Fri Apr 17 04:04:57 2009 (r191192)
@@ -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
Modified: head/usr.bin/cpio/test/main.c
==============================================================================
--- head/usr.bin/cpio/test/main.c Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/test/main.c Fri Apr 17 04:04:57 2009 (r191192)
@@ -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 *fil
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,
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, c
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 *bu
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 *bu
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 *t
/* 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;
- break;
- case 'k':
- keep_temp_files = 1;
+ ++argv; /* Skip program name */
+ while (*argv != NULL) {
+ if (**argv != '-')
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))
Modified: head/usr.bin/cpio/test/test.h
==============================================================================
--- head/usr.bin/cpio/test/test.h Fri Apr 17 03:49:26 2009 (r191191)
+++ head/usr.bin/cpio/test/test.h Fri Apr 17 04:04:57 2009 (r191192)
@@ -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__)
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list