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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to