Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Apr 2009 04:04:57 +0000 (UTC)
From:      Tim Kientzle <kientzle@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r191192 - in head/usr.bin/cpio: . test
Message-ID:  <200904170404.n3H44vIV007538@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904170404.n3H44vIV007538>