bsdcpio 2.8.3

This commit is contained in:
Tim Kientzle 2010-05-08 16:47:33 +00:00
parent 9122b590b2
commit b6cb607644
15 changed files with 684 additions and 571 deletions

View File

@ -3,8 +3,8 @@
.include <bsd.own.mk> .include <bsd.own.mk>
PROG= bsdcpio PROG= bsdcpio
BSDCPIO_VERSION_STRING=2.7.0 BSDCPIO_VERSION_STRING=2.8.3
SRCS= cpio.c cmdline.c err.c matching.c pathmatch.c SRCS= cpio.c cmdline.c err.c line_reader.c matching.c pathmatch.c
CFLAGS+= -DBSDCPIO_VERSION_STRING=\"${BSDCPIO_VERSION_STRING}\" CFLAGS+= -DBSDCPIO_VERSION_STRING=\"${BSDCPIO_VERSION_STRING}\"
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\" CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
.ifdef RELEASE_CRUNCH .ifdef RELEASE_CRUNCH

View File

@ -80,6 +80,9 @@ specified directory.
Unless specifically stated otherwise, options are applicable in Unless specifically stated otherwise, options are applicable in
all operating modes. all operating modes.
.Bl -tag -width indent .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 .It Fl A
(o mode only) (o mode only)
Append to the specified archive. Append to the specified archive.
@ -142,6 +145,11 @@ for more complete information about the
formats currently supported by the underlying formats currently supported by the underlying
.Xr libarchive 3 .Xr libarchive 3
library. library.
.It Fl H Ar format
Synonym for
.Fl -format .
.It Fl h , Fl -help
Print usage information.
.It Fl I Ar file .It Fl I Ar file
Read archive from Read archive from
.Ar file . .Ar file .
@ -154,6 +162,14 @@ Disable security checks during extraction or copying.
This allows extraction via symbolic links and path names containing This allows extraction via symbolic links and path names containing
.Sq .. .Sq ..
in the name. 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 .It Fl L
(o and p modes) (o and p modes)
All symbolic links will be followed. 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) (p mode only)
Create links from the target directory to the original files, Create links from the target directory to the original files,
instead of copying. 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 .It Fl m
(i and p modes) (i and p modes)
Set file modification time on created files to match 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 displays the user and group names when they are provided in the
archive, or looks up the user and group names in the system archive, or looks up the user and group names in the system
password database. 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 .It Fl O Ar file
Write archive to Write archive to
.Ar file . .Ar file .
@ -185,6 +210,10 @@ See above for description.
.It Fl p .It Fl p
Pass-through mode. Pass-through mode.
See above for description. 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 .It Fl -quiet
Suppress unnecessary messages. Suppress unnecessary messages.
.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc .It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc
@ -266,7 +295,7 @@ for more information.
.Sh EXAMPLES .Sh EXAMPLES
The The
.Nm .Nm
command is traditionally used to copy file hierarchies in conjunction command is traditionally used to copy file heirarchies in conjunction
with the with the
.Xr find 1 .Xr find 1
command. command.

View File

