summaryrefslogtreecommitdiffstats
path: root/usr.bin/cpio
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2010-05-08 16:47:33 +0000
committerkientzle <kientzle@FreeBSD.org>2010-05-08 16:47:33 +0000
commit94ac1169df0fe3609aa671582574d421e89b7ff3 (patch)
tree551fb87f2d73c01d8a568f60595409846d1450d2 /usr.bin/cpio
parent4ae7167075e6eae3f41a1efdb35bb448a52bddb0 (diff)
downloadFreeBSD-src-94ac1169df0fe3609aa671582574d421e89b7ff3.zip
FreeBSD-src-94ac1169df0fe3609aa671582574d421e89b7ff3.tar.gz
bsdcpio 2.8.3
Diffstat (limited to 'usr.bin/cpio')
-rw-r--r--usr.bin/cpio/Makefile4
-rw-r--r--usr.bin/cpio/bsdcpio.131
-rw-r--r--usr.bin/cpio/cmdline.c42
-rw-r--r--usr.bin/cpio/config_freebsd.h67
-rw-r--r--usr.bin/cpio/cpio.c576
-rw-r--r--usr.bin/cpio/cpio.h23
-rw-r--r--usr.bin/cpio/cpio_platform.h43
-rw-r--r--usr.bin/cpio/err.c17
-rw-r--r--usr.bin/cpio/err.h43
-rw-r--r--usr.bin/cpio/line_reader.c171
-rw-r--r--usr.bin/cpio/line_reader.h37
-rw-r--r--usr.bin/cpio/matching.c145
-rw-r--r--usr.bin/cpio/matching.h18
-rw-r--r--usr.bin/cpio/pathmatch.c14
-rw-r--r--usr.bin/cpio/pathmatch.h6
15 files changed, 675 insertions, 562 deletions
diff --git a/usr.bin/cpio/Makefile b/usr.bin/cpio/Makefile
index 499b173..80cf1fa 100644
--- a/usr.bin/cpio/Makefile
+++ b/usr.bin/cpio/Makefile
@@ -3,8 +3,8 @@
.include <bsd.own.mk>
PROG= bsdcpio
-BSDCPIO_VERSION_STRING=2.7.0
-SRCS= cpio.c cmdline.c err.c matching.c pathmatch.c
+BSDCPIO_VERSION_STRING=2.8.3
+SRCS= cpio.c cmdline.c err.c line_reader.c matching.c pathmatch.c
CFLAGS+= -DBSDCPIO_VERSION_STRING=\"${BSDCPIO_VERSION_STRING}\"
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
.ifdef RELEASE_CRUNCH
diff --git a/usr.bin/cpio/bsdcpio.1 b/usr.bin/cpio/bsdcpio.1
index 6017bc5..79b6997 100644
--- a/usr.bin/cpio/bsdcpio.1
+++ b/usr.bin/cpio/bsdcpio.1
@@ -80,6 +80,9 @@ specified directory.
Unless specifically stated otherwise, options are applicable in
all operating modes.
.Bl -tag -width indent
+.It Fl 0
+Read filenames separated by NUL characters instead of newlines.
+This is necessary if any of the filenames being read might contain newlines.
.It Fl A
(o mode only)
Append to the specified archive.
@@ -142,6 +145,11 @@ for more complete information about the
formats currently supported by the underlying
.Xr libarchive 3
library.
+.It Fl H Ar format
+Synonym for
+.Fl -format .
+.It Fl h , Fl -help
+Print usage information.
.It Fl I Ar file
Read archive from
.Ar file .
@@ -154,6 +162,14 @@ Disable security checks during extraction or copying.
This allows extraction via symbolic links and path names containing
.Sq ..
in the name.
+.It Fl J
+(o mode only)
+Compress the file with xz-compatible compression before writing it.
+In input mode, this option is ignored; xz compression is recognized
+automatically on input.
+.It Fl j
+Synonym for
+.Fl y .
.It Fl L
(o and p modes)
All symbolic links will be followed.
@@ -163,6 +179,11 @@ With this option, the target of the link will be archived or copied instead.
(p mode only)
Create links from the target directory to the original files,
instead of copying.
+.It Fl lzma
+(o mode only)
+Compress the file with lzma-compatible compression before writing it.
+In input mode, this option is ignored; lzma compression is recognized
+automatically on input.
.It Fl m
(i and p modes)
Set file modification time on created files to match
@@ -176,6 +197,10 @@ By default,
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 no-preserve-owner
+(i mode only)
+Do not attempt to restore file ownership.
+This is the default when run by non-root users.
.It Fl O Ar file
Write archive to
.Ar file .
@@ -185,6 +210,10 @@ See above for description.
.It Fl p
Pass-through mode.
See above for description.
+.It Fl preserve-owner
+(i mode only)
+Restore file ownership.
+This is the default when run by the root user.
.It Fl -quiet
Suppress unnecessary messages.
.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc
@@ -266,7 +295,7 @@ for more information.
.Sh EXAMPLES
The
.Nm
-command is traditionally used to copy file hierarchies in conjunction
+command is traditionally used to copy file heirarchies in conjunction
with the
.Xr find 1
command.
diff --git a/usr.bin/cpio/cmdline.c b/usr.bin/cpio/cmdline.c
index b6a56be..ca50ed2 100644
--- a/usr.bin/cpio/cmdline.c
+++ b/usr.bin/cpio/cmdline.c
@@ -46,11 +46,12 @@ __FBSDID("$FreeBSD$");
#endif
#include "cpio.h"
+#include "err.h"
/*
* Short options for cpio. Please keep this sorted.
*/
-static const char *short_options = "0AaBC:F:O:cdE:f:H:hijLlmnopR:rtuvVW:yZz";
+static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuvW:yZz";
/*
* Long options for cpio. Please keep this sorted.
@@ -61,7 +62,6 @@ static const struct option {
int equivalent; /* Equivalent short option. */
} cpio_longopts[] = {
{ "create", 0, 'o' },
- { "dot", 0, 'V' },
{ "extract", 0, 'i' },
{ "file", 1, 'F' },
{ "format", 1, 'H' },
@@ -69,6 +69,7 @@ static const struct option {
{ "insecure", 0, OPTION_INSECURE },
{ "link", 0, 'l' },
{ "list", 0, 't' },
+ { "lzma", 0, OPTION_LZMA },
{ "make-directories", 0, 'd' },
{ "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER },
{ "null", 0, '0' },
@@ -76,10 +77,12 @@ static const struct option {
{ "owner", 1, 'R' },
{ "pass-through", 0, 'p' },
{ "preserve-modification-time", 0, 'm' },
+ { "preserve-owner", 0, OPTION_PRESERVE_OWNER },
{ "quiet", 0, OPTION_QUIET },
{ "unconditional", 0, 'u' },
{ "verbose", 0, 'v' },
{ "version", 0, OPTION_VERSION },
+ { "xz", 0, 'J' },
{ NULL, 0, 0 }
};
@@ -172,7 +175,7 @@ cpio_getopt(struct cpio *cpio)
/* Otherwise, pick up the next word. */
opt_word = *cpio->argv;
if (opt_word == NULL) {
- cpio_warnc(0,
+ warnc(0,
"Option -%c requires an argument",
opt);
return ('?');
@@ -223,13 +226,13 @@ cpio_getopt(struct cpio *cpio)
/* Fail if there wasn't a unique match. */
if (match == NULL) {
- cpio_warnc(0,
+ warnc(0,
"Option %s%s is not supported",
long_prefix, opt_word);
return ('?');
}
if (match2 != NULL) {
- cpio_warnc(0,
+ warnc(0,
"Ambiguous option %s%s (matches --%s and --%s)",
long_prefix, opt_word, match->name, match2->name);
return ('?');
@@ -241,7 +244,7 @@ cpio_getopt(struct cpio *cpio)
if (cpio->optarg == NULL) {
cpio->optarg = *cpio->argv;
if (cpio->optarg == NULL) {
- cpio_warnc(0,
+ warnc(0,
"Option %s%s requires an argument",
long_prefix, match->name);
return ('?');
@@ -252,7 +255,7 @@ cpio_getopt(struct cpio *cpio)
} else {
/* Argument forbidden: fail if there is one. */
if (cpio->optarg != NULL) {
- cpio_warnc(0,
+ warnc(0,
"Option %s%s does not allow an argument",
long_prefix, match->name);
return ('?');
@@ -283,17 +286,20 @@ cpio_getopt(struct cpio *cpio)
*
* Sets uid/gid return as appropriate, -1 indicates uid/gid not specified.
*
+ * Returns NULL if no error, otherwise returns error string for display.
+ *
*/
-int
+const char *
owner_parse(const char *spec, int *uid, int *gid)
{
+ static char errbuff[128];
const char *u, *ue, *g;
*uid = -1;
*gid = -1;
if (spec[0] == '\0')
- return (1);
+ return ("Invalid empty user/group spec");
/*
* Split spec into [user][:.][group]
@@ -321,10 +327,8 @@ owner_parse(const char *spec, int *uid, int *gid)
struct passwd *pwent;
user = (char *)malloc(ue - u + 1);
- if (user == NULL) {
- cpio_warnc(errno, "Couldn't allocate memory");
- return (1);
- }
+ if (user == NULL)
+ return ("Couldn't allocate memory");
memcpy(user, u, ue - u);
user[ue - u] = '\0';
if ((pwent = getpwnam(user)) != NULL) {
@@ -336,9 +340,10 @@ owner_parse(const char *spec, int *uid, int *gid)
errno = 0;
*uid = strtoul(user, &end, 10);
if (errno || *end != '\0') {
- cpio_warnc(errno,
+ snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup user ``%s''", user);
- return (1);
+ errbuff[sizeof(errbuff) - 1] = '\0';
+ return (errbuff);
}
}
free(user);
@@ -353,11 +358,12 @@ owner_parse(const char *spec, int *uid, int *gid)
errno = 0;
*gid = strtoul(g, &end, 10);
if (errno || *end != '\0') {
- cpio_warnc(errno,
+ snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup group ``%s''", g);
- return (1);
+ errbuff[sizeof(errbuff) - 1] = '\0';
+ return (errbuff);
}
}
}
- return (0);
+ return (NULL);
}
diff --git a/usr.bin/cpio/config_freebsd.h b/usr.bin/cpio/config_freebsd.h
index df376ff..ec4e441 100644
--- a/usr.bin/cpio/config_freebsd.h
+++ b/usr.bin/cpio/config_freebsd.h
@@ -25,83 +25,32 @@
* $FreeBSD$
*/
-/* A default configuration for FreeBSD, used if there is no config.h. */
+/* A hand-tooled configuration for FreeBSD. */
#include <sys/param.h> /* __FreeBSD_version */
-#if __FreeBSD__ > 4
-#define HAVE_ACL_GET_PERM 0
-#define HAVE_ACL_GET_PERM_NP 1
-#define HAVE_ACL_PERMSET_T 1
-#define HAVE_ACL_USER 1
-#endif
-#undef HAVE_ATTR_XATTR_H
-#define HAVE_BZLIB_H 1
-#define HAVE_CHFLAGS 1
-#define HAVE_DECL_OPTARG 1
-#define HAVE_DECL_OPTIND 1
-#define HAVE_DIRENT_D_NAMLEN 1
#define HAVE_DIRENT_H 1
-#define HAVE_D_MD_ORDER 1
#define HAVE_ERRNO_H 1
-#undef HAVE_EXT2FS_EXT2_FS_H
-#define HAVE_FCHDIR 1
#define HAVE_FCNTL_H 1
-#define HAVE_FNMATCH 1
-#define HAVE_FNMATCH_H 1
-#define HAVE_FNM_LEADING_DIR 1
-#define HAVE_FTRUNCATE 1
#define HAVE_FUTIMES 1
-#undef HAVE_GETXATTR
#define HAVE_GRP_H 1
-#define HAVE_INTTYPES_H 1
-#define HAVE_LANGINFO_H 1
-#undef HAVE_LGETXATTR
-#undef HAVE_LIBACL
#define HAVE_LIBARCHIVE 1
-#define HAVE_LIBBZ2 1
-#define HAVE_LIBZ 1
-#define HAVE_LIMITS_H 1
-#undef HAVE_LINUX_EXT2_FS_H
-#undef HAVE_LINUX_FS_H
-#undef HAVE_LISTXATTR
-#undef HAVE_LLISTXATTR
-#define HAVE_LOCALE_H 1
+#define HAVE_LINK 1
+#define HAVE_LSTAT 1
#define HAVE_LUTIMES 1
-#define HAVE_MALLOC 1
-#define HAVE_MEMMOVE 1
-#define HAVE_MEMORY_H 1
-#define HAVE_MEMSET 1
-#if __FreeBSD_version >= 450002 /* nl_langinfo introduced */
-#define HAVE_NL_LANGINFO 1
-#endif
-#define HAVE_PATHS_H 1
#define HAVE_PWD_H 1
-#define HAVE_SETLOCALE 1
+#define HAVE_READLINK 1
#define HAVE_STDARG_H 1
-#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
-#define HAVE_STRCHR 1
-#define HAVE_STRDUP 1
-#define HAVE_STRERROR 1
-#define HAVE_STRFTIME 1
-#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
-#define HAVE_STRRCHR 1
-#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
-#define HAVE_SYS_ACL_H 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYMLINK 1
+#define HAVE_SYS_CDEFS_H 1
#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
#define HAVE_TIME_H 1
-#define HAVE_SYS_TYPES_H 1
#define HAVE_UINTMAX_T 1
#define HAVE_UNISTD_H 1
#define HAVE_UNSIGNED_LONG_LONG 1
+#define HAVE_UTIME_H 1
#define HAVE_UTIMES 1
-#define HAVE_VPRINTF 1
-#define HAVE_ZLIB_H 1
-#undef MAJOR_IN_MKDEV
-#define STDC_HEADERS 1
diff --git a/usr.bin/cpio/cpio.c b/usr.bin/cpio/cpio.c
index 53195aa..9b76fe8 100644
--- a/usr.bin/cpio/cpio.c
+++ b/usr.bin/cpio/cpio.c
@@ -56,6 +56,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -74,11 +77,17 @@ __FBSDID("$FreeBSD$");
#endif
#include "cpio.h"
+#include "err.h"
+#include "line_reader.h"
#include "matching.h"
/* Fixed size of uname/gname caches. */
#define name_cache_size 101
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
struct name_cache {
int probes;
int hits;
@@ -89,7 +98,8 @@ struct name_cache {
} cache[name_cache_size];
};
-static int copy_data(struct archive *, struct archive *);
+static int extract_data(struct archive *, struct archive *);
+const char * cpio_i64toa(int64_t);
static const char *cpio_rename(const char *name);
static int entry_to_archive(struct cpio *, struct archive_entry *);
static int file_to_archive(struct cpio *, const char *);
@@ -117,6 +127,7 @@ main(int argc, char *argv[])
static char buff[16384];
struct cpio _cpio; /* Allocated on stack. */
struct cpio *cpio;
+ const char *errmsg;
int uid, gid;
int opt;
@@ -124,33 +135,26 @@ 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. */
+ /* Need progname before calling warnc. */
if (*argv == NULL)
- cpio_progname = "bsdcpio";
+ progname = "bsdcpio";
else {
#if defined(_WIN32) && !defined(__CYGWIN__)
- cpio_progname = strrchr(*argv, '\\');
+ progname = strrchr(*argv, '\\');
#else
- cpio_progname = strrchr(*argv, '/');
+ progname = strrchr(*argv, '/');
#endif
- if (cpio_progname != NULL)
- cpio_progname++;
+ if (progname != NULL)
+ progname++;
else
- cpio_progname = *argv;
+ progname = *argv;
}
cpio->uid_override = -1;
cpio->gid_override = -1;
cpio->argv = argv;
cpio->argc = argc;
- cpio->line_separator = '\n';
cpio->mode = '\0';
cpio->verbose = 0;
cpio->compress = '\0';
@@ -161,19 +165,17 @@ 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 !defined(_WIN32) && !defined(__CYGWIN__)
if (geteuid() == 0)
-#endif
cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
+#endif
cpio->bytes_per_block = 512;
cpio->filename = NULL;
while ((opt = cpio_getopt(cpio)) != -1) {
switch (opt) {
case '0': /* GNU convention: --null, -0 */
- cpio->line_separator = '\0';
+ cpio->option_null = 1;
break;
case 'A': /* NetBSD/OpenBSD */
cpio->option_append = 1;
@@ -187,7 +189,7 @@ main(int argc, char *argv[])
case 'C': /* NetBSD/OpenBSD */
cpio->bytes_per_block = atoi(cpio->optarg);
if (cpio->bytes_per_block <= 0)
- cpio_errc(1, 0, "Invalid blocksize %s", cpio->optarg);
+ errc(1, 0, "Invalid blocksize %s", cpio->optarg);
break;
case 'c': /* POSIX 1997 */
cpio->format = "odc";
@@ -196,13 +198,14 @@ main(int argc, char *argv[])
cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR;
break;
case 'E': /* NetBSD/OpenBSD */
- include_from_file(cpio, cpio->optarg);
+ include_from_file(&cpio->matching,
+ cpio->optarg, cpio->option_null);
break;
case 'F': /* NetBSD/OpenBSD/GNU cpio */
cpio->filename = cpio->optarg;
break;
case 'f': /* POSIX 1997 */
- exclude(cpio, cpio->optarg);
+ exclude(&cpio->matching, cpio->optarg);
break;
case 'H': /* GNU cpio (also --format) */
cpio->format = cpio->optarg;
@@ -215,10 +218,16 @@ main(int argc, char *argv[])
break;
case 'i': /* POSIX 1997 */
if (cpio->mode != '\0')
- cpio_errc(1, 0,
+ errc(1, 0,
"Cannot use both -i and -%c", cpio->mode);
cpio->mode = opt;
break;
+ case 'J': /* GNU tar, others */
+ cpio->compress = opt;
+ break;
+ case 'j': /* GNU tar, others */
+ cpio->compress = opt;
+ break;
case OPTION_INSECURE:
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS;
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
@@ -229,6 +238,9 @@ main(int argc, char *argv[])
case 'l': /* POSIX 1997 */
cpio->option_link = 1;
break;
+ case OPTION_LZMA: /* GNU tar, others */
+ cpio->compress = opt;
+ break;
case 'm': /* POSIX 1997 */
cpio->extract_flags |= ARCHIVE_EXTRACT_TIME;
break;
@@ -243,23 +255,29 @@ main(int argc, char *argv[])
break;
case 'o': /* POSIX 1997 */
if (cpio->mode != '\0')
- cpio_errc(1, 0,
+ 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,
+ errc(1, 0,
"Cannot use both -p and -%c", cpio->mode);
cpio->mode = opt;
cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
break;
+ case OPTION_PRESERVE_OWNER:
+ cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
+ break;
case OPTION_QUIET: /* GNU cpio */
cpio->quiet = 1;
break;
case 'R': /* GNU cpio, also --owner */
- if (owner_parse(cpio->optarg, &uid, &gid))
+ errmsg = owner_parse(cpio->optarg, &uid, &gid);
+ if (errmsg) {
+ warnc(-1, "%s", errmsg);
usage();
+ }
if (uid != -1)
cpio->uid_override = uid;
if (gid != -1)
@@ -278,9 +296,6 @@ main(int argc, char *argv[])
case 'v': /* POSIX 1997 */
cpio->verbose++;
break;
- case 'V': /* GNU cpio */
- cpio->dot++;
- break;
case OPTION_VERSION: /* GNU convention */
version();
break;
@@ -293,23 +308,13 @@ 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();
@@ -324,19 +329,16 @@ main(int argc, char *argv[])
cpio->mode = 'i';
/* -t requires -i */
if (cpio->option_list && cpio->mode != 'i')
- cpio_errc(1, 0, "Option -t requires -i", cpio->mode);
+ errc(1, 0, "Option -t requires -i");
/* -n requires -it */
if (cpio->option_numeric_uid_gid && !cpio->option_list)
- cpio_errc(1, 0, "Option -n requires -it");
+ 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");
+ 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");
- /* -v overrides -V */
- if (cpio->dot && cpio->verbose)
- cpio->dot = 0;
+ errc(1, 0, "Option -l requires -p");
/* TODO: Flag other nonsensical combinations. */
switch (cpio->mode) {
@@ -350,7 +352,7 @@ main(int argc, char *argv[])
break;
case 'i':
while (*cpio->argv != NULL) {
- include(cpio, *cpio->argv);
+ include(&cpio->matching, *cpio->argv);
--cpio->argc;
++cpio->argv;
}
@@ -361,26 +363,26 @@ main(int argc, char *argv[])
break;
case 'p':
if (*cpio->argv == NULL || **cpio->argv == '\0')
- cpio_errc(1, 0,
+ errc(1, 0,
"-p mode requires a target directory");
mode_pass(cpio, *cpio->argv);
break;
default:
- cpio_errc(1, 0,
+ errc(1, 0,
"Must specify at least one of -i, -o, or -p");
}
free_cache(cpio->gname_cache);
free_cache(cpio->uname_cache);
- return (0);
+ return (cpio->return_value);
}
-void
+static void
usage(void)
{
const char *p;
- p = cpio_progname;
+ p = progname;
fprintf(stderr, "Brief Usage:\n");
fprintf(stderr, " List: %s -it < archive\n", p);
@@ -394,14 +396,9 @@ static const char *long_help_msg =
"First option must be a mode specifier:\n"
" -i Input -o Output -p Pass\n"
"Common Options:\n"
- " -v Verbose filenames -V one dot per file\n"
+ " -v Verbose\n"
"Create: %p -o [options] < [list of files] > [archive]\n"
-#ifdef HAVE_BZLIB_H
- " -y Compress archive with bzip2\n"
-#endif
-#ifdef HAVE_ZLIB_H
- " -z Compress archive with gzip\n"
-#endif
+ " -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n"
" --format {odc|newc|ustar} Select archive format\n"
"List: %p -it < [archive]\n"
"Extract: %p -i [options] < [archive]\n";
@@ -423,7 +420,7 @@ long_help(void)
const char *prog;
const char *p;
- prog = cpio_progname;
+ prog = progname;
fflush(stderr);
@@ -455,19 +452,33 @@ version(void)
static void
mode_out(struct cpio *cpio)
{
- unsigned long blocks;
struct archive_entry *entry, *spare;
struct line_reader *lr;
const char *p;
int r;
if (cpio->option_append)
- cpio_errc(1, 0, "Append mode not yet supported.");
+ errc(1, 0, "Append mode not yet supported.");
+
+ cpio->archive_read_disk = archive_read_disk_new();
+ if (cpio->archive_read_disk == NULL)
+ errc(1, 0, "Failed to allocate archive object");
+ if (cpio->option_follow_links)
+ archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
+ else
+ archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
+ archive_read_disk_set_standard_lookup(cpio->archive_read_disk);
+
cpio->archive = archive_write_new();
if (cpio->archive == NULL)
- cpio_errc(1, 0, "Failed to allocate archive object");
+ errc(1, 0, "Failed to allocate archive object");
switch (cpio->compress) {
-#ifndef SMALLER
+ case 'J':
+ r = archive_write_set_compression_xz(cpio->archive);
+ break;
+ case OPTION_LZMA:
+ r = archive_write_set_compression_lzma(cpio->archive);
+ break;
case 'j': case 'y':
r = archive_write_set_compression_bzip2(cpio->archive);
break;
@@ -477,41 +488,30 @@ mode_out(struct cpio *cpio)
case 'Z':
r = archive_write_set_compression_compress(cpio->archive);
break;
-#endif
- case '\0':
+ default:
r = archive_write_set_compression_none(cpio->archive);
break;
- default:
- cpio_errc(1, 0, "Unrecognized compression option");
}
- if (r != ARCHIVE_OK)
- cpio_errc(1, 0, "Unsupported compression format");
-#ifdef SMALLER
- if (strcmp(cpio->format, "cpio"))
- r = archive_write_set_format_cpio(cpio->archive);
- else if (strcmp(cpio->format, "odc"))
- r = archive_write_set_format_cpio(cpio->archive);
- else if (strcmp(cpio->format, "newc"))
- r = archive_write_set_format_cpio(cpio->archive);
- else if (strcmp(cpio->format, "ustar"))
- r = archive_write_set_format_cpio(cpio->archive);
-#else
+ if (r < ARCHIVE_WARN)
+ errc(1, 0, "Requested compression not available");
r = archive_write_set_format_by_name(cpio->archive, cpio->format);
-#endif
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(cpio->archive));
+ errc(1, 0, "%s", archive_error_string(cpio->archive));
archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block);
cpio->linkresolver = archive_entry_linkresolver_new();
archive_entry_linkresolver_set_strategy(cpio->linkresolver,
archive_format(cpio->archive));
+ /*
+ * The main loop: Copy each file into the output archive.
+ */
r = archive_write_open_file(cpio->archive, cpio->filename);
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(cpio->archive));
- lr = process_lines_init("-", cpio->line_separator);
- while ((p = process_lines_next(lr)) != NULL)
+ errc(1, 0, "%s", archive_error_string(cpio->archive));
+ lr = line_reader("-", cpio->option_null);
+ while ((p = line_reader_next(lr)) != NULL)
file_to_archive(cpio, p);
- process_lines_free(lr);
+ line_reader_free(lr);
/*
* The hardlink detection may have queued up a couple of entries
@@ -527,15 +527,14 @@ mode_out(struct cpio *cpio)
}
r = archive_write_close(cpio->archive);
- if (cpio->dot)
- fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(cpio->archive));
+ errc(1, 0, "%s", archive_error_string(cpio->archive));
if (!cpio->quiet) {
- blocks = (archive_position_uncompressed(cpio->archive) + 511)
- / 512;
- fprintf(stderr, "%lu %s\n", blocks,
+ int64_t blocks =
+ (archive_position_uncompressed(cpio->archive) + 511)
+ / 512;
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
archive_write_finish(cpio->archive);
@@ -549,57 +548,37 @@ mode_out(struct cpio *cpio)
static int
file_to_archive(struct cpio *cpio, const char *srcpath)
{
- struct stat st;
const char *destpath;
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)
- cpio_errc(1, 0, "Couldn't allocate entry");
+ errc(1, 0, "Couldn't allocate entry");
archive_entry_copy_sourcepath(entry, srcpath);
-
- /* Get stat information. */
- if (cpio->option_follow_links)
- r = stat(srcpath, &st);
- else
- r = lstat(srcpath, &st);
- if (r != 0) {
- cpio_warnc(errno, "Couldn't stat \"%s\"", srcpath);
- archive_entry_free(entry);
- return (0);
+ r = archive_read_disk_entry_from_file(cpio->archive_read_disk,
+ entry, -1, NULL);
+ if (r < ARCHIVE_FAILED)
+ errc(1, 0, "%s",
+ archive_error_string(cpio->archive_read_disk));
+ if (r < ARCHIVE_OK)
+ warnc(0, "%s",
+ archive_error_string(cpio->archive_read_disk));
+ if (r <= ARCHIVE_FAILED) {
+ cpio->return_value = 1;
+ return (r);
}
if (cpio->uid_override >= 0)
- st.st_uid = cpio->uid_override;
+ archive_entry_set_uid(entry, cpio->uid_override);
if (cpio->gid_override >= 0)
- st.st_gid = cpio->gid_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);
- if (lnklen < 0) {
- cpio_warnc(errno,
- "%s: Couldn't read symbolic link", srcpath);
- archive_entry_free(entry);
- return (0);
- }
- cpio->buff[lnklen] = 0;
- archive_entry_set_symlink(entry, cpio->buff);
- }
-#endif
+ archive_entry_set_gid(entry, cpio->gid_override);
/*
* Generate a destination path for this entry.
@@ -618,7 +597,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
free(cpio->pass_destpath);
cpio->pass_destpath = malloc(cpio->pass_destpath_alloc);
if (cpio->pass_destpath == NULL)
- cpio_errc(1, ENOMEM,
+ errc(1, ENOMEM,
"Can't allocate path buffer");
}
strcpy(cpio->pass_destpath, cpio->destdir);
@@ -639,18 +618,18 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
*/
spare = NULL;
if (cpio->linkresolver != NULL
- && !S_ISDIR(st.st_mode)) {
+ && archive_entry_filetype(entry) != AE_IFDIR) {
archive_entry_linkify(cpio->linkresolver, &entry, &spare);
}
if (entry != NULL) {
r = entry_to_archive(cpio, entry);
archive_entry_free(entry);
- }
- if (spare != NULL) {
- if (r == 0)
- r = entry_to_archive(cpio, spare);
- archive_entry_free(spare);
+ if (spare != NULL) {
+ if (r == 0)
+ r = entry_to_archive(cpio, spare);
+ archive_entry_free(spare);
+ }
}
return (r);
}
@@ -667,8 +646,6 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
/* Print out the destination name to the user. */
if (cpio->verbose)
fprintf(stderr,"%s", destpath);
- if (cpio->dot)
- fprintf(stderr, ".");
/*
* Option_link only makes sense in pass mode and for
@@ -686,7 +663,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
/* Save the original entry in case we need it later. */
t = archive_entry_clone(entry);
if (t == NULL)
- cpio_errc(1, ENOMEM, "Can't create link");
+ errc(1, ENOMEM, "Can't create link");
/* Note: link(2) doesn't create parent directories,
* so we use archive_write_header() instead as a
* convenience. */
@@ -696,15 +673,15 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
r = archive_write_header(cpio->archive, t);
archive_entry_free(t);
if (r != ARCHIVE_OK)
- cpio_warnc(archive_errno(cpio->archive),
- archive_error_string(cpio->archive));
+ warnc(archive_errno(cpio->archive),
+ "%s", archive_error_string(cpio->archive));
if (r == ARCHIVE_FATAL)
exit(1);
#ifdef EXDEV
if (r != ARCHIVE_OK && archive_errno(cpio->archive) == EXDEV) {
/* Cross-device link: Just fall through and use
* the original entry to copy the file over. */
- cpio_warnc(0, "Copying file instead");
+ warnc(0, "Copying file instead");
} else
#endif
return (0);
@@ -716,9 +693,9 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
*/
if (archive_entry_filetype(entry) == AE_IFREG) {
if (archive_entry_size(entry) > 0) {
- fd = open(srcpath, O_RDONLY);
+ fd = open(srcpath, O_RDONLY | O_BINARY);
if (fd < 0) {
- cpio_warnc(errno,
+ warnc(errno,
"%s: could not open file", srcpath);
goto cleanup;
}
@@ -730,7 +707,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
r = archive_write_header(cpio->archive, entry);
if (r != ARCHIVE_OK)
- cpio_warnc(archive_errno(cpio->archive),
+ warnc(archive_errno(cpio->archive),
"%s: %s",
srcpath,
archive_error_string(cpio->archive));
@@ -744,10 +721,10 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
r = archive_write_data(cpio->archive,
cpio->buff, bytes_read);
if (r < 0)
- cpio_errc(1, archive_errno(cpio->archive),
- archive_error_string(cpio->archive));
+ errc(1, archive_errno(cpio->archive),
+ "%s", archive_error_string(cpio->archive));
if (r < bytes_read) {
- cpio_warnc(0,
+ warnc(0,
"Truncated write; file may have grown while being archived.");
}
bytes_read = read(fd, cpio->buff, cpio->buff_size);
@@ -776,7 +753,7 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
(void)name; /* UNUSED */
if (!warned)
- cpio_warnc(0, "Can't restore access times on this platform");
+ warnc(0, "Can't restore access times on this platform");
warned = 1;
return (fd);
#else
@@ -795,7 +772,7 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
times[0].tv_sec = archive_entry_atime(entry);
times[0].tv_usec = archive_entry_atime_nsec(entry) / 1000;
-#ifdef HAVE_FUTIMES
+#if defined(HAVE_FUTIMES) && !defined(__CYGWIN__)
if (fd >= 0 && futimes(fd, times) == 0)
return (fd);
#endif
@@ -811,9 +788,10 @@ restore_time(struct cpio *cpio, struct archive_entry *entry,
#ifdef HAVE_LUTIMES
if (lutimes(name, times) != 0)
#else
- if (!S_ISLNK(archive_entry_mode(entry)) && utimes(name, times) != 0)
+ if ((AE_IFLNK != archive_entry_filetype(entry))
+ && utimes(name, times) != 0)
#endif
- cpio_warnc(errno, "Can't update time for %s", name);
+ warnc(errno, "Can't update time for %s", name);
#endif
return (fd);
}
@@ -826,38 +804,32 @@ mode_in(struct cpio *cpio)
struct archive_entry *entry;
struct archive *ext;
const char *destpath;
- unsigned long blocks;
int r;
ext = archive_write_disk_new();
if (ext == NULL)
- cpio_errc(1, 0, "Couldn't allocate restore object");
+ errc(1, 0, "Couldn't allocate restore object");
r = archive_write_disk_set_options(ext, cpio->extract_flags);
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(ext));
+ errc(1, 0, "%s", archive_error_string(ext));
a = archive_read_new();
if (a == NULL)
- cpio_errc(1, 0, "Couldn't allocate archive object");
-#ifdef SMALLER
- archive_read_support_format_cpio(a);
- archive_read_support_format_tar(a);
-#else
+ errc(1, 0, "Couldn't allocate archive object");
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
-#endif
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
- cpio_errc(1, archive_errno(a),
- archive_error_string(a));
+ errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK) {
- cpio_errc(1, archive_errno(a),
- archive_error_string(a));
+ errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
}
- if (excluded(cpio, archive_entry_pathname(entry)))
+ if (excluded(cpio->matching, archive_entry_pathname(entry)))
continue;
if (cpio->option_rename) {
destpath = cpio_rename(archive_entry_pathname(entry));
@@ -867,9 +839,7 @@ mode_in(struct cpio *cpio)
if (destpath == NULL)
continue;
if (cpio->verbose)
- fprintf(stderr, "%s\n", destpath);
- if (cpio->dot)
- fprintf(stderr, ".");
+ fprintf(stdout, "%s\n", destpath);
if (cpio->uid_override >= 0)
archive_entry_set_uid(entry, cpio->uid_override);
if (cpio->gid_override >= 0)
@@ -880,30 +850,34 @@ mode_in(struct cpio *cpio)
archive_entry_pathname(entry),
archive_error_string(ext));
} else if (archive_entry_size(entry) > 0) {
- r = copy_data(a, ext);
+ r = extract_data(a, ext);
+ if (r != ARCHIVE_OK)
+ cpio->return_value = 1;
}
}
r = archive_read_close(a);
- if (cpio->dot)
- fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(a));
+ errc(1, 0, "%s", archive_error_string(a));
r = archive_write_close(ext);
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(ext));
+ errc(1, 0, "%s", archive_error_string(ext));
if (!cpio->quiet) {
- blocks = (archive_position_uncompressed(a) + 511)
+ int64_t blocks = (archive_position_uncompressed(a) + 511)
/ 512;
- fprintf(stderr, "%lu %s\n", blocks,
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
archive_read_finish(a);
archive_write_finish(ext);
- exit(0);
+ exit(cpio->return_value);
}
+/*
+ * Exits if there's a fatal error. Returns ARCHIVE_OK
+ * if everything is kosher.
+ */
static int
-copy_data(struct archive *ar, struct archive *aw)
+extract_data(struct archive *ar, struct archive *aw)
{
int r;
size_t size;
@@ -915,14 +889,14 @@ copy_data(struct archive *ar, struct archive *aw)
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK) {
- cpio_warnc(archive_errno(ar),
+ warnc(archive_errno(ar),
"%s", archive_error_string(ar));
- return (r);
+ exit(1);
}
r = archive_write_data_block(aw, block, size, offset);
if (r != ARCHIVE_OK) {
- cpio_warnc(archive_errno(aw),
- archive_error_string(aw));
+ warnc(archive_errno(aw),
+ "%s", archive_error_string(aw));
return (r);
}
}
@@ -933,32 +907,26 @@ mode_list(struct cpio *cpio)
{
struct archive *a;
struct archive_entry *entry;
- unsigned long blocks;
int r;
a = archive_read_new();
if (a == NULL)
- cpio_errc(1, 0, "Couldn't allocate archive object");
-#ifdef SMALLER
- archive_read_support_format_cpio(a);
- archive_read_support_format_tar(a);
-#else
+ errc(1, 0, "Couldn't allocate archive object");
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
-#endif
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
- cpio_errc(1, archive_errno(a),
- archive_error_string(a));
+ errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK) {
- cpio_errc(1, archive_errno(a),
- archive_error_string(a));
+ errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
}
- if (excluded(cpio, archive_entry_pathname(entry)))
+ if (excluded(cpio->matching, archive_entry_pathname(entry)))
continue;
if (cpio->verbose)
list_item_verbose(cpio, entry);
@@ -967,11 +935,11 @@ mode_list(struct cpio *cpio)
}
r = archive_read_close(a);
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(a));
+ errc(1, 0, "%s", archive_error_string(a));
if (!cpio->quiet) {
- blocks = (archive_position_uncompressed(a) + 511)
+ int64_t blocks = (archive_position_uncompressed(a) + 511)
/ 512;
- fprintf(stderr, "%lu %s\n", blocks,
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
archive_read_finish(a);
@@ -994,23 +962,18 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
char uids[16], gids[16];
const char *uname, *gname;
FILE *out = stdout;
- const struct stat *st;
const char *fmt;
- time_t tim;
+ time_t mtime;
static time_t now;
- st = archive_entry_stat(entry);
-
if (!now)
time(&now);
if (cpio->option_numeric_uid_gid) {
/* Format numeric uid/gid for display. */
- snprintf(uids, sizeof(uids), "%jd",
- (intmax_t)archive_entry_uid(entry));
+ strcpy(uids, cpio_i64toa(archive_entry_uid(entry)));
uname = uids;
- snprintf(gids, sizeof(gids), "%jd",
- (intmax_t)archive_entry_gid(entry));
+ strcpy(gids, cpio_i64toa(archive_entry_gid(entry)));
gname = gids;
} else {
/* Use uname if it's present, else lookup name from uid. */
@@ -1024,30 +987,31 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
}
/* Print device number or file size. */
- if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+ if (archive_entry_filetype(entry) == AE_IFCHR
+ || archive_entry_filetype(entry) == AE_IFBLK) {
snprintf(size, sizeof(size), "%lu,%lu",
- (unsigned long)major(st->st_rdev),
- (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */
+ (unsigned long)archive_entry_rdevmajor(entry),
+ (unsigned long)archive_entry_rdevminor(entry));
} else {
- snprintf(size, sizeof(size), CPIO_FILESIZE_PRINTF,
- (CPIO_FILESIZE_TYPE)st->st_size);
+ strcpy(size, cpio_i64toa(archive_entry_size(entry)));
}
/* Format the time using 'ls -l' conventions. */
- tim = (time_t)st->st_mtime;
+ mtime = archive_entry_mtime(entry);
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Windows' strftime function does not support %e format. */
- if (abs(tim - now) > (365/2)*86400)
+ if (mtime - now > 365*86400/2
+ || mtime - now < -365*86400/2)
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)
+ if (abs(mtime - 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));
+ strftime(date, sizeof(date), fmt, localtime(&mtime));
fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
archive_entry_strmode(entry),
@@ -1066,7 +1030,6 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
static void
mode_pass(struct cpio *cpio, const char *destdir)
{
- unsigned long blocks;
struct line_reader *lr;
const char *p;
int r;
@@ -1079,28 +1042,37 @@ mode_pass(struct cpio *cpio, const char *destdir)
cpio->archive = archive_write_disk_new();
if (cpio->archive == NULL)
- cpio_errc(1, 0, "Failed to allocate archive object");
+ errc(1, 0, "Failed to allocate archive object");
r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags);
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(cpio->archive));
+ errc(1, 0, "%s", archive_error_string(cpio->archive));
cpio->linkresolver = archive_entry_linkresolver_new();
archive_write_disk_set_standard_lookup(cpio->archive);
- lr = process_lines_init("-", cpio->line_separator);
- while ((p = process_lines_next(lr)) != NULL)
+
+ cpio->archive_read_disk = archive_read_disk_new();
+ if (cpio->archive_read_disk == NULL)
+ errc(1, 0, "Failed to allocate archive object");
+ if (cpio->option_follow_links)
+ archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
+ else
+ archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
+ archive_read_disk_set_standard_lookup(cpio->archive_read_disk);
+
+ lr = line_reader("-", cpio->option_null);
+ while ((p = line_reader_next(lr)) != NULL)
file_to_archive(cpio, p);
- process_lines_free(lr);
+ line_reader_free(lr);
archive_entry_linkresolver_free(cpio->linkresolver);
r = archive_write_close(cpio->archive);
- if (cpio->dot)
- fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
- cpio_errc(1, 0, archive_error_string(cpio->archive));
+ errc(1, 0, "%s", archive_error_string(cpio->archive));
if (!cpio->quiet) {
- blocks = (archive_position_uncompressed(cpio->archive) + 511)
- / 512;
- fprintf(stderr, "%lu %s\n", blocks,
+ int64_t blocks =
+ (archive_position_uncompressed(cpio->archive) + 511)
+ / 512;
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
@@ -1150,130 +1122,6 @@ cpio_rename(const char *name)
return (ret);
}
-
-/*
- * Read lines from file and do something with each one. If option_null
- * is set, lines are terminated with zero bytes; otherwise, they're
- * terminated with newlines.
- *
- * This uses a self-sizing buffer to handle arbitrarily-long lines.
- */
-struct line_reader {
- FILE *f;
- char *buff, *buff_end, *line_start, *line_end, *p;
- char *pathname;
- size_t buff_length;
- int separator;
- int ret;
-};
-
-struct line_reader *
-process_lines_init(const char *pathname, char separator)
-{
- struct line_reader *lr;
-
- lr = calloc(1, sizeof(*lr));
- if (lr == NULL)
- cpio_errc(1, ENOMEM, "Can't open %s", pathname);
-
- lr->separator = separator;
- lr->pathname = strdup(pathname);
-
- if (strcmp(pathname, "-") == 0)
- lr->f = stdin;
- else
- lr->f = fopen(pathname, "r");
- if (lr->f == NULL)
- cpio_errc(1, errno, "Couldn't open %s", pathname);
- lr->buff_length = 8192;
- lr->buff = malloc(lr->buff_length);
- if (lr->buff == NULL)
- cpio_errc(1, ENOMEM, "Can't read %s", pathname);
- lr->line_start = lr->line_end = lr->buff_end = lr->buff;
-
- return (lr);
-}
-
-const char *
-process_lines_next(struct line_reader *lr)
-{
- size_t bytes_wanted, bytes_read, new_buff_size;
- char *line_start, *p;
-
- for (;;) {
- /* If there's a line in the buffer, return it immediately. */
- while (lr->line_end < lr->buff_end) {
- if (*lr->line_end == lr->separator) {
- *lr->line_end = '\0';
- line_start = lr->line_start;
- lr->line_start = lr->line_end + 1;
- lr->line_end = lr->line_start;
- return (line_start);
- } else
- lr->line_end++;
- }
-
- /* If we're at end-of-file, process the final data. */
- if (lr->f == NULL) {
- /* If there's more text, return one last line. */
- if (lr->line_end > lr->line_start) {
- *lr->line_end = '\0';
- line_start = lr->line_start;
- lr->line_start = lr->line_end + 1;
- lr->line_end = lr->line_start;
- return (line_start);
- }
- /* Otherwise, we're done. */
- return (NULL);
- }
-
- /* Buffer only has part of a line. */
- if (lr->line_start > lr->buff) {
- /* Move a leftover fractional line to the beginning. */
- memmove(lr->buff, lr->line_start,
- lr->buff_end - lr->line_start);
- lr->buff_end -= lr->line_start - lr->buff;
- lr->line_end -= lr->line_start - lr->buff;
- lr->line_start = lr->buff;
- } else {
- /* Line is too big; enlarge the buffer. */
- new_buff_size = lr->buff_length * 2;
- if (new_buff_size <= lr->buff_length)
- cpio_errc(1, ENOMEM,
- "Line too long in %s", lr->pathname);
- lr->buff_length = new_buff_size;
- p = realloc(lr->buff, new_buff_size);
- if (p == NULL)
- cpio_errc(1, ENOMEM,
- "Line too long in %s", lr->pathname);
- lr->buff_end = p + (lr->buff_end - lr->buff);
- lr->line_end = p + (lr->line_end - lr->buff);
- lr->line_start = lr->buff = p;
- }
-
- /* Get some more data into the buffer. */
- bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
- bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
- lr->buff_end += bytes_read;
-
- if (ferror(lr->f))
- cpio_errc(1, errno, "Can't read %s", lr->pathname);
- if (feof(lr->f)) {
- if (lr->f != stdin)
- fclose(lr->f);
- lr->f = NULL;
- }
- }
-}
-
-void
-process_lines_free(struct line_reader *lr)
-{
- free(lr->buff);
- free(lr->pathname);
- free(lr);
-}
-
static void
free_cache(struct name_cache *cache)
{
@@ -1302,7 +1150,7 @@ lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
if (*name_cache_variable == NULL) {
*name_cache_variable = malloc(sizeof(struct name_cache));
if (*name_cache_variable == NULL)
- cpio_errc(1, ENOMEM, "No more memory");
+ errc(1, ENOMEM, "No more memory");
memset(*name_cache_variable, 0, sizeof(struct name_cache));
(*name_cache_variable)->size = name_cache_size;
}
@@ -1358,8 +1206,8 @@ lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
pwent = getpwuid((uid_t)id);
if (pwent == NULL) {
*name = NULL;
- if (errno != 0)
- cpio_warnc(errno, "getpwuid(%d) failed", id);
+ if (errno != 0 && errno != ENOENT)
+ warnc(errno, "getpwuid(%d) failed", id);
return (errno);
}
@@ -1386,10 +1234,34 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
if (grent == NULL) {
*name = NULL;
if (errno != 0)
- cpio_warnc(errno, "getgrgid(%d) failed", id);
+ warnc(errno, "getgrgid(%d) failed", id);
return (errno);
}
*name = grent->gr_name;
return (0);
}
+
+/*
+ * It would be nice to just use printf() for formatting large numbers,
+ * but the compatibility problems are a big headache. Hence the
+ * following simple utility function.
+ */
+const char *
+cpio_i64toa(int64_t n0)
+{
+ // 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
+ // We also need 1 byte for '-' and 1 for '\0'.
+ static char buff[22];
+ int64_t n = n0 < 0 ? -n0 : n0;
+ char *p = buff + sizeof(buff);
+
+ *--p = '\0';
+ do {
+ *--p = '0' + (int)(n % 10);
+ n /= 10;
+ } while (n > 0);
+ if (n0 < 0)
+ *--p = '-';
+ return p;
+}
diff --git a/usr.bin/cpio/cpio.h b/usr.bin/cpio/cpio.h
index 8c18737..36dab55 100644
--- a/usr.bin/cpio/cpio.h
+++ b/usr.bin/cpio/cpio.h
@@ -31,7 +31,7 @@
#include "cpio_platform.h"
#include <stdio.h>
-#define DEFAULT_BYTES_PER_BLOCK (20*512)
+#include "matching.h"
/*
* The internal state for the "cpio" program.
@@ -52,17 +52,16 @@ struct cpio {
const char *format; /* -H format */
int bytes_per_block; /* -b block_size */
int verbose; /* -v */
- int dot; /* -V */
int quiet; /* --quiet */
int extract_flags; /* Flags for extract operation */
char symlink_mode; /* H or L, per BSD conventions */
const char *compress_program;
- char line_separator; /* --null ? '\0' : '\n' */
int option_append; /* -A, only relevant for -o */
int option_atime_restore; /* -a */
int option_follow_links; /* -L */
int option_link; /* -l */
int option_list; /* -t */
+ char option_null; /* --null */
int option_numeric_uid_gid; /* -n */
int option_rename; /* -r */
char *destdir;
@@ -77,6 +76,7 @@ struct cpio {
/* Miscellaneous state information */
struct archive *archive;
+ struct archive *archive_read_disk;
int argc;
char **argv;
int return_value; /* Value returned by main() */
@@ -91,30 +91,19 @@ struct cpio {
size_t buff_size;
};
-/* Name of this program; used in error reporting, initialized in main(). */
-const char *cpio_progname;
-
-void cpio_errc(int _eval, int _code, const char *fmt, ...) __LA_DEAD;
-void cpio_warnc(int _code, const char *fmt, ...);
-
-int owner_parse(const char *, int *, int *);
+const char *owner_parse(const char *, int *, int *);
/* Fake short equivalents for long options that otherwise lack them. */
enum {
OPTION_INSECURE = 1,
+ OPTION_LZMA,
OPTION_NO_PRESERVE_OWNER,
+ OPTION_PRESERVE_OWNER,
OPTION_QUIET,
OPTION_VERSION
};
-struct line_reader;
-
-struct line_reader *process_lines_init(const char *, char separator);
-const char *process_lines_next(struct line_reader *);
-void process_lines_free(struct line_reader *);
-
int cpio_getopt(struct cpio *cpio);
-int include_from_file(struct cpio *, const char *);
#endif
diff --git a/usr.bin/cpio/cpio_platform.h b/usr.bin/cpio/cpio_platform.h
index 037376a..3043828 100644
--- a/usr.bin/cpio/cpio_platform.h
+++ b/usr.bin/cpio/cpio_platform.h
@@ -37,19 +37,18 @@
#if defined(PLATFORM_CONFIG_H)
/* Use hand-built config.h in environments that need it. */
#include PLATFORM_CONFIG_H
-#elif defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build 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.
-#endif /* !HAVE_CONFIG_H */
+/* Read config.h or die trying. */
+#include "config.h"
+#endif
-/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
-#ifdef __FreeBSD__
-#include <sys/cdefs.h> /* For __FBSDID */
-#elif !defined(__FBSDID)
-/* Just leaving this macro replacement empty leads to a dangling semicolon. */
+/* Get a real definition for __FBSDID if we can */
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+/* If not, define it so as to avoid dangling semicolons. */
+#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
@@ -63,24 +62,6 @@
#include "archive_entry.h"
#endif
-/*
- * We need to be able to display a filesize using printf(). The type
- * and format string here must be compatible with one another and
- * large enough for any file.
- */
-#if HAVE_UINTMAX_T
-#define CPIO_FILESIZE_TYPE uintmax_t
-#define CPIO_FILESIZE_PRINTF "%ju"
-#else
-#if HAVE_UNSIGNED_LONG_LONG
-#define CPIO_FILESIZE_TYPE unsigned long long
-#define CPIO_FILESIZE_PRINTF "%llu"
-#else
-#define CPIO_FILESIZE_TYPE unsigned long
-#define CPIO_FILESIZE_PRINTF "%lu"
-#endif
-#endif
-
/* How to mark functions that don't return. */
#if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
@@ -89,9 +70,7 @@
#define __LA_DEAD
#endif
-#if defined(__CYGWIN__)
-#include "cpio_cygwin.h"
-#elif defined(_WIN32) /* && !__CYGWIN__ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include "cpio_windows.h"
#endif
diff --git a/usr.bin/cpio/err.c b/usr.bin/cpio/err.c
index ad9c0e1..c74e097 100644
--- a/usr.bin/cpio/err.c
+++ b/usr.bin/cpio/err.c
@@ -24,7 +24,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
#include "cpio_platform.h"
__FBSDID("$FreeBSD$");
@@ -39,12 +38,14 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#endif
-#include "cpio.h"
+#include "err.h"
+
+const char *progname;
static void
-cpio_vwarnc(int code, const char *fmt, va_list ap)
+vwarnc(int code, const char *fmt, va_list ap)
{
- fprintf(stderr, "%s: ", cpio_progname);
+ fprintf(stderr, "%s: ", progname);
vfprintf(stderr, fmt, ap);
if (code != 0)
fprintf(stderr, ": %s", strerror(code));
@@ -52,22 +53,22 @@ cpio_vwarnc(int code, const char *fmt, va_list ap)
}
void
-cpio_warnc(int code, const char *fmt, ...)
+warnc(int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- cpio_vwarnc(code, fmt, ap);
+ vwarnc(code, fmt, ap);
va_end(ap);
}
void
-cpio_errc(int eval, int code, const char *fmt, ...)
+errc(int eval, int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- cpio_vwarnc(code, fmt, ap);
+ vwarnc(code, fmt, ap);
va_end(ap);
exit(eval);
}
diff --git a/usr.bin/cpio/err.h b/usr.bin/cpio/err.h
new file mode 100644
index 0000000..fe96c70
--- /dev/null
+++ b/usr.bin/cpio/err.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2009 Joerg Sonnenberger
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef LAFE_ERR_H
+#define LAFE_ERR_H
+
+#if defined(__GNUC__) && (__GNUC__ > 2 || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
+#define __LA_DEAD __attribute__((__noreturn__))
+#else
+#define __LA_DEAD
+#endif
+
+extern const char *progname;
+
+void warnc(int code, const char *fmt, ...);
+void errc(int eval, int code, const char *fmt, ...) __LA_DEAD;
+
+#endif
diff --git a/usr.bin/cpio/line_reader.c b/usr.bin/cpio/line_reader.c
new file mode 100644
index 0000000..8461941
--- /dev/null
+++ b/usr.bin/cpio/line_reader.c
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2008 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cpio_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "err.h"
+#include "line_reader.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
+#define strdup _strdup
+#endif
+
+/*
+ * Read lines from file and do something with each one. If option_null
+ * is set, lines are terminated with zero bytes; otherwise, they're
+ * terminated with newlines.
+ *
+ * This uses a self-sizing buffer to handle arbitrarily-long lines.
+ */
+struct line_reader {
+ FILE *f;
+ char *buff, *buff_end, *line_start, *line_end, *p;
+ char *pathname;
+ size_t buff_length;
+ int nullSeparator; /* Lines separated by null, not CR/CRLF/etc. */
+ int ret;
+};
+
+struct line_reader *
+line_reader(const char *pathname, int nullSeparator)
+{
+ struct line_reader *lr;
+
+ lr = calloc(1, sizeof(*lr));
+ if (lr == NULL)
+ errc(1, ENOMEM, "Can't open %s", pathname);
+
+ lr->nullSeparator = nullSeparator;
+ lr->pathname = strdup(pathname);
+
+ if (strcmp(pathname, "-") == 0)
+ lr->f = stdin;
+ else
+ lr->f = fopen(pathname, "r");
+ if (lr->f == NULL)
+ errc(1, errno, "Couldn't open %s", pathname);
+ lr->buff_length = 8192;
+ lr->buff = malloc(lr->buff_length);
+ if (lr->buff == NULL)
+ errc(1, ENOMEM, "Can't read %s", pathname);
+ lr->line_start = lr->line_end = lr->buff_end = lr->buff;
+
+ return (lr);
+}
+
+const char *
+line_reader_next(struct line_reader *lr)
+{
+ size_t bytes_wanted, bytes_read, new_buff_size;
+ char *line_start, *p;
+
+ for (;;) {
+ /* If there's a line in the buffer, return it immediately. */
+ while (lr->line_end < lr->buff_end) {
+ if (lr->nullSeparator) {
+ if (*lr->line_end == '\0') {
+ line_start = lr->line_start;
+ lr->line_start = lr->line_end + 1;
+ lr->line_end = lr->line_start;
+ return (line_start);
+ }
+ } else if (*lr->line_end == '\x0a' || *lr->line_end == '\x0d') {
+ *lr->line_end = '\0';
+ line_start = lr->line_start;
+ lr->line_start = lr->line_end + 1;
+ lr->line_end = lr->line_start;
+ if (line_start[0] != '\0')
+ return (line_start);
+ }
+ lr->line_end++;
+ }
+
+ /* If we're at end-of-file, process the final data. */
+ if (lr->f == NULL) {
+ /* If there's more text, return one last line. */
+ if (lr->line_end > lr->line_start) {
+ *lr->line_end = '\0';
+ line_start = lr->line_start;
+ lr->line_start = lr->line_end + 1;
+ lr->line_end = lr->line_start;
+ return (line_start);
+ }
+ /* Otherwise, we're done. */
+ return (NULL);
+ }
+
+ /* Buffer only has part of a line. */
+ if (lr->line_start > lr->buff) {
+ /* Move a leftover fractional line to the beginning. */
+ memmove(lr->buff, lr->line_start,
+ lr->buff_end - lr->line_start);
+ lr->buff_end -= lr->line_start - lr->buff;
+ lr->line_end -= lr->line_start - lr->buff;
+ lr->line_start = lr->buff;
+ } else {
+ /* Line is too big; enlarge the buffer. */
+ new_buff_size = lr->buff_length * 2;
+ if (new_buff_size <= lr->buff_length)
+ errc(1, ENOMEM,
+ "Line too long in %s", lr->pathname);
+ lr->buff_length = new_buff_size;
+ p = realloc(lr->buff, new_buff_size);
+ if (p == NULL)
+ errc(1, ENOMEM,
+ "Line too long in %s", lr->pathname);
+ lr->buff_end = p + (lr->buff_end - lr->buff);
+ lr->line_end = p + (lr->line_end - lr->buff);
+ lr->line_start = lr->buff = p;
+ }
+
+ /* Get some more data into the buffer. */
+ bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
+ bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
+ lr->buff_end += bytes_read;
+
+ if (ferror(lr->f))
+ errc(1, errno, "Can't read %s", lr->pathname);
+ if (feof(lr->f)) {
+ if (lr->f != stdin)
+ fclose(lr->f);
+ lr->f = NULL;
+ }
+ }
+}
+
+void
+line_reader_free(struct line_reader *lr)
+{
+ free(lr->buff);
+ free(lr->pathname);
+ free(lr);
+}
diff --git a/usr.bin/cpio/line_reader.h b/usr.bin/cpio/line_reader.h
new file mode 100644
index 0000000..4f5dd6a
--- /dev/null
+++ b/usr.bin/cpio/line_reader.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2009 Joerg Sonnenberger
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef LAFE_LINE_READER_H
+#define LAFE_LINE_READER_H
+
+struct line_reader;
+
+struct line_reader *line_reader(const char *, int nullSeparator);
+const char *line_reader_next(struct line_reader *);
+void line_reader_free(struct line_reader *);
+
+#endif
diff --git a/usr.bin/cpio/matching.c b/usr.bin/cpio/matching.c
index 8d1798f..0fd2b6a 100644
--- a/usr.bin/cpio/matching.c
+++ b/usr.bin/cpio/matching.c
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#endif
+#include "err.h"
+#include "line_reader.h"
#include "matching.h"
#include "pathmatch.h"
@@ -54,7 +56,7 @@ struct matching {
};
static void add_pattern(struct match **list, const char *pattern);
-static void initialize_matching(struct cpio *);
+static void initialize_matching(struct matching **);
static int match_exclusion(struct match *, const char *pathname);
static int match_inclusion(struct match *, const char *pathname);
@@ -70,52 +72,58 @@ static int match_inclusion(struct match *, const char *pathname);
*/
int
-exclude(struct cpio *cpio, const char *pattern)
+exclude(struct matching **matching, const char *pattern)
{
- struct matching *matching;
- if (cpio->matching == NULL)
- initialize_matching(cpio);
- matching = cpio->matching;
- add_pattern(&(matching->exclusions), pattern);
- matching->exclusions_count++;
+ if (*matching == NULL)
+ initialize_matching(matching);
+ add_pattern(&((*matching)->exclusions), pattern);
+ (*matching)->exclusions_count++;
return (0);
}
-#if 0
int
-exclude_from_file(struct cpio *cpio, const char *pathname)
+exclude_from_file(struct matching **matching, const char *pathname)
{
- return (process_lines(cpio, pathname, &exclude));
+ struct line_reader *lr;
+ const char *p;
+ int ret = 0;
+
+ lr = line_reader(pathname, 0);
+ while ((p = line_reader_next(lr)) != NULL) {
+ if (exclude(matching, p) != 0)
+ ret = -1;
+ }
+ line_reader_free(lr);
+ return (ret);
}
-#endif
int
-include(struct cpio *cpio, const char *pattern)
+include(struct matching **matching, const char *pattern)
{
- struct matching *matching;
-
- if (cpio->matching == NULL)
- initialize_matching(cpio);
- matching = cpio->matching;
- add_pattern(&(matching->inclusions), pattern);
- matching->inclusions_count++;
- matching->inclusions_unmatched_count++;
+
+ if (*matching == NULL)
+ initialize_matching(matching);
+ add_pattern(&((*matching)->inclusions), pattern);
+ (*matching)->inclusions_count++;
+ (*matching)->inclusions_unmatched_count++;
return (0);
}
int
-include_from_file(struct cpio *cpio, const char *pathname)
+include_from_file(struct matching **matching, const char *pathname,
+ int nullSeparator)
{
struct line_reader *lr;
const char *p;
int ret = 0;
- lr = process_lines_init(pathname, '\n');
- while ((p = process_lines_next(lr)) != NULL)
- if (include(cpio, p) != 0)
+ lr = line_reader(pathname, nullSeparator);
+ while ((p = line_reader_next(lr)) != NULL) {
+ if (include(matching, p) != 0)
ret = -1;
- process_lines_free(lr);
+ }
+ line_reader_free(lr);
return (ret);
}
@@ -123,15 +131,15 @@ static void
add_pattern(struct match **list, const char *pattern)
{
struct match *match;
+ size_t len;
- match = malloc(sizeof(*match) + strlen(pattern) + 1);
+ len = strlen(pattern);
+ match = malloc(sizeof(*match) + len + 1);
if (match == NULL)
- cpio_errc(1, errno, "Out of memory");
- if (pattern[0] == '/')
- pattern++;
+ errc(1, errno, "Out of memory");
strcpy(match->pattern, pattern);
/* Both "foo/" and "foo" should match "foo/bar". */
- if (match->pattern[strlen(match->pattern)-1] == '/')
+ if (len && match->pattern[len - 1] == '/')
match->pattern[strlen(match->pattern)-1] = '\0';
match->next = *list;
*list = match;
@@ -140,13 +148,11 @@ add_pattern(struct match **list, const char *pattern)
int
-excluded(struct cpio *cpio, const char *pathname)
+excluded(struct matching *matching, const char *pathname)
{
- struct matching *matching;
struct match *match;
struct match *matched;
- matching = cpio->matching;
if (matching == NULL)
return (0);
@@ -166,7 +172,7 @@ excluded(struct cpio *cpio, const char *pathname)
*/
if (match->matches == 0) {
match->matches++;
- matching->inclusions_unmatched_count++;
+ matching->inclusions_unmatched_count--;
return (0);
}
/*
@@ -198,7 +204,7 @@ excluded(struct cpio *cpio, const char *pathname)
* gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
*
*/
-int
+static int
match_exclusion(struct match *match, const char *pathname)
{
return (pathmatch(match->pattern,
@@ -210,50 +216,69 @@ match_exclusion(struct match *match, const char *pathname)
* Again, mimic gtar: inclusions are always anchored (have to match
* the beginning of the path) even though exclusions are not anchored.
*/
-int
+static int
match_inclusion(struct match *match, const char *pathname)
{
+#if 0
return (pathmatch(match->pattern, pathname, 0));
+#else
+ return (pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
+#endif
}
void
-cleanup_exclusions(struct cpio *cpio)
+cleanup_exclusions(struct matching **matching)
{
struct match *p, *q;
- if (cpio->matching) {
- p = cpio->matching->inclusions;
- while (p != NULL) {
- q = p;
- p = p->next;
- free(q);
- }
- p = cpio->matching->exclusions;
- while (p != NULL) {
- q = p;
- p = p->next;
- free(q);
- }
- free(cpio->matching);
+ if (*matching == NULL)
+ return;
+
+ for (p = (*matching)->inclusions; p != NULL; ) {
+ q = p;
+ p = p->next;
+ free(q);
+ }
+
+ for (p = (*matching)->exclusions; p != NULL; ) {
+ q = p;
+ p = p->next;
+ free(q);
}
+
+ free(*matching);
+ *matching = NULL;
}
static void
-initialize_matching(struct cpio *cpio)
+initialize_matching(struct matching **matching)
{
- cpio->matching = malloc(sizeof(*cpio->matching));
- if (cpio->matching == NULL)
- cpio_errc(1, errno, "No memory");
- memset(cpio->matching, 0, sizeof(*cpio->matching));
+ *matching = calloc(sizeof(**matching), 1);
+ if (*matching == NULL)
+ errc(1, errno, "No memory");
}
int
-unmatched_inclusions(struct cpio *cpio)
+unmatched_inclusions(struct matching *matching)
{
- struct matching *matching;
- matching = cpio->matching;
if (matching == NULL)
return (0);
return (matching->inclusions_unmatched_count);
}
+
+int
+unmatched_inclusions_warn(struct matching *matching, const char *msg)
+{
+ struct match *p;
+
+ if (matching == NULL)
+ return (0);
+
+ for (p = matching->inclusions; p != NULL; p = p->next) {
+ if (p->matches == 0)
+ warnc(0, "%s: %s", p->pattern, msg);
+ }
+
+ return (matching->inclusions_unmatched_count);
+}
diff --git a/usr.bin/cpio/matching.h b/usr.bin/cpio/matching.h
index a66bc86..e98e82e 100644
--- a/usr.bin/cpio/matching.h
+++ b/usr.bin/cpio/matching.h
@@ -29,12 +29,18 @@
#ifndef MATCHING_H
#define MATCHING_H
-#include "cpio.h"
+struct matching;
-int exclude(struct cpio *, const char *pattern);
-int include(struct cpio *, const char *pattern);
-int excluded(struct cpio *cpio, const char *pathname);
-void cleanup_exclusions(struct cpio *cpio);
-int unmatched_inclusions(struct cpio *cpio);
+int exclude(struct matching **matching, const char *pattern);
+int exclude_from_file(struct matching **matching,
+ const char *pathname);
+int include(struct matching **matching, const char *pattern);
+int include_from_file(struct matching **matching,
+ const char *pathname, int nullSeparator);
+
+int excluded(struct matching *, const char *pathname);
+void cleanup_exclusions(struct matching **);
+int unmatched_inclusions(struct matching *);
+int unmatched_inclusions_warn(struct matching *, const char *msg);
#endif
diff --git a/usr.bin/cpio/pathmatch.c b/usr.bin/cpio/pathmatch.c
index 40fa836..75f9095 100644
--- a/usr.bin/cpio/pathmatch.c
+++ b/usr.bin/cpio/pathmatch.c
@@ -131,7 +131,6 @@ pm(const char *p, const char *s, int flags)
s = pm_slashskip(s);
}
return (*s == '\0');
- break;
case '?':
/* ? always succeds, unless we hit end of 's' */
if (*s == '\0')
@@ -150,7 +149,6 @@ pm(const char *p, const char *s, int flags)
++s;
}
return (0);
- break;
case '[':
/*
* Find the end of the [...] character class,
@@ -229,9 +227,17 @@ pathmatch(const char *p, const char *s, int flags)
flags &= ~PATHMATCH_NO_ANCHOR_START;
}
- /* Certain patterns anchor implicitly. */
- if (*p == '*' || *p == '/')
+ if (*p == '/' && *s != '/')
+ return (0);
+
+ /* Certain patterns and file names anchor implicitly. */
+ if (*p == '*' || *p == '/' || *p == '/') {
+ while (*p == '/')
+ ++p;
+ while (*s == '/')
+ ++s;
return (pm(p, s, flags));
+ }
/* If start is unanchored, try to match start of each path element. */
if (flags & PATHMATCH_NO_ANCHOR_START) {
diff --git a/usr.bin/cpio/pathmatch.h b/usr.bin/cpio/pathmatch.h
index fd2c257..3e82830 100644
--- a/usr.bin/cpio/pathmatch.h
+++ b/usr.bin/cpio/pathmatch.h
@@ -26,13 +26,13 @@
* $FreeBSD$
*/
-#ifndef PATHMATCH_H
-#define PATHMATCH_H
+#ifndef LAFE_PATHMATCH_H
+#define LAFE_PATHMATCH_H
/* Don't anchor at beginning unless the pattern starts with "^" */
#define PATHMATCH_NO_ANCHOR_START 1
/* Don't anchor at end unless the pattern ends with "$" */
-#define PATHMATCH_NO_ANCHOR_END 2
+#define PATHMATCH_NO_ANCHOR_END 2
/* Note that "^" and "$" are not special unless you set the corresponding
* flag above. */
OpenPOWER on IntegriCloud