@ -46,11 +46,12 @@ __FBSDID("$FreeBSD$");
#endif #endif
#include "cpio.h" #include "cpio.h"
#include "err.h"
/* /*
* Short options for cpio. Please keep this sorted. * 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. * Long options for cpio. Please keep this sorted.
@ -61,7 +62,6 @@ static const struct option {
int equivalent; /* Equivalent short option. */ int equivalent; /* Equivalent short option. */
} cpio_longopts[] = { } cpio_longopts[] = {
{ "create", 0, 'o' }, { "create", 0, 'o' },
{ "dot", 0, 'V' },
{ "extract", 0, 'i' }, { "extract", 0, 'i' },
{ "file", 1, 'F' }, { "file", 1, 'F' },
{ "format", 1, 'H' }, { "format", 1, 'H' },
@ -69,6 +69,7 @@ static const struct option {
{ "insecure", 0, OPTION_INSECURE }, { "insecure", 0, OPTION_INSECURE },
{ "link", 0, 'l' }, { "link", 0, 'l' },
{ "list", 0, 't' }, { "list", 0, 't' },
{ "lzma", 0, OPTION_LZMA },
{ "make-directories", 0, 'd' }, { "make-directories", 0, 'd' },
{ "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER }, { "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER },
{ "null", 0, '0' }, { "null", 0, '0' },
@ -76,10 +77,12 @@ static const struct option {
{ "owner", 1, 'R' }, { "owner", 1, 'R' },
{ "pass-through", 0, 'p' }, { "pass-through", 0, 'p' },
{ "preserve-modification-time", 0, 'm' }, { "preserve-modification-time", 0, 'm' },
{ "preserve-owner", 0, OPTION_PRESERVE_OWNER },
{ "quiet", 0, OPTION_QUIET }, { "quiet", 0, OPTION_QUIET },
{ "unconditional", 0, 'u' }, { "unconditional", 0, 'u' },
{ "verbose", 0, 'v' }, { "verbose", 0, 'v' },
{ "version", 0, OPTION_VERSION }, { "version", 0, OPTION_VERSION },
{ "xz", 0, 'J' },
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };
@ -172,7 +175,7 @@ cpio_getopt(struct cpio *cpio)
/* Otherwise, pick up the next word. */ /* Otherwise, pick up the next word. */
opt_word = *cpio->argv; opt_word = *cpio->argv;
if (opt_word == NULL) { if (opt_word == NULL) {
cpio_warnc(0, warnc(0,
"Option -%c requires an argument", "Option -%c requires an argument",
opt); opt);
return ('?'); return ('?');
@ -223,13 +226,13 @@ cpio_getopt(struct cpio *cpio)
/* Fail if there wasn't a unique match. */ /* Fail if there wasn't a unique match. */
if (match == NULL) { if (match == NULL) {
cpio_warnc(0, warnc(0,
"Option %s%s is not supported", "Option %s%s is not supported",
long_prefix, opt_word); long_prefix, opt_word);
return ('?'); return ('?');
} }
if (match2 != NULL) { if (match2 != NULL) {
cpio_warnc(0, warnc(0,
"Ambiguous option %s%s (matches --%s and --%s)", "Ambiguous option %s%s (matches --%s and --%s)",
long_prefix, opt_word, match->name, match2->name); long_prefix, opt_word, match->name, match2->name);
return ('?'); return ('?');
@ -241,7 +244,7 @@ cpio_getopt(struct cpio *cpio)
if (cpio->optarg == NULL) { if (cpio->optarg == NULL) {
cpio->optarg = *cpio->argv; cpio->optarg = *cpio->argv;
if (cpio->optarg == NULL) { if (cpio->optarg == NULL) {
cpio_warnc(0, warnc(0,
"Option %s%s requires an argument", "Option %s%s requires an argument",
long_prefix, match->name); long_prefix, match->name);
return ('?'); return ('?');
@ -252,7 +255,7 @@ cpio_getopt(struct cpio *cpio)
} else { } else {
/* Argument forbidden: fail if there is one. */ /* Argument forbidden: fail if there is one. */
if (cpio->optarg != NULL) { if (cpio->optarg != NULL) {
cpio_warnc(0, warnc(0,
"Option %s%s does not allow an argument", "Option %s%s does not allow an argument",
long_prefix, match->name); long_prefix, match->name);
return ('?'); return ('?');
@ -283,17 +286,20 @@ cpio_getopt(struct cpio *cpio)
* *
* Sets uid/gid return as appropriate, -1 indicates uid/gid not specified. * 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) owner_parse(const char *spec, int *uid, int *gid)
{ {
static char errbuff[128];
const char *u, *ue, *g; const char *u, *ue, *g;
*uid = -1; *uid = -1;
*gid = -1; *gid = -1;
if (spec[0] == '\0') if (spec[0] == '\0')
return (1); return ("Invalid empty user/group spec");
/* /*
* Split spec into [user][:.][group] * Split spec into [user][:.][group]
@ -321,10 +327,8 @@ owner_parse(const char *spec, int *uid, int *gid)
struct passwd *pwent; struct passwd *pwent;
user = (char *)malloc(ue - u + 1); user = (char *)malloc(ue - u + 1);
if (user == NULL) { if (user == NULL)
cpio_warnc(errno, "Couldn't allocate memory"); return ("Couldn't allocate memory");
return (1);
}
memcpy(user, u, ue - u); memcpy(user, u, ue - u);
user[ue - u] = '\0'; user[ue - u] = '\0';
if ((pwent = getpwnam(user)) != NULL) { if ((pwent = getpwnam(user)) != NULL) {
@ -336,9 +340,10 @@ owner_parse(const char *spec, int *uid, int *gid)
errno = 0; errno = 0;
*uid = strtoul(user, &end, 10); *uid = strtoul(user, &end, 10);
if (errno || *end != '\0') { if (errno || *end != '\0') {
cpio_warnc(errno, snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup user ``%s''", user); "Couldn't lookup user ``%s''", user);
return (1); errbuff[sizeof(errbuff) - 1] = '\0';
return (errbuff);
} }
} }
free(user); free(user);
@ -353,11 +358,12 @@ owner_parse(const char *spec, int *uid, int *gid)
errno = 0; errno = 0;
*gid = strtoul(g, &end, 10); *gid = strtoul(g, &end, 10);
if (errno || *end != '\0') { if (errno || *end != '\0') {
cpio_warnc(errno, snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup group ``%s''", g); "Couldn't lookup group ``%s''", g);
return (1); errbuff[sizeof(errbuff) - 1] = '\0';
return (errbuff);
} }
} }
} }
return (0); return (NULL);
} }

View File

@ -25,83 +25,32 @@
* $FreeBSD$ * $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 */ #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_DIRENT_H 1
#define HAVE_D_MD_ORDER 1
#define HAVE_ERRNO_H 1 #define HAVE_ERRNO_H 1
#undef HAVE_EXT2FS_EXT2_FS_H
#define HAVE_FCHDIR 1
#define HAVE_FCNTL_H 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 #define HAVE_FUTIMES 1
#undef HAVE_GETXATTR
#define HAVE_GRP_H 1 #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_LIBARCHIVE 1
#define HAVE_LIBBZ2 1 #define HAVE_LINK 1
#define HAVE_LIBZ 1 #define HAVE_LSTAT 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_LUTIMES 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_PWD_H 1
#define HAVE_SETLOCALE 1 #define HAVE_READLINK 1
#define HAVE_STDARG_H 1 #define HAVE_STDARG_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_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_STRING_H 1
#define HAVE_STRRCHR 1 #define HAVE_SYMLINK 1
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC #define HAVE_SYS_CDEFS_H 1
#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_SYS_STAT_H 1 #define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_TIME_H 1 #define HAVE_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_UINTMAX_T 1 #define HAVE_UINTMAX_T 1
#define HAVE_UNISTD_H 1 #define HAVE_UNISTD_H 1
#define HAVE_UNSIGNED_LONG_LONG 1 #define HAVE_UNSIGNED_LONG_LONG 1
#define HAVE_UTIME_H 1
#define HAVE_UTIMES 1 #define HAVE_UTIMES 1
#define HAVE_VPRINTF 1
#define HAVE_ZLIB_H 1
#undef MAJOR_IN_MKDEV
#define STDC_HEADERS 1

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@
#include "cpio_platform.h" #include "cpio_platform.h"
#include <stdio.h> #include <stdio.h>
#define DEFAULT_BYTES_PER_BLOCK (20*512) #include "matching.h"
/* /*
* The internal state for the "cpio" program. * The internal state for the "cpio" program.
@ -52,17 +52,16 @@ struct cpio {
const char *format; /* -H format */ const char *format; /* -H format */
int bytes_per_block; /* -b block_size */ int bytes_per_block; /* -b block_size */
int verbose; /* -v */ int verbose; /* -v */
int dot; /* -V */
int quiet; /* --quiet */ int quiet; /* --quiet */
int extract_flags; /* Flags for extract operation */ int extract_flags; /* Flags for extract operation */
char symlink_mode; /* H or L, per BSD conventions */ char symlink_mode; /* H or L, per BSD conventions */
const char *compress_program; const char *compress_program;
char line_separator; /* --null ? '\0' : '\n' */
int option_append; /* -A, only relevant for -o */ int option_append; /* -A, only relevant for -o */
int option_atime_restore; /* -a */ int option_atime_restore; /* -a */
int option_follow_links; /* -L */ int option_follow_links; /* -L */
int option_link; /* -l */ int option_link; /* -l */
int option_list; /* -t */ int option_list; /* -t */
char option_null; /* --null */
int option_numeric_uid_gid; /* -n */ int option_numeric_uid_gid; /* -n */
int option_rename; /* -r */ int option_rename; /* -r */
char *destdir; char *destdir;
@ -77,6 +76,7 @@ struct cpio {
/* Miscellaneous state information */ /* Miscellaneous state information */
struct archive *archive; struct archive *archive;
struct archive *archive_read_disk;
int argc; int argc;
char **argv; char **argv;
int return_value; /* Value returned by main() */ int return_value; /* Value returned by main() */
@ -91,30 +91,19 @@ struct cpio {
size_t buff_size; size_t buff_size;
}; };
/* Name of this program; used in error reporting, initialized in main(). */ const char *owner_parse(const char *, int *, int *);
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 *);
/* Fake short equivalents for long options that otherwise lack them. */ /* Fake short equivalents for long options that otherwise lack them. */
enum { enum {
OPTION_INSECURE = 1, OPTION_INSECURE = 1,
OPTION_LZMA,
OPTION_NO_PRESERVE_OWNER, OPTION_NO_PRESERVE_OWNER,
OPTION_PRESERVE_OWNER,
OPTION_QUIET, OPTION_QUIET,
OPTION_VERSION 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 cpio_getopt(struct cpio *cpio);
int include_from_file(struct cpio *, const char *);
#endif #endif

View File

@ -37,19 +37,18 @@
#if defined(PLATFORM_CONFIG_H) #if defined(PLATFORM_CONFIG_H)
/* Use hand-built config.h in environments that need it. */ /* Use hand-built config.h in environments that need it. */
#include PLATFORM_CONFIG_H #include PLATFORM_CONFIG_H
#elif defined(HAVE_CONFIG_H)
/* Most POSIX platforms use the 'configure' script to build config.h */
#include "config.h"
#else #else
/* Warn if cpio hasn't been (automatically or manually) configured. */ /* Read config.h or die trying. */
#error Oops: No config.h and no built-in configuration in cpio_platform.h. #include "config.h"
#endif /* !HAVE_CONFIG_H */ #endif
/* No non-FreeBSD platform will have __FBSDID, so just define it here. */ /* Get a real definition for __FBSDID if we can */
#ifdef __FreeBSD__ #if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> /* For __FBSDID */ #include <sys/cdefs.h>
#elif !defined(__FBSDID) #endif
/* Just leaving this macro replacement empty leads to a dangling semicolon. */
/* If not, define it so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack #define __FBSDID(a) struct _undefined_hack
#endif #endif
@ -63,24 +62,6 @@
#include "archive_entry.h" #include "archive_entry.h"
#endif #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. */ /* How to mark functions that don't return. */
#if defined(__GNUC__) && (__GNUC__ > 2 || \ #if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5)) (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
@ -89,9 +70,7 @@
#define __LA_DEAD #define __LA_DEAD
#endif #endif
#if defined(__CYGWIN__) #if defined(_WIN32) && !defined(__CYGWIN__)
#include "cpio_cygwin.h"
#elif defined(_WIN32) /* && !__CYGWIN__ */
#include "cpio_windows.h" #include "cpio_windows.h"
#endif #endif

View File

@ -24,7 +24,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "cpio_platform.h" #include "cpio_platform.h"
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
@ -39,12 +38,14 @@ __FBSDID("$FreeBSD$");
#include <string.h> #include <string.h>
#endif #endif
#include "cpio.h" #include "err.h"
const char *progname;
static void 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); vfprintf(stderr, fmt, ap);
if (code != 0) if (code != 0)
fprintf(stderr, ": %s", strerror(code)); fprintf(stderr, ": %s", strerror(code));
@ -52,22 +53,22 @@ cpio_vwarnc(int code, const char *fmt, va_list ap)
} }
void void
cpio_warnc(int code, const char *fmt, ...) warnc(int code, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
cpio_vwarnc(code, fmt, ap); vwarnc(code, fmt, ap);
va_end(ap); va_end(ap);
} }
void void
cpio_errc(int eval, int code, const char *fmt, ...) errc(int eval, int code, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
cpio_vwarnc(code, fmt, ap); vwarnc(code, fmt, ap);
va_end(ap); va_end(ap);
exit(eval); exit(eval);
} }

43
usr.bin/cpio/err.h Normal file
View File

@ -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

171
usr.bin/cpio/line_reader.c Normal file
View File

@ -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);
}

View File

@ -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

View File

@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include <string.h> #include <string.h>
#endif #endif
#include "err.h"
#include "line_reader.h"
#include "matching.h" #include "matching.h"
#include "pathmatch.h" #include "pathmatch.h"
@ -54,7 +56,7 @@ struct matching {
}; };
static void add_pattern(struct match **list, const char *pattern); 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_exclusion(struct match *, const char *pathname);
static int match_inclusion(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 int
exclude(struct cpio *cpio, const char *pattern) exclude(struct matching **matching, const char *pattern)
{ {
struct matching *matching;
if (cpio->matching == NULL) if (*matching == NULL)
initialize_matching(cpio); initialize_matching(matching);
matching = cpio->matching; add_pattern(&((*matching)->exclusions), pattern);
add_pattern(&(matching->exclusions), pattern); (*matching)->exclusions_count++;
matching->exclusions_count++;
return (0);
}
#if 0
int
exclude_from_file(struct cpio *cpio, const char *pathname)
{
return (process_lines(cpio, pathname, &exclude));
}
#endif
int
include(struct cpio *cpio, 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++;
return (0); return (0);
} }
int int
include_from_file(struct cpio *cpio, const char *pathname) exclude_from_file(struct matching **matching, const char *pathname)
{ {
struct line_reader *lr; struct line_reader *lr;
const char *p; const char *p;
int ret = 0; int ret = 0;
lr = process_lines_init(pathname, '\n'); lr = line_reader(pathname, 0);
while ((p = process_lines_next(lr)) != NULL) while ((p = line_reader_next(lr)) != NULL) {
if (include(cpio, p) != 0) if (exclude(matching, p) != 0)
ret = -1; ret = -1;
process_lines_free(lr); }
line_reader_free(lr);
return (ret);
}
int
include(struct matching **matching, const char *pattern)
{
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 matching **matching, const char *pathname,
int nullSeparator)
{
struct line_reader *lr;
const char *p;
int ret = 0;
lr = line_reader(pathname, nullSeparator);
while ((p = line_reader_next(lr)) != NULL) {
if (include(matching, p) != 0)
ret = -1;
}
line_reader_free(lr);
return (ret); return (ret);
} }
@ -123,15 +131,15 @@ static void
add_pattern(struct match **list, const char *pattern) add_pattern(struct match **list, const char *pattern)
{ {
struct match *match; 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) if (match == NULL)
cpio_errc(1, errno, "Out of memory"); errc(1, errno, "Out of memory");
if (pattern[0] == '/')
pattern++;
strcpy(match->pattern, pattern); strcpy(match->pattern, pattern);
/* Both "foo/" and "foo" should match "foo/bar". */ /* 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->pattern[strlen(match->pattern)-1] = '\0';
match->next = *list; match->next = *list;
*list = match; *list = match;
@ -140,13 +148,11 @@ add_pattern(struct match **list, const char *pattern)
int int
excluded(struct cpio *cpio, const char *pathname) excluded(struct matching *matching, const char *pathname)
{ {
struct matching *matching;
struct match *match; struct match *match;
struct match *matched; struct match *matched;
matching = cpio->matching;
if (matching == NULL) if (matching == NULL)
return (0); return (0);
@ -166,7 +172,7 @@ excluded(struct cpio *cpio, const char *pathname)
*/ */
if (match->matches == 0) { if (match->matches == 0) {
match->matches++; match->matches++;
matching->inclusions_unmatched_count++; matching->inclusions_unmatched_count--;
return (0); return (0);
} }
/* /*
@ -198,7 +204,7 @@ excluded(struct cpio *cpio, const char *pathname)
* gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar' * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
* *
*/ */
int static int
match_exclusion(struct match *match, const char *pathname) match_exclusion(struct match *match, const char *pathname)
{ {
return (pathmatch(match->pattern, 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 * Again, mimic gtar: inclusions are always anchored (have to match
* the beginning of the path) even though exclusions are not anchored. * the beginning of the path) even though exclusions are not anchored.
*/ */
int static int
match_inclusion(struct match *match, const char *pathname) match_inclusion(struct match *match, const char *pathname)
{ {
#if 0
return (pathmatch(match->pattern, pathname, 0)); return (pathmatch(match->pattern, pathname, 0));
#else
return (pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
#endif
} }
void void
cleanup_exclusions(struct cpio *cpio) cleanup_exclusions(struct matching **matching)
{ {
struct match *p, *q; struct match *p, *q;
if (cpio->matching) { if (*matching == NULL)
p = cpio->matching->inclusions; return;
while (p != NULL) {
q = p; for (p = (*matching)->inclusions; p != NULL; ) {
p = p->next; q = p;
free(q); p = p->next;
} free(q);
p = cpio->matching->exclusions;
while (p != NULL) {
q = p;
p = p->next;
free(q);
}
free(cpio->matching);
} }
for (p = (*matching)->exclusions; p != NULL; ) {
q = p;
p = p->next;
free(q);
}
free(*matching);
*matching = NULL;
} }
static void static void
initialize_matching(struct cpio *cpio) initialize_matching(struct matching **matching)
{ {
cpio->matching = malloc(sizeof(*cpio->matching)); *matching = calloc(sizeof(**matching), 1);
if (cpio->matching == NULL) if (*matching == NULL)
cpio_errc(1, errno, "No memory"); errc(1, errno, "No memory");
memset(cpio->matching, 0, sizeof(*cpio->matching));
} }
int int
unmatched_inclusions(struct cpio *cpio) unmatched_inclusions(struct matching *matching)
{ {
struct matching *matching;
matching = cpio->matching;
if (matching == NULL) if (matching == NULL)
return (0); return (0);
return (matching->inclusions_unmatched_count); 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);
}

View File

@ -29,12 +29,18 @@
#ifndef MATCHING_H #ifndef MATCHING_H
#define MATCHING_H #define MATCHING_H
#include "cpio.h" struct matching;
int exclude(struct cpio *, const char *pattern); int exclude(struct matching **matching, const char *pattern);
int include(struct cpio *, const char *pattern); int exclude_from_file(struct matching **matching,
int excluded(struct cpio *cpio, const char *pathname); const char *pathname);
void cleanup_exclusions(struct cpio *cpio); int include(struct matching **matching, const char *pattern);
int unmatched_inclusions(struct cpio *cpio); 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 #endif

View File

@ -131,7 +131,6 @@ pm(const char *p, const char *s, int flags)
s = pm_slashskip(s); s = pm_slashskip(s);
} }
return (*s == '\0'); return (*s == '\0');
break;
case '?': case '?':
/* ? always succeds, unless we hit end of 's' */ /* ? always succeds, unless we hit end of 's' */
if (*s == '\0') if (*s == '\0')
@ -150,7 +149,6 @@ pm(const char *p, const char *s, int flags)
++s; ++s;
} }
return (0); return (0);
break;
case '[': case '[':
/* /*
* Find the end of the [...] character class, * 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; flags &= ~PATHMATCH_NO_ANCHOR_START;
} }
/* Certain patterns anchor implicitly. */ if (*p == '/' && *s != '/')
if (*p == '*' || *p == '/') return (0);
/* Certain patterns and file names anchor implicitly. */
if (*p == '*' || *p == '/' || *p == '/') {
while (*p == '/')
++p;
while (*s == '/')
++s;
return (pm(p, s, flags)); return (pm(p, s, flags));
}
/* If start is unanchored, try to match start of each path element. */ /* If start is unanchored, try to match start of each path element. */
if (flags & PATHMATCH_NO_ANCHOR_START) { if (flags & PATHMATCH_NO_ANCHOR_START) {

View File

@ -26,13 +26,13 @@
* $FreeBSD$ * $FreeBSD$
*/ */
#ifndef PATHMATCH_H #ifndef LAFE_PATHMATCH_H
#define PATHMATCH_H #define LAFE_PATHMATCH_H
/* Don't anchor at beginning unless the pattern starts with "^" */ /* Don't anchor at beginning unless the pattern starts with "^" */
#define PATHMATCH_NO_ANCHOR_START 1 #define PATHMATCH_NO_ANCHOR_START 1
/* Don't anchor at end unless the pattern ends with "$" */ /* 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 /* Note that "^" and "$" are not special unless you set the corresponding
* flag above. */ * flag above. */