From 08895e6721d60486b26d2089d48277db846ac4db Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sat, 12 Jul 2008 14:42:23 +0000 Subject: [PATCH] Import libarchive-2.5.5. --- contrib/libarchive-2/NEWS | 8 + contrib/libarchive-2/cpio/bsdcpio.1 | 367 +++++++ contrib/libarchive-2/cpio/cmdline.c | 256 +++++ contrib/libarchive-2/cpio/cpio.c | 1026 ++++++++++++++++++++ contrib/libarchive-2/cpio/cpio.h | 110 +++ contrib/libarchive-2/cpio/cpio_platform.h | 84 ++ .../archive_entry_strmode.c => cpio/err.c} | 81 +- contrib/libarchive-2/cpio/matching.c | 259 +++++ contrib/libarchive-2/cpio/matching.h | 40 + contrib/libarchive-2/cpio/pathmatch.c | 250 +++++ contrib/libarchive-2/cpio/pathmatch.h | 37 + contrib/libarchive-2/libarchive/archive.h | 6 +- contrib/libarchive-2/libarchive/archive_endian.h | 2 +- contrib/libarchive-2/libarchive/archive_entry.3 | 2 +- contrib/libarchive-2/libarchive/archive_entry.c | 2 +- contrib/libarchive-2/libarchive/archive_entry.h | 2 +- .../libarchive/archive_entry_link_resolver.c | 5 +- .../libarchive/archive_entry_private.h | 2 +- .../libarchive/archive_entry_strmode.c | 7 +- contrib/libarchive-2/libarchive/archive_platform.h | 2 +- contrib/libarchive-2/libarchive/archive_read.3 | 2 +- .../libarchive-2/libarchive/archive_read_extract.c | 2 +- .../archive_read_support_compression_bzip2.c | 2 +- .../archive_read_support_compression_program.c | 14 +- .../libarchive/archive_read_support_format_ar.c | 2 +- .../archive_read_support_format_iso9660.c | 2 +- .../libarchive/archive_read_support_format_mtree.c | 100 +- .../libarchive/archive_read_support_format_tar.c | 4 +- .../libarchive/archive_read_support_format_zip.c | 10 +- contrib/libarchive-2/libarchive/archive_string.c | 92 +- contrib/libarchive-2/libarchive/archive_string.h | 5 +- contrib/libarchive-2/libarchive/archive_util.c | 2 +- contrib/libarchive-2/libarchive/archive_write.3 | 2 +- .../libarchive-2/libarchive/archive_write_disk.3 | 2 +- .../libarchive-2/libarchive/archive_write_disk.c | 25 +- .../archive_write_set_compression_program.c | 12 +- .../libarchive/archive_write_set_format_ar.c | 2 +- .../libarchive/archive_write_set_format_pax.c | 2 +- .../libarchive/archive_write_set_format_ustar.c | 2 +- contrib/libarchive-2/libarchive/cpio.5 | 2 +- contrib/libarchive-2/libarchive/filter_fork.c | 39 +- .../libarchive-2/libarchive/libarchive-formats.5 | 2 +- contrib/libarchive-2/libarchive/tar.5 | 2 +- contrib/libarchive-2/tar/bsdtar.1 | 2 +- contrib/libarchive-2/tar/bsdtar.c | 2 +- contrib/libarchive-2/tar/bsdtar.h | 2 +- contrib/libarchive-2/tar/matching.c | 2 +- contrib/libarchive-2/tar/read.c | 4 +- contrib/libarchive-2/tar/subst.c | 18 +- contrib/libarchive-2/tar/util.c | 8 +- contrib/libarchive-2/tar/write.c | 5 +- contrib/libarchive-2/version | 2 +- 52 files changed, 2733 insertions(+), 189 deletions(-) create mode 100644 contrib/libarchive-2/cpio/bsdcpio.1 create mode 100644 contrib/libarchive-2/cpio/cmdline.c create mode 100644 contrib/libarchive-2/cpio/cpio.c create mode 100644 contrib/libarchive-2/cpio/cpio.h create mode 100644 contrib/libarchive-2/cpio/cpio_platform.h copy contrib/libarchive-2/{libarchive/archive_entry_strmode.c => cpio/err.c} (51%) create mode 100644 contrib/libarchive-2/cpio/matching.c create mode 100644 contrib/libarchive-2/cpio/matching.h create mode 100644 contrib/libarchive-2/cpio/pathmatch.c create mode 100644 contrib/libarchive-2/cpio/pathmatch.h diff --git a/contrib/libarchive-2/NEWS b/contrib/libarchive-2/NEWS index b7e578e290..36005fd1e9 100644 --- a/contrib/libarchive-2/NEWS +++ b/contrib/libarchive-2/NEWS @@ -1,4 +1,12 @@ +Jul 02, 2008: libarchive 2.5.5 released + +Jul 02, 2008: libarchive 2.5.5b released +Jul 01, 2008: bsdcpio is being used by enough people, we can call it 1.0.0 now +Jun 20, 2008: bsdcpio: If a -l link fails with EXDEV, copy the file instead +Jun 19, 2008: bsdcpio: additional long options for better GNU cpio compat +Jun 15, 2008: Many small portability and bugfixes since 2.5.4b. + May 25, 2008: libarchive 2.5.4b released May 21, 2008: Joerg Sonnenberger: fix bsdtar hardlink handling for newc format diff --git a/contrib/libarchive-2/cpio/bsdcpio.1 b/contrib/libarchive-2/cpio/bsdcpio.1 new file mode 100644 index 0000000000..d4a1857852 --- /dev/null +++ b/contrib/libarchive-2/cpio/bsdcpio.1 @@ -0,0 +1,367 @@ +.\" Copyright (c) 2003-2007 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. +.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$ +.\" +.Dd December 21, 2007 +.Dt BSDCPIO 1 +.Os +.Sh NAME +.Nm cpio +.Nd copy files to and from archives +.Sh SYNOPSIS +.Nm +.Brq Fl i +.Op Ar options +.Op Ar pattern ... +.Op Ar < archive +.Nm +.Brq Fl o +.Op Ar options +.Ar < name-list +.Op Ar > archive +.Nm +.Brq Fl p +.Op Ar options +.Ar dest-dir +.Ar < name-list +.Sh DESCRIPTION +.Nm +copies files between archives and directories. +This implementation can extract from tar, pax, cpio, zip, jar, ar, +and ISO 9660 cdrom images and can create tar, pax, cpio, ar, +and shar archives. +.Pp +The first option to +.Nm +is a mode indicator from the following list: +.Bl -tag -compact -width indent +.It Fl i +Input. +Read an archive from standard input (unless overriden) and extract the +contents to disk or (if the +.Fl t +option is specified) +list the contents to standard output. +If one or more file patterns are specified, only files matching +one of the patterns will be extracted. +.It Fl o +Output. +Read a list of filenames from standard input and produce a new archive +on standard output (unless overriden) containing the specified items. +.It Fl p +Pass-through. +Read a list of filenames from standard input and copy the files to the +specified directory. +.El +.Pp +.Sh OPTIONS +Unless specifically stated otherwise, options are applicable in +all operating modes. +.Bl -tag -width indent +.It Fl A +(o mode only) +Append to the specified archive. +(Not yet implemented.) +.It Fl a +(o and p modes) +Reset access times on files after they are read. +.It Fl B +(o mode only) +Block output to records of 5120 bytes. +.It Fl C Ar size +(o mode only) +Block output to records of +.Ar size +bytes. +.It Fl c +(o mode only) +Use the old POSIX portable character format. +Equivalent to +.Fl -format Ar odc . +.It Fl d +(i and p modes) +Create directories as necessary. +.It Fl E Ar file +(i mode only) +Read list of file name patterns from +.Ar file +to list and extract. +.It Fl F Ar file +Read archive from or write archive to +.Ar file . +.It Fl f Ar pattern +(i mode only) +Ignore files that match +.Ar pattern . +.It Fl -format Ar format +(o mode only) +Produce the output archive in the specified format. +Supported formats include: +.Pp +.Bl -tag -width "iso9660" -compact +.It Ar cpio +Synonym for +.Ar odc . +.It Ar newc +The SVR4 portable cpio format. +.It Ar odc +The old POSIX.1 portable octet-oriented cpio format. +.It Ar pax +The POSIX.1 pax format, an extension of the ustar format. +.It Ar ustar +The POSIX.1 tar format. +.El +.Pp +The default format is +.Ar odc . +See +.Xr libarchive_formats 5 +for more complete information about the +formats currently supported by the underlying +.Xr libarchive 3 +library. +.It Fl I Ar file +Read archive from +.Ar file . +.It Fl i +Input mode. +See above for description. +.It Fl -insecure +(i and p mode only) +Disable security checks during extraction or copying. +This allows extraction via symbolic links and path names containing +.Sq .. +in the name. +.It Fl L +(o and p modes) +All symbolic links will be followed. +Normally, symbolic links are archived and copied as symbolic links. +With this option, the target of the link will be archived or copied instead. +.It Fl l +(p mode only) +Create links from the target directory to the original files, +instead of copying. +.It Fl m +(i and p modes) +Set file modification time on created files to match +those in the source. +.It Fl O Ar file +Write archive to +.Ar file . +.It Fl o +Output mode. +See above for description. +.It Fl p +Pass-through mode. +See above for description. +.It Fl -quiet +Suppress unnecessary messages. +.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc +Set the owner and/or group on files in the output. +If group is specified with no user +(for example, +.Fl R Ar :wheel ) +then the group will be set but not the user. +If the user is specified with a trailing colon and no group +(for example, +.Fl R Ar root: ) +then the group will be set to the user's default group. +If the user is specified with no trailing colon, then +the user will be set but not the group. +In +.Fl i +and +.Fl p +modes, this option can only be used by the super-user. +(For compatibility, a period can be used in place of the colon.) +.It Fl r +(All modes.) +Rename files interactively. +For each file, a prompt is written to +.Pa /dev/tty +containing the name of the file and a line is read from +.Pa /dev/tty . +If the line read is blank, the file is skipped. +If the line contains a single period, the file is processed normally. +Otherwise, the line is taken to be the new name of the file. +.It Fl t +(i mode only) +List the contents of the archive to stdout; +do not restore the contents to disk. +.It Fl u +(i and p modes) +Unconditionally overwrite existing files. +Ordinarily, an older file will not overwrite a newer file on disk. +.It Fl v +Print the name of each file to stderr as it is processed. +With +.Fl t , +provide a detailed listing of each file. +.It Fl -version +Print the program version information and exit. +.It Fl y +(o mode only) +Compress the archive with bzip2-compatible compression before writing it. +In input mode, this option is ignored; +bzip2 compression is recognized automatically on input. +.It Fl Z +(o mode only) +Compress the archive with compress-compatible compression before writing it. +In input mode, this option is ignored; +compression is recognized automatically on input. +.It Fl z +(o mode only) +Compress the archive with gzip-compatible compression before writing it. +In input mode, this option is ignored; +gzip compression is recognized automatically on input. +.El +.Sh ENVIRONMENT +The following environment variables affect the execution of +.Nm : +.Bl -tag -width ".Ev BLOCKSIZE" +.It Ev LANG +The locale to use. +See +.Xr environ 7 +for more information. +.It Ev TZ +The timezone to use when displaying dates. +See +.Xr environ 7 +for more information. +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +The +.Nm +command is traditionally used to copy file heirarchies in conjunction +with the +.Xr find 1 +command. +The first example here simply copies all files from +.Pa src +to +.Pa dest : +.Dl Nm find Pa src | Nm Fl pmud Pa dest +.Pp +By carefully selecting options to the +.Xr find 1 +command and combining it with other standard utilities, +it is possible to exercise very fine control over which files are copied. +This next example copies files from +.Pa src +to +.Pa dest +that are more than 2 days old and whose names match a particular pattern: +.Dl Nm find Pa src Fl mtime Ar +2 | Nm grep foo[bar] | Nm Fl pdmu Pa dest +.Pp +This example copies files from +.Pa src +to +.Pa dest +that are more than 2 days old and which contain the word +.Do foobar Dc : +.Dl Nm find Pa src Fl mtime Ar +2 | Nm xargs Nm grep -l foobar | Nm Fl pdmu Pa dest +.Sh COMPATIBILITY +The mode options i, o, and p and the options +a, B, c, d, f, l, m, r, t, u, and v comply with SUSv2. +.Pp +The old POSIX.1 standard specified that only +.Fl i , +.Fl o , +and +.Fl p +were interpreted as command-line options. +Each took a single argument of a list of modifier +characters. +For example, the standard syntax allows +.Fl imu +but does not support +.Fl miu +or +.Fl i Fl m Fl u , +since +.Ar m +and +.Ar u +are only modifiers to +.Fl i , +they are not command-line options in their own right. +The syntax supported by this implementation is backwards-compatible +with the standard. +For best compatibility, scripts should limit themselves to the +standard syntax. +.Sh SEE ALSO +.Xr bzip2 1 , +.Xr tar 1 , +.Xr gzip 1 , +.Xr mt 1 , +.Xr pax 1 , +.Xr libarchive 3 , +.Xr cpio 5 , +.Xr libarchive-formats 5 , +.Xr tar 5 +.Sh STANDARDS +There is no current POSIX standard for the cpio command; it appeared +in +.St -p1003.1-96 +but was dropped from +.St -p1003.1-2001 . +.Pp +The cpio, ustar, and pax interchange file formats are defined by +.St -p1003.1-2001 +for the pax command. +.Sh HISTORY +The original +.Nm cpio +and +.Nm find +utilities were written by Dick Haight +while working in AT&T's Unix Support Group. +They first appeared in 1977 in PWB/UNIX 1.0, the +.Dq Programmer's Work Bench +system developed for use within AT&T. +They were first released outside of AT&T as part of System III Unix in 1981. +As a result, +.Nm cpio +actually predates +.Nm tar , +even though it was not well-known outside of AT&T until some time later. +.Pp +This is a complete re-implementation based on the +.Xr libarchive 3 +library. +.Sh BUGS +The cpio archive format has several basic limitations: +It does not store user and group names, only numbers. +As a result, it cannot be reliably used to transfer +files between systems with dissimilar user and group numbering. +Older cpio formats limit the user and group numbers to +16 or 18 bits, which is insufficient for modern systems. +The cpio archive formats cannot support files over 4 gigabytes, +except for the +.Dq odc +variant, which can support files up to 8 gigabytes. diff --git a/contrib/libarchive-2/cpio/cmdline.c b/contrib/libarchive-2/cpio/cmdline.c new file mode 100644 index 0000000000..a602e39c17 --- /dev/null +++ b/contrib/libarchive-2/cpio/cmdline.c @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 2003-2007 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: src/usr.bin/cpio/cmdline.c,v 1.3 2008/06/21 02:20:20 kientzle Exp $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_GETOPT_LONG +#include +#else +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; +#define no_argument 0 +#define required_argument 1 +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "cpio.h" + +/* + * + * Option parsing routines for bsdcpio. + * + */ + + +static const char *cpio_opts = "0AaBC:F:O:cdE:f:H:hijLlmopR:rtuvW:yZz"; + +/* + * On systems that lack getopt_long, long options can be specified + * using -W longopt and -W longopt=value, e.g. "-W version" is the + * same as "--version" and "-W format=ustar" is the same as "--format + * ustar". This does not rely the GNU getopt() "W;" extension, so + * should work correctly on any system with a POSIX-compliant + * getopt(). + */ + +/* + * If you add anything, be very careful to keep this list properly + * sorted, as the -W logic below relies on it. + */ +static const struct option cpio_longopts[] = { + { "create", no_argument, NULL, 'o' }, + { "extract", no_argument, NULL, 'i' }, + { "file", required_argument, NULL, 'F' }, + { "format", required_argument, NULL, 'H' }, + { "help", no_argument, NULL, 'h' }, + { "insecure", no_argument, NULL, OPTION_INSECURE }, + { "link", no_argument, NULL, 'l' }, + { "list", no_argument, NULL, 't' }, + { "make-directories", no_argument, NULL, 'd' }, + { "null", no_argument, NULL, '0' }, + { "owner", required_argument, NULL, 'R' }, + { "pass-through", no_argument, NULL, 'p' }, + { "preserve-modification-time", no_argument, NULL, 'm' }, + { "quiet", no_argument, NULL, OPTION_QUIET }, + { "unconditional", no_argument, NULL, 'u' }, + { "verbose", no_argument, NULL, 'v' }, + { "version", no_argument, NULL, OPTION_VERSION }, + { NULL, 0, NULL, 0 } +}; + +/* + * Parse command-line options using system-provided getopt() or getopt_long(). + * If option is -W, then parse argument as a long option. + */ +int +cpio_getopt(struct cpio *cpio) +{ + char *p, *q; + const struct option *option, *option2; + int opt; + int option_index; + size_t option_length; + + option_index = -1; + +#ifdef HAVE_GETOPT_LONG + opt = getopt_long(cpio->argc, cpio->argv, cpio_opts, + cpio_longopts, &option_index); +#else + opt = getopt(cpio->argc, cpio->argv, cpio_opts); +#endif + + /* Support long options through -W longopt=value */ + if (opt == 'W') { + p = optarg; + q = strchr(optarg, '='); + if (q != NULL) { + option_length = (size_t)(q - p); + optarg = q + 1; + } else { + option_length = strlen(p); + optarg = NULL; + } + option = cpio_longopts; + while (option->name != NULL && + (strlen(option->name) < option_length || + strncmp(p, option->name, option_length) != 0 )) { + option++; + } + + if (option->name != NULL) { + option2 = option; + opt = option->val; + + /* If the first match was exact, we're done. */ + if (strncmp(p, option->name, strlen(option->name)) == 0) { + while (option->name != NULL) + option++; + } else { + /* Check if there's another match. */ + option++; + while (option->name != NULL && + (strlen(option->name) < option_length || + strncmp(p, option->name, option_length) != 0)) { + option++; + } + } + if (option->name != NULL) + cpio_errc(1, 0, + "Ambiguous option %s " + "(matches both %s and %s)", + p, option2->name, option->name); + + if (option2->has_arg == required_argument + && optarg == NULL) + cpio_errc(1, 0, + "Option \"%s\" requires argument", p); + } else { + opt = '?'; + } + } + + return (opt); +} + + +/* + * Parse the argument to the -R or --owner flag. + * + * The format is one of the following: + * - Override user but not group + * : - Override both, group is user's default group + * : - Override both + * : - Override group but not user + * + * A period can be used instead of the colon. + * + * Sets uid/gid as appropriate, -1 indicates uid/gid not specified. + * + */ +int +owner_parse(const char *spec, int *uid, int *gid) +{ + const char *u, *ue, *g; + + *uid = -1; + *gid = -1; + + /* + * Split spec into [user][:.][group] + * u -> first char of username, NULL if no username + * ue -> first char after username (colon, period, or \0) + * g -> first char of group name + */ + if (*spec == ':' || *spec == '.') { + /* If spec starts with ':' or '.', then just group. */ + ue = u = NULL; + g = spec + 1; + } else { + /* Otherwise, [user] or [user][:] or [user][:][group] */ + ue = u = spec; + while (*ue != ':' && *ue != '.' && *ue != '\0') + ++ue; + g = ue; + if (*g != '\0') /* Skip : or . to find first char of group. */ + ++g; + } + + if (u != NULL) { + /* Look up user: ue is first char after end of user. */ + char *user; + struct passwd *pwent; + + user = (char *)malloc(ue - u + 1); + if (user == NULL) { + cpio_warnc(errno, "Couldn't allocate memory"); + return (1); + } + memcpy(user, u, ue - u); + user[ue - u] = '\0'; + pwent = getpwnam(user); + if (pwent == NULL) { + cpio_warnc(errno, "Couldn't lookup user ``%s''", user); + return (1); + } + free(user); + *uid = pwent->pw_uid; + if (*ue != '\0' && *g == '\0') + *gid = pwent->pw_gid; + } + if (*g != '\0') { + struct group *grp; + grp = getgrnam(g); + if (grp != NULL) + *gid = grp->gr_gid; + else { + cpio_warnc(errno, "Couldn't look up group ``%s''", g); + return (1); + } + } + return (0); +} diff --git a/contrib/libarchive-2/cpio/cpio.c b/contrib/libarchive-2/cpio/cpio.c new file mode 100644 index 0000000000..76a91cf715 --- /dev/null +++ b/contrib/libarchive-2/cpio/cpio.c @@ -0,0 +1,1026 @@ +/*- + * Copyright (c) 2003-2007 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: src/usr.bin/cpio/cpio.c,v 1.4 2008/06/24 15:18:40 kientzle Exp $"); + +#include +#include +#include + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "cpio.h" +#include "matching.h" + +static int copy_data(struct archive *, struct archive *); +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 *); +static void long_help(void); +static void mode_in(struct cpio *); +static void mode_list(struct cpio *); +static void mode_out(struct cpio *); +static void mode_pass(struct cpio *, const char *); +static void restore_time(struct cpio *, struct archive_entry *, + const char *, int fd); +static void usage(void); +static void version(void); + +int +main(int argc, char *argv[]) +{ + static char buff[16384]; + struct cpio _cpio; /* Allocated on stack. */ + struct cpio *cpio; + int uid, gid; + int opt; + + cpio = &_cpio; + memset(cpio, 0, sizeof(*cpio)); + cpio->buff = buff; + cpio->buff_size = sizeof(buff); + + /* Need cpio_progname before calling cpio_warnc. */ + if (*argv == NULL) + cpio_progname = "bsdcpio"; + else { + cpio_progname = strrchr(*argv, '/'); + if (cpio_progname != NULL) + cpio_progname++; + else + cpio_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'; + /* TODO: Implement old binary format in libarchive, use that here. */ + cpio->format = "odc"; /* Default format */ + cpio->extract_flags = ARCHIVE_EXTRACT_NO_AUTODIR; + cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS; + cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT; + /* TODO: If run by root, set owner as well. */ + 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'; + break; + case 'A': /* NetBSD/OpenBSD */ + cpio->option_append = 1; + break; + case 'a': /* POSIX 1997 */ + cpio->option_atime_restore = 1; + break; + case 'B': /* POSIX 1997 */ + cpio->bytes_per_block = 5120; + break; + case 'C': /* NetBSD/OpenBSD */ + cpio->bytes_per_block = atoi(optarg); + if (cpio->bytes_per_block <= 0) + cpio_errc(1, 0, "Invalid blocksize %s", optarg); + break; + case 'c': /* POSIX 1997 */ + cpio->format = "odc"; + break; + case 'd': /* POSIX 1997 */ + cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR; + break; + case 'E': /* NetBSD/OpenBSD */ + include_from_file(cpio, optarg); + break; + case 'F': /* NetBSD/OpenBSD/GNU cpio */ + cpio->filename = optarg; + break; + case 'f': /* POSIX 1997 */ + exclude(cpio, optarg); + break; + case 'H': /* GNU cpio (also --format) */ + cpio->format = optarg; + break; + case 'h': + long_help(); + break; + case 'I': /* NetBSD/OpenBSD */ + cpio->filename = optarg; + break; + case 'i': /* POSIX 1997 */ + cpio->mode = opt; + break; + case OPTION_INSECURE: + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS; + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT; + break; + case 'L': /* GNU cpio */ + cpio->option_follow_links = 1; + break; + case 'l': /* POSIX 1997 */ + cpio->option_link = 1; + break; + case 'm': /* POSIX 1997 */ + cpio->extract_flags |= ARCHIVE_EXTRACT_TIME; + break; + case 'O': /* GNU cpio */ + cpio->filename = optarg; + break; + case 'o': /* POSIX 1997 */ + cpio->mode = opt; + break; + case 'p': /* POSIX 1997 */ + cpio->mode = opt; + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT; + break; + case OPTION_QUIET: /* GNU cpio */ + cpio->quiet = 1; + break; + case 'R': /* GNU cpio, also --owner */ + if (owner_parse(optarg, &uid, &gid)) + usage(); + if (uid != -1) + cpio->uid_override = uid; + if (gid != -1) + cpio->gid_override = gid; + break; + case 'r': /* POSIX 1997 */ + cpio->option_rename = 1; + break; + case 't': /* POSIX 1997 */ + cpio->option_list = 1; + break; + case 'u': /* POSIX 1997 */ + cpio->extract_flags + &= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + break; + case 'v': /* POSIX 1997 */ + cpio->verbose++; + break; + case OPTION_VERSION: /* GNU convention */ + version(); + break; +#if 0 + /* + * cpio_getopt() handles -W specially, so it's not + * available here. + */ + case 'W': /* Obscure, but useful GNU convention. */ + break; +#endif + case 'y': /* tar convention */ + cpio->compress = opt; + break; + case 'Z': /* tar convention */ + cpio->compress = opt; + break; + case 'z': /* tar convention */ + cpio->compress = opt; + break; + default: + usage(); + } + } + + /* TODO: Sanity-check args, error out on nonsensical combinations. */ + + cpio->argc -= optind; + cpio->argv += optind; + + switch (cpio->mode) { + case 'o': + mode_out(cpio); + break; + case 'i': + while (*cpio->argv != NULL) { + include(cpio, *cpio->argv); + --cpio->argc; + ++cpio->argv; + } + if (cpio->option_list) + mode_list(cpio); + else + mode_in(cpio); + break; + case 'p': + if (*cpio->argv == NULL || **cpio->argv == '\0') + cpio_errc(1, 0, + "-p mode requires a target directory"); + mode_pass(cpio, *cpio->argv); + break; + default: + cpio_errc(1, 0, + "Must specify at least one of -i, -o, or -p"); + } + + return (0); +} + +void +usage(void) +{ + const char *p; + + p = cpio_progname; + + fprintf(stderr, "Brief Usage:\n"); + fprintf(stderr, " List: %s -it < archive\n", p); + fprintf(stderr, " Extract: %s -i < archive\n", p); + fprintf(stderr, " Create: %s -o < filenames > archive\n", p); +#ifdef HAVE_GETOPT_LONG + fprintf(stderr, " Help: %s --help\n", p); +#else + fprintf(stderr, " Help: %s -h\n", p); +#endif + exit(1); +} + +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\n" + "Create: %p -o [options] < [list of files] > [archive]\n" + " -z, -y Compress archive with gzip/bzip2\n" + " --format {odc|newc|ustar} Select archive format\n" + "List: %p -it < [archive]\n" + "Extract: %p -i [options] < [archive]\n"; + + +/* + * Note that the word 'bsdcpio' will always appear in the first line + * of output. + * + * In particular, /bin/sh scripts that need to test for the presence + * of bsdcpio can use the following template: + * + * if (cpio --help 2>&1 | grep bsdcpio >/dev/null 2>&1 ) then \ + * echo bsdcpio; else echo not bsdcpio; fi + */ +static void +long_help(void) +{ + const char *prog; + const char *p; + + prog = cpio_progname; + + fflush(stderr); + + p = (strcmp(prog,"bsdcpio") != 0) ? "(bsdcpio)" : ""; + printf("%s%s: manipulate archive files\n", prog, p); + + for (p = long_help_msg; *p != '\0'; p++) { + if (*p == '%') { + if (p[1] == 'p') { + fputs(prog, stdout); + p++; + } else + putchar('%'); + } else + putchar(*p); + } + version(); +} + +static void +version(void) +{ + fprintf(stdout,"bsdcpio %s -- %s\n", + BSDCPIO_VERSION_STRING, + archive_version()); + exit(0); +} + +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."); + cpio->archive = archive_write_new(); + if (cpio->archive == NULL) + cpio_errc(1, 0, "Failed to allocate archive object"); + switch (cpio->compress) { + case 'j': case 'y': + archive_write_set_compression_bzip2(cpio->archive); + break; + case 'z': + archive_write_set_compression_gzip(cpio->archive); + break; + case 'Z': + archive_write_set_compression_compress(cpio->archive); + break; + default: + archive_write_set_compression_none(cpio->archive); + break; + } + r = archive_write_set_format_by_name(cpio->archive, cpio->format); + if (r != ARCHIVE_OK) + cpio_errc(1, 0, 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)); + + 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) + file_to_archive(cpio, p); + process_lines_free(lr); + + /* + * The hardlink detection may have queued up a couple of entries + * that can now be flushed. + */ + entry = NULL; + archive_entry_linkify(cpio->linkresolver, &entry, &spare); + while (entry != NULL) { + entry_to_archive(cpio, entry); + archive_entry_free(entry); + entry = NULL; + archive_entry_linkify(cpio->linkresolver, &entry, &spare); + } + + r = archive_write_close(cpio->archive); + if (r != ARCHIVE_OK) + cpio_errc(1, 0, archive_error_string(cpio->archive)); + + if (!cpio->quiet) { + blocks = (archive_position_uncompressed(cpio->archive) + 511) + / 512; + fprintf(stderr, "%lu %s\n", blocks, + blocks == 1 ? "block" : "blocks"); + } + archive_write_finish(cpio->archive); +} + +/* + * This is used by both out mode (to copy objects from disk into + * an archive) and pass mode (to copy objects from disk to + * an archive_write_disk "archive"). + */ +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; + int lnklen; + int r; + + /* + * Create an archive_entry describing the source file. + */ + entry = archive_entry_new(); + if (entry == NULL) + cpio_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); + } + + if (cpio->uid_override >= 0) + st.st_uid = cpio->uid_override; + if (cpio->gid_override >= 0) + st.st_gid = cpio->uid_override; + archive_entry_copy_stat(entry, &st); + + /* 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); + } + + /* + * Generate a destination path for this entry. + * "destination path" is the name to which it will be copied in + * pass mode or the name that will go into the archive in + * output mode. + */ + destpath = srcpath; + if (cpio->destdir) { + len = strlen(cpio->destdir) + strlen(srcpath) + 8; + if (len >= cpio->pass_destpath_alloc) { + while (len >= cpio->pass_destpath_alloc) { + cpio->pass_destpath_alloc += 512; + cpio->pass_destpath_alloc *= 2; + } + free(cpio->pass_destpath); + cpio->pass_destpath = malloc(cpio->pass_destpath_alloc); + if (cpio->pass_destpath == NULL) + cpio_errc(1, ENOMEM, + "Can't allocate path buffer"); + } + strcpy(cpio->pass_destpath, cpio->destdir); + p = srcpath; + while (p[0] == '/') + ++p; + strcat(cpio->pass_destpath, p); + destpath = cpio->pass_destpath; + } + if (cpio->option_rename) + destpath = cpio_rename(destpath); + if (destpath == NULL) + return (0); + archive_entry_copy_pathname(entry, destpath); + + /* + * If we're trying to preserve hardlinks, match them here. + */ + spare = NULL; + if (cpio->linkresolver != NULL + && !S_ISDIR(st.st_mode)) { + 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); + } + return (r); +} + +static int +entry_to_archive(struct cpio *cpio, struct archive_entry *entry) +{ + const char *destpath = archive_entry_pathname(entry); + const char *srcpath = archive_entry_sourcepath(entry); + int fd = -1; + ssize_t bytes_read; + int r; + + /* Print out the destination name to the user. */ + if (cpio->verbose) + fprintf(stderr,"%s", destpath); + + /* + * Option_link only makes sense in pass mode and for + * regular files. Also note: if a link operation fails + * because of cross-device restrictions, we'll fall back + * to copy mode for that entry. + * + * TODO: Test other cpio implementations to see if they + * hard-link anything other than regular files here. + */ + if (cpio->option_link + && archive_entry_filetype(entry) == AE_IFREG) + { + struct archive_entry *t; + /* 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"); + /* Note: link(2) doesn't create parent directories, + * so we use archive_write_header() instead as a + * convenience. */ + archive_entry_set_hardlink(t, srcpath); + /* This is a straight link that carries no data. */ + archive_entry_set_size(t, 0); + 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)); + 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"); + } else +#endif + return (0); + } + + /* + * Make sure we can open the file (if necessary) before + * trying to write the header. + */ + if (archive_entry_filetype(entry) == AE_IFREG) { + if (archive_entry_size(entry) > 0) { + fd = open(srcpath, O_RDONLY); + if (fd < 0) { + cpio_warnc(errno, + "%s: could not open file", srcpath); + goto cleanup; + } + } + } else { + archive_entry_set_size(entry, 0); + } + + r = archive_write_header(cpio->archive, entry); + + if (r != ARCHIVE_OK) + cpio_warnc(archive_errno(cpio->archive), + "%s: %s", + destpath, + archive_error_string(cpio->archive)); + + if (r == ARCHIVE_FATAL) + exit(1); + + if (r >= ARCHIVE_WARN && fd >= 0) { + bytes_read = read(fd, cpio->buff, cpio->buff_size); + while (bytes_read > 0) { + 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)); + if (r < bytes_read) { + cpio_warnc(0, + "Truncated write; file may have grown while being archived."); + } + bytes_read = read(fd, cpio->buff, cpio->buff_size); + } + } + + restore_time(cpio, entry, srcpath, fd); + +cleanup: + if (cpio->verbose) + fprintf(stderr,"\n"); + if (fd >= 0) + close(fd); + return (0); +} + +static void +restore_time(struct cpio *cpio, struct archive_entry *entry, + const char *name, int fd) +{ +#ifndef HAVE_UTIMES + static int warned = 0; + + (void)cpio; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)name; /* UNUSED */ + (void)fd; /* UNUSED */ + + if (!warned) + cpio_warnc(0, "Can't restore access times on this platform"); + warned = 1; + return; +#else + struct timeval times[2]; + + if (!cpio->option_atime_restore) + return; + + times[1].tv_sec = archive_entry_mtime(entry); + times[1].tv_usec = archive_entry_mtime_nsec(entry) / 1000; + + times[0].tv_sec = archive_entry_atime(entry); + times[0].tv_usec = archive_entry_atime_nsec(entry) / 1000; + +#ifdef HAVE_FUTIMES + if (fd >= 0 && futimes(fd, times) == 0) + return; +#endif + +#ifdef HAVE_LUTIMES + if (lutimes(name, times) != 0) +#else + if (!S_ISLNK(archive_entry_mode(entry)) && utimes(name, times) != 0) +#endif + cpio_warnc(errno, "Can't update time for %s", name); +#endif +} + + +static void +mode_in(struct cpio *cpio) +{ + struct archive *a; + 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"); + r = archive_write_disk_set_options(ext, cpio->extract_flags); + if (r != ARCHIVE_OK) + cpio_errc(1, 0, archive_error_string(ext)); + a = archive_read_new(); + if (a == NULL) + cpio_errc(1, 0, "Couldn't allocate archive object"); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + + if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block)) + cpio_errc(1, archive_errno(a), + 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)); + } + if (excluded(cpio, archive_entry_pathname(entry))) + continue; + if (cpio->option_rename) { + destpath = cpio_rename(archive_entry_pathname(entry)); + archive_entry_set_pathname(entry, destpath); + } else + destpath = archive_entry_pathname(entry); + if (destpath == NULL) + continue; + if (cpio->verbose) + fprintf(stdout, "%s\n", destpath); + if (cpio->uid_override >= 0) + archive_entry_set_uid(entry, cpio->uid_override); + if (cpio->gid_override >= 0) + archive_entry_set_gid(entry, cpio->gid_override); + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) { + fprintf(stderr, "%s: %s\n", + archive_entry_pathname(entry), + archive_error_string(ext)); + } else if (archive_entry_size(entry) > 0) { + r = copy_data(a, ext); + } + } + r = archive_read_close(a); + if (r != ARCHIVE_OK) + cpio_errc(1, 0, archive_error_string(a)); + r = archive_write_close(ext); + if (r != ARCHIVE_OK) + cpio_errc(1, 0, archive_error_string(ext)); + if (!cpio->quiet) { + blocks = (archive_position_uncompressed(a) + 511) + / 512; + fprintf(stderr, "%lu %s\n", blocks, + blocks == 1 ? "block" : "blocks"); + } + archive_read_finish(a); + archive_write_finish(ext); + exit(0); +} + +static int +copy_data(struct archive *ar, struct archive *aw) +{ + int r; + size_t size; + const void *block; + off_t offset; + + for (;;) { + r = archive_read_data_block(ar, &block, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r != ARCHIVE_OK) { + cpio_warnc(archive_errno(ar), + "%s", archive_error_string(ar)); + return (r); + } + r = archive_write_data_block(aw, block, size, offset); + if (r != ARCHIVE_OK) { + cpio_warnc(archive_errno(aw), + archive_error_string(aw)); + return (r); + } + } +} + +static void +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"); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + + if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block)) + cpio_errc(1, archive_errno(a), + 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)); + } + if (excluded(cpio, archive_entry_pathname(entry))) + continue; + if (cpio->verbose) { + /* TODO: uname/gname lookups */ + /* TODO: Clean this up. */ + fprintf(stdout, + "%s%3d %8s%8s " CPIO_FILESIZE_PRINTF " %s\n", + archive_entry_strmode(entry), + archive_entry_nlink(entry), + archive_entry_uname(entry), + archive_entry_gname(entry), + (CPIO_FILESIZE_TYPE)archive_entry_size(entry), + archive_entry_pathname(entry)); + } else + fprintf(stdout, "%s\n", archive_entry_pathname(entry)); + } + r = archive_read_close(a); + if (r != ARCHIVE_OK) + cpio_errc(1, 0, archive_error_string(a)); + if (!cpio->quiet) { + blocks = (archive_position_uncompressed(a) + 511) + / 512; + fprintf(stderr, "%lu %s\n", blocks, + blocks == 1 ? "block" : "blocks"); + } + archive_read_finish(a); + exit(0); +} + +static void +mode_pass(struct cpio *cpio, const char *destdir) +{ + struct line_reader *lr; + const char *p; + int r; + + /* Ensure target dir has a trailing '/' to simplify path surgery. */ + cpio->destdir = malloc(strlen(destdir) + 8); + strcpy(cpio->destdir, destdir); + if (destdir[strlen(destdir) - 1] != '/') + strcat(cpio->destdir, "/"); + + cpio->archive = archive_write_disk_new(); + if (cpio->archive == NULL) + cpio_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)); + 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) + file_to_archive(cpio, p); + process_lines_free(lr); + + archive_entry_linkresolver_free(cpio->linkresolver); + r = archive_write_close(cpio->archive); + if (r != ARCHIVE_OK) + cpio_errc(1, 0, archive_error_string(cpio->archive)); + archive_write_finish(cpio->archive); +} + +/* + * Prompt for a new name for this entry. Returns a pointer to the + * new name or NULL if the entry should not be copied. This + * implements the semantics defined in POSIX.1-1996, which specifies + * that an input of '.' means the name should be unchanged. GNU cpio + * treats '.' as a literal new name. + */ +static const char * +cpio_rename(const char *name) +{ + static char buff[1024]; + FILE *t; + char *p, *ret; + + t = fopen("/dev/tty", "r+"); + if (t == NULL) + return (name); + fprintf(t, "%s (Enter/./(new name))? ", name); + fflush(t); + + p = fgets(buff, sizeof(buff), t); + fclose(t); + if (p == NULL) + /* End-of-file is a blank line. */ + return (NULL); + + while (*p == ' ' || *p == '\t') + ++p; + if (*p == '\n' || *p == '\0') + /* Empty line. */ + return (NULL); + if (*p == '.' && p[1] == '\n') + /* Single period preserves original name. */ + return (name); + ret = p; + /* Trim the final newline. */ + while (*p != '\0' && *p != '\n') + ++p; + /* Overwrite the final \n with a null character. */ + *p = '\0'; + 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); +} diff --git a/contrib/libarchive-2/cpio/cpio.h b/contrib/libarchive-2/cpio/cpio.h new file mode 100644 index 0000000000..3afd952030 --- /dev/null +++ b/contrib/libarchive-2/cpio/cpio.h @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2003-2007 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. + * 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: src/usr.bin/cpio/cpio.h,v 1.2 2008/06/21 02:20:20 kientzle Exp $ + */ + +#ifndef CPIO_H_INCLUDED +#define CPIO_H_INCLUDED + +#include "cpio_platform.h" +#include + +#define DEFAULT_BYTES_PER_BLOCK (20*512) + +/* + * The internal state for the "cpio" program. + * + * Keeping all of the state in a structure like this simplifies memory + * leak testing (at exit, anything left on the heap is suspect). A + * pointer to this structure is passed to most cpio internal + * functions. + */ +struct cpio { + /* Options */ + char *filename; + char mode; /* -i -o -p */ + char compress; /* -j, -y, or -z */ + const char *format; /* -H format */ + int bytes_per_block; /* -b block_size */ + int verbose; /* -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 */ + int option_rename; /* -r */ + char *destdir; + size_t pass_destpath_alloc; + char *pass_destpath; + int uid_override; + int gid_override; + + /* If >= 0, then close this when done. */ + int fd; + + /* Miscellaneous state information */ + struct archive *archive; + int argc; + char **argv; + int return_value; /* Value returned by main() */ + struct archive_entry_linkresolver *linkresolver; + + /* Work data. */ + struct matching *matching; + char *buff; + 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, ...); +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. */ +enum { + OPTION_INSECURE = 1, + 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/contrib/libarchive-2/cpio/cpio_platform.h b/contrib/libarchive-2/cpio/cpio_platform.h new file mode 100644 index 0000000000..3145198298 --- /dev/null +++ b/contrib/libarchive-2/cpio/cpio_platform.h @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2003-2007 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. + * 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$ + */ + +/* + * This header is the first thing included in any of the cpio + * source files. As far as possible, platform-specific issues should + * be dealt with here and not within individual source files. + */ + +#ifndef CPIO_PLATFORM_H_INCLUDED +#define CPIO_PLATFORM_H_INCLUDED + +#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 */ + +/* No non-FreeBSD platform will have __FBSDID, so just define it here. */ +#ifdef __FreeBSD__ +#include /* For __FBSDID */ +#else +/* Just leaving this macro replacement empty leads to a dangling semicolon. */ +#define __FBSDID(a) struct _undefined_hack +#endif + +#ifdef HAVE_LIBARCHIVE +/* If we're using the platform libarchive, include system headers. */ +#include +#include +#else +/* Otherwise, include user headers. */ +#include "archive.h" +#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 + +#endif /* !CPIO_PLATFORM_H_INCLUDED */ diff --git a/contrib/libarchive-2/libarchive/archive_entry_strmode.c b/contrib/libarchive-2/cpio/err.c similarity index 51% copy from contrib/libarchive-2/libarchive/archive_entry_strmode.c copy to contrib/libarchive-2/cpio/err.c index cfe6ae33ba..ad9c0e193e 100644 --- a/contrib/libarchive-2/libarchive/archive_entry_strmode.c +++ b/contrib/libarchive-2/cpio/err.c @@ -6,7 +6,8 @@ * 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. + * 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. @@ -23,60 +24,50 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.3 2008/05/23 04:57:28 cperciva Exp $"); -#ifdef HAVE_SYS_STAT_H -#include +#include "cpio_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STDARG_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include #endif #ifdef HAVE_STRING_H #include #endif -#include "archive_entry.h" -#include "archive_entry_private.h" +#include "cpio.h" -const char * -archive_entry_strmode(struct archive_entry *entry) +static void +cpio_vwarnc(int code, const char *fmt, va_list ap) { - static const mode_t permbits[] = - { 0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001 }; - char *bp = entry->strmode; - mode_t mode; - int i; - - /* Fill in a default string, then selectively override. */ - strcpy(bp, "?rwxrwxrwx "); + fprintf(stderr, "%s: ", cpio_progname); + vfprintf(stderr, fmt, ap); + if (code != 0) + fprintf(stderr, ": %s", strerror(code)); + fprintf(stderr, "\n"); +} - mode = archive_entry_mode(entry); - switch (archive_entry_filetype(entry)) { - case AE_IFREG: bp[0] = '-'; break; - case AE_IFBLK: bp[0] = 'b'; break; - case AE_IFCHR: bp[0] = 'c'; break; - case AE_IFDIR: bp[0] = 'd'; break; - case AE_IFLNK: bp[0] = 'l'; break; - case AE_IFSOCK: bp[0] = 's'; break; - case AE_IFIFO: bp[0] = 'p'; break; - } +void +cpio_warnc(int code, const char *fmt, ...) +{ + va_list ap; - for (i = 0; i < 9; i++) - if (!(mode & permbits[i])) - bp[i+1] = '-'; + va_start(ap, fmt); + cpio_vwarnc(code, fmt, ap); + va_end(ap); +} - if (mode & S_ISUID) { - if (mode & 0100) bp[3] = 's'; - else bp[3] = 'S'; - } - if (mode & S_ISGID) { - if (mode & 0010) bp[6] = 's'; - else bp[6] = 'S'; - } - if (mode & S_ISVTX) { - if (mode & 0001) bp[9] = 't'; - else bp[9] = 'T'; - } - if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)) - bp[10] = '+'; +void +cpio_errc(int eval, int code, const char *fmt, ...) +{ + va_list ap; - return (bp); + va_start(ap, fmt); + cpio_vwarnc(code, fmt, ap); + va_end(ap); + exit(eval); } diff --git a/contrib/libarchive-2/cpio/matching.c b/contrib/libarchive-2/cpio/matching.c new file mode 100644 index 0000000000..3e4ddc3bfd --- /dev/null +++ b/contrib/libarchive-2/cpio/matching.c @@ -0,0 +1,259 @@ +/*- + * Copyright (c) 2003-2007 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. + * 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: src/usr.bin/cpio/matching.c,v 1.2 2008/06/21 02:20:20 kientzle Exp $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "matching.h" +#include "pathmatch.h" + +struct match { + struct match *next; + int matches; + char pattern[1]; +}; + +struct matching { + struct match *exclusions; + int exclusions_count; + struct match *inclusions; + int inclusions_count; + int inclusions_unmatched_count; +}; + +static void add_pattern(struct match **list, const char *pattern); +static void initialize_matching(struct cpio *); +static int match_exclusion(struct match *, const char *pathname); +static int match_inclusion(struct match *, const char *pathname); + +/* + * The matching logic here needs to be re-thought. I started out to + * try to mimic gtar's matching logic, but it's not entirely + * consistent. In particular 'tar -t' and 'tar -x' interpret patterns + * on the command line as anchored, but --exclude doesn't. + */ + +/* + * Utility functions to manage exclusion/inclusion patterns + */ + +int +exclude(struct cpio *cpio, const char *pattern) +{ + struct matching *matching; + + if (cpio->matching == NULL) + initialize_matching(cpio); + matching = cpio->matching; + add_pattern(&(matching->exclusions), pattern); + 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); +} + +int +include_from_file(struct cpio *cpio, const char *pathname) +{ + 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) + ret = -1; + process_lines_free(lr); + return (ret); +} + +static void +add_pattern(struct match **list, const char *pattern) +{ + struct match *match; + + match = malloc(sizeof(*match) + strlen(pattern) + 1); + if (match == NULL) + cpio_errc(1, errno, "Out of memory"); + if (pattern[0] == '/') + pattern++; + strcpy(match->pattern, pattern); + /* Both "foo/" and "foo" should match "foo/bar". */ + if (match->pattern[strlen(match->pattern)-1] == '/') + match->pattern[strlen(match->pattern)-1] = '\0'; + match->next = *list; + *list = match; + match->matches = 0; +} + + +int +excluded(struct cpio *cpio, const char *pathname) +{ + struct matching *matching; + struct match *match; + struct match *matched; + + matching = cpio->matching; + if (matching == NULL) + return (0); + + /* Exclusions take priority */ + for (match = matching->exclusions; match != NULL; match = match->next){ + if (match_exclusion(match, pathname)) + return (1); + } + + /* Then check for inclusions */ + matched = NULL; + for (match = matching->inclusions; match != NULL; match = match->next){ + if (match_inclusion(match, pathname)) { + /* + * If this pattern has never been matched, + * then we're done. + */ + if (match->matches == 0) { + match->matches++; + matching->inclusions_unmatched_count++; + return (0); + } + /* + * Otherwise, remember the match but keep checking + * in case we can tick off an unmatched pattern. + */ + matched = match; + } + } + /* + * We didn't find a pattern that had never been matched, but + * we did find a match, so count it and exit. + */ + if (matched != NULL) { + matched->matches++; + return (0); + } + + /* If there were inclusions, default is to exclude. */ + if (matching->inclusions != NULL) + return (1); + + /* No explicit inclusions, default is to match. */ + return (0); +} + +/* + * This is a little odd, but it matches the default behavior of + * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar' + * + */ +int +match_exclusion(struct match *match, const char *pathname) +{ + return (pathmatch(match->pattern, + pathname, + PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); +} + +/* + * Again, mimic gtar: inclusions are always anchored (have to match + * the beginning of the path) even though exclusions are not anchored. + */ +int +match_inclusion(struct match *match, const char *pathname) +{ + return (pathmatch(match->pattern, pathname, 0)); +} + +void +cleanup_exclusions(struct cpio *cpio) +{ + 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); + } +} + +static void +initialize_matching(struct cpio *cpio) +{ + cpio->matching = malloc(sizeof(*cpio->matching)); + if (cpio->matching == NULL) + cpio_errc(1, errno, "No memory"); + memset(cpio->matching, 0, sizeof(*cpio->matching)); +} + +int +unmatched_inclusions(struct cpio *cpio) +{ + struct matching *matching; + + matching = cpio->matching; + if (matching == NULL) + return (0); + return (matching->inclusions_unmatched_count); +} diff --git a/contrib/libarchive-2/cpio/matching.h b/contrib/libarchive-2/cpio/matching.h new file mode 100644 index 0000000000..a66bc86bc7 --- /dev/null +++ b/contrib/libarchive-2/cpio/matching.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2003-2007 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. + * + * $FreeBSD$ + */ + +#ifndef MATCHING_H +#define MATCHING_H + +#include "cpio.h" + +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); + +#endif diff --git a/contrib/libarchive-2/cpio/pathmatch.c b/contrib/libarchive-2/cpio/pathmatch.c new file mode 100644 index 0000000000..d33bd34389 --- /dev/null +++ b/contrib/libarchive-2/cpio/pathmatch.c @@ -0,0 +1,250 @@ +/*- + * Copyright (c) 2003-2007 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$"); + +#ifdef HAVE_STRING_H +#include +#endif + +#include "pathmatch.h" + +/* + * Check whether a character 'c' is matched by a list specification [...]: + * * Leading '!' negates the class. + * * - is a range of characters + * * \ removes any special meaning for + * + * Some interesting boundary cases: + * a-d-e is one range (a-d) followed by two single characters - and e. + * \a-\d is same as a-d + * a\-d is three single characters: a, d, - + * Trailing - is not special (so [a-] is two characters a and -). + * Initial - is not special ([a-] is same as [-a] is same as [\\-a]) + * This function never sees a trailing \. + * [] always fails + * [!] always succeeds + */ +static int +pm_list(const char *start, const char *end, const char c, int flags) +{ + const char *p = start; + char rangeStart = '\0', nextRangeStart; + int match = 1, nomatch = 0; + + /* This will be used soon... */ + (void)flags; /* UNUSED */ + + /* If this is a negated class, return success for nomatch. */ + if (*p == '!' && p < end) { + match = 0; + nomatch = 1; + ++p; + } + + while (p < end) { + nextRangeStart = '\0'; + switch (*p) { + case '-': + /* Trailing or initial '-' is not special. */ + if ((rangeStart == '\0') || (p == end - 1)) { + if (*p == c) + return (match); + } else { + char rangeEnd = *++p; + if (rangeEnd == '\\') + rangeEnd = *++p; + if ((rangeStart <= c) && (c <= rangeEnd)) + return (match); + } + break; + case '\\': + ++p; + /* Fall through */ + default: + if (*p == c) + return (match); + nextRangeStart = *p; /* Possible start of range. */ + } + rangeStart = nextRangeStart; + ++p; + } + return (nomatch); +} + +/* + * If s is pointing to "./", ".//", "./././" or the like, skip it. + */ +static const char * +pm_slashskip(const char *s) { + while (*s == '.' || *s == '/') { + if (s[0] != '/' && s[1] != '/') + break; + ++s; + } + return (s); +} + +static int +pm(const char *p, const char *s, int flags) +{ + const char *end; + + /* + * Ignore leading './', './/', '././', etc. + */ + if (s[0] == '.' && s[1] == '/') + s = pm_slashskip(s + 1); + if (p[0] == '.' && p[1] == '/') + p = pm_slashskip(p + 1); + + for (;;) { + switch (*p) { + case '\0': + if (s[0] == '/') { + if (flags & PATHMATCH_NO_ANCHOR_END) + return (1); + /* "dir" == "dir/" == "dir/." */ + s = pm_slashskip(s); + if (s[0] == '.' && s[1] == '\0') + return (1); + } + return (*s == '\0'); + break; + case '?': + /* ? always succeds, unless we hit end of 's' */ + if (*s == '\0') + return (0); + break; + case '*': + /* "*" == "**" == "***" ... */ + while (*p == '*') + ++p; + /* Trailing '*' always succeeds. */ + if (*p == '\0') + return (1); + while (*s) { + if (pathmatch(p, s, flags)) + return (1); + ++s; + } + return (0); + break; + case '[': + /* + * Find the end of the [...] character class, + * ignoring \] that might occur within the class. + */ + end = p + 1; + while (*end != '\0' && *end != ']') { + if (*end == '\\' && end[1] != '\0') + ++end; + ++end; + } + if (*end == ']') { + /* We found [...], try to match it. */ + if (!pm_list(p + 1, end, *s, flags)) + return (0); + p = end; /* Jump to trailing ']' char. */ + break; + } else + /* No final ']', so just match '['. */ + if (*p != *s) + return (0); + break; + default: + if (*p == *s) + break; + if ((*s == '\0') && (*p == '/')) { + p = pm_slashskip(p); + if (*p == '\0') + return (1); + if (p[0] == '.' && p[1] == '\0') + return (1); + return (0); + } + return (0); + break; + case '\\': + /* Trailing '\\' matches itself. */ + if (p[1] == '\0') { + if (*s != '\\') + return (0); + } else { + ++p; + if (*p != *s) + return (0); + } + break; + } + /* + * TODO: pattern of "\/\.\/" should not match plain "/", + * it should only match explicit "/./". + */ + if (*p == '/') + p = pm_slashskip(p); + else + ++p; + if (*s == '/') + s = pm_slashskip(s); + else + ++s; + } +} + +/* Main entry point. */ +int +pathmatch(const char *p, const char *s, int flags) +{ + /* Empty pattern only matches the empty string. */ + if (p == NULL || *p == '\0') + return (s == NULL || *s == '\0'); + + /* Leading '^' anchors the start of the pattern. */ + if (*p == '^') { + ++p; + flags &= ~PATHMATCH_NO_ANCHOR_START; + } + + /* Certain patterns anchor implicitly. */ + if (*p == '*' || *p == '/') + return (pm(p, s, flags)); + + /* If start is unanchored, try to match start of each path element. */ + if (flags & PATHMATCH_NO_ANCHOR_START) { + for ( ; p != NULL; p = strchr(p, '/')) { + if (*p == '/') + p++; + if (pm(p, s, flags)) + return (1); + } + return (0); + } + + /* Default: Match from beginning. */ + return (pm(p, s, flags)); +} diff --git a/contrib/libarchive-2/cpio/pathmatch.h b/contrib/libarchive-2/cpio/pathmatch.h new file mode 100644 index 0000000000..990fa1fa1e --- /dev/null +++ b/contrib/libarchive-2/cpio/pathmatch.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2003-2007 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. + * + * $FreeBSD$ + */ + +#ifndef PATHMATCH_H +#define PATHMATCH_H + +#define PATHMATCH_NO_ANCHOR_START 1 +#define PATHMATCH_NO_ANCHOR_END 2 + +int pathmatch(const char *p, const char *s, int flags); + +#endif diff --git a/contrib/libarchive-2/libarchive/archive.h b/contrib/libarchive-2/libarchive/archive.h index 6bfe81eb24..3f9f6e1cf6 100644 --- a/contrib/libarchive-2/libarchive/archive.h +++ b/contrib/libarchive-2/libarchive/archive.h @@ -22,7 +22,7 @@ * (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: src/lib/libarchive/archive.h.in,v 1.49 2008/03/14 22:19:50 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $ */ #ifndef ARCHIVE_H_INCLUDED @@ -112,13 +112,13 @@ extern "C" { * (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000) * #endif */ -#define ARCHIVE_VERSION_NUMBER 2005004 +#define ARCHIVE_VERSION_NUMBER 2005005 __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_STRING "libarchive 2.5.4b" +#define ARCHIVE_VERSION_STRING "libarchive 2.5.5" __LA_DECL const char * archive_version_string(void); #if ARCHIVE_VERSION_NUMBER < 3000000 diff --git a/contrib/libarchive-2/libarchive/archive_endian.h b/contrib/libarchive-2/libarchive/archive_endian.h index 61af4161c3..550be16402 100644 --- a/contrib/libarchive-2/libarchive/archive_endian.h +++ b/contrib/libarchive-2/libarchive/archive_endian.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libarchive/archive_endian.h,v 1.2 2008/02/26 07:17:47 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive_endian.h,v 1.3 2008/05/26 17:00:22 kientzle Exp $ * * Borrowed from FreeBSD's */ diff --git a/contrib/libarchive-2/libarchive/archive_entry.3 b/contrib/libarchive-2/libarchive/archive_entry.3 index e2d4ab1177..9ceb18b7aa 100644 --- a/contrib/libarchive-2/libarchive/archive_entry.3 +++ b/contrib/libarchive-2/libarchive/archive_entry.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.17 2008/03/14 23:00:53 kientzle Exp $ +.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $ .\" .Dd May 12, 2008 .Dt archive_entry 3 diff --git a/contrib/libarchive-2/libarchive/archive_entry.c b/contrib/libarchive-2/libarchive/archive_entry.c index 210685af2b..69921c309f 100644 --- a/contrib/libarchive-2/libarchive/archive_entry.c +++ b/contrib/libarchive-2/libarchive/archive_entry.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry.c,v 1.51 2008/03/14 23:19:46 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry.c,v 1.52 2008/05/26 17:00:22 kientzle Exp $"); #ifdef HAVE_SYS_STAT_H #include diff --git a/contrib/libarchive-2/libarchive/archive_entry.h b/contrib/libarchive-2/libarchive/archive_entry.h index f8601b9ee2..ee96c56a79 100644 --- a/contrib/libarchive-2/libarchive/archive_entry.h +++ b/contrib/libarchive-2/libarchive/archive_entry.h @@ -22,7 +22,7 @@ * (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: src/lib/libarchive/archive_entry.h,v 1.26 2008/03/14 23:00:53 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive_entry.h,v 1.27 2008/05/26 17:00:22 kientzle Exp $ */ #ifndef ARCHIVE_ENTRY_H_INCLUDED diff --git a/contrib/libarchive-2/libarchive/archive_entry_link_resolver.c b/contrib/libarchive-2/libarchive/archive_entry_link_resolver.c index c0770c239d..4deee260d4 100644 --- a/contrib/libarchive-2/libarchive/archive_entry_link_resolver.c +++ b/contrib/libarchive-2/libarchive/archive_entry_link_resolver.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_link_resolver.c,v 1.1 2007/12/30 04:58:21 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_link_resolver.c,v 1.3 2008/06/15 04:31:43 kientzle Exp $"); #ifdef HAVE_SYS_STAT_H #include @@ -181,6 +181,9 @@ archive_entry_linkify(struct archive_entry_linkresolver *res, /* If it has only one link, then we're done. */ if (archive_entry_nlink(*e) == 1) return; + /* Directories never have hardlinks. */ + if (archive_entry_filetype(*e) == AE_IFDIR) + return; switch (res->strategy) { case ARCHIVE_ENTRY_LINKIFY_LIKE_TAR: diff --git a/contrib/libarchive-2/libarchive/archive_entry_private.h b/contrib/libarchive-2/libarchive/archive_entry_private.h index f893fb982a..0289290b19 100644 --- a/contrib/libarchive-2/libarchive/archive_entry_private.h +++ b/contrib/libarchive-2/libarchive/archive_entry_private.h @@ -22,7 +22,7 @@ * (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: src/lib/libarchive/archive_entry_private.h,v 1.3 2008/03/31 06:24:39 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive_entry_private.h,v 1.4 2008/05/26 17:00:22 kientzle Exp $ */ #ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED diff --git a/contrib/libarchive-2/libarchive/archive_entry_strmode.c b/contrib/libarchive-2/libarchive/archive_entry_strmode.c index cfe6ae33ba..16cb3f7bb3 100644 --- a/contrib/libarchive-2/libarchive/archive_entry_strmode.c +++ b/contrib/libarchive-2/libarchive/archive_entry_strmode.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.3 2008/05/23 04:57:28 cperciva Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.4 2008/06/15 05:14:01 kientzle Exp $"); #ifdef HAVE_SYS_STAT_H #include @@ -57,6 +57,11 @@ archive_entry_strmode(struct archive_entry *entry) case AE_IFLNK: bp[0] = 'l'; break; case AE_IFSOCK: bp[0] = 's'; break; case AE_IFIFO: bp[0] = 'p'; break; + default: + if (archive_entry_hardlink(entry) != NULL) { + bp[0] = 'h'; + break; + } } for (i = 0; i < 9; i++) diff --git a/contrib/libarchive-2/libarchive/archive_platform.h b/contrib/libarchive-2/libarchive/archive_platform.h index 41fd4e549d..99dfacc50f 100644 --- a/contrib/libarchive-2/libarchive/archive_platform.h +++ b/contrib/libarchive-2/libarchive/archive_platform.h @@ -22,7 +22,7 @@ * (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: src/lib/libarchive/archive_platform.h,v 1.29 2008/02/19 06:06:13 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive_platform.h,v 1.30 2008/05/26 17:00:22 kientzle Exp $ */ /* diff --git a/contrib/libarchive-2/libarchive/archive_read.3 b/contrib/libarchive-2/libarchive/archive_read.3 index dbbe1f7f1e..13063d917c 100644 --- a/contrib/libarchive-2/libarchive/archive_read.3 +++ b/contrib/libarchive-2/libarchive/archive_read.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/archive_read.3,v 1.36 2008/03/10 14:45:29 jkoshy Exp $ +.\" $FreeBSD: src/lib/libarchive/archive_read.3,v 1.37 2008/05/26 17:00:22 kientzle Exp $ .\" .Dd August 19, 2006 .Dt archive_read 3 diff --git a/contrib/libarchive-2/libarchive/archive_read_extract.c b/contrib/libarchive-2/libarchive/archive_read_extract.c index ab01f7df3e..e1027995ec 100644 --- a/contrib/libarchive-2/libarchive/archive_read_extract.c +++ b/contrib/libarchive-2/libarchive/archive_read_extract.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.60 2008/01/18 04:53:45 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include diff --git a/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c b/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c index e6397df963..824b0cdeb5 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c @@ -25,7 +25,7 @@ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_bzip2.c,v 1.17 2008/02/19 05:44:59 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_bzip2.c,v 1.18 2008/05/26 17:00:22 kientzle Exp $"); #ifdef HAVE_ERRNO_H #include diff --git a/contrib/libarchive-2/libarchive/archive_read_support_compression_program.c b/contrib/libarchive-2/libarchive/archive_read_support_compression_program.c index 206215c897..4f25d6ed56 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_compression_program.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_compression_program.c @@ -24,11 +24,11 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_program.c,v 1.2 2007/07/20 01:28:50 kientzle Exp $"); - +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_program.c,v 1.4 2008/06/15 10:45:57 kientzle Exp $"); /* This capability is only available on POSIX systems. */ -#if !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) +#if !defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \ + !(defined(HAVE_FORK) || defined(HAVE_VFORK)) /* * On non-Posix systems, allow the program to build, but choke if @@ -177,6 +177,12 @@ restart_read: state->child_in_buf_avail = ret; } + if (state->child_stdin == -1) { + fcntl(state->child_stdout, F_SETFL, 0); + __archive_check_child(state->child_stdin, state->child_stdout); + goto restart_read; + } + do { ret = write(state->child_stdin, state->child_in_buf, state->child_in_buf_avail); @@ -191,7 +197,7 @@ restart_read: goto restart_read; } else if (ret == 0 || (ret == -1 && errno == EPIPE)) { close(state->child_stdin); - state->child_stdout = -1; + state->child_stdin = -1; fcntl(state->child_stdout, F_SETFL, 0); goto restart_read; } else { diff --git a/contrib/libarchive-2/libarchive/archive_read_support_format_ar.c b/contrib/libarchive-2/libarchive/archive_read_support_format_ar.c index 15d7e7cfd7..baf80bd62f 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_format_ar.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_format_ar.c @@ -26,7 +26,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_ar.c,v 1.9 2008/03/12 21:10:26 kaiw Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_ar.c,v 1.10 2008/05/26 17:00:22 kientzle Exp $"); #ifdef HAVE_SYS_STAT_H #include diff --git a/contrib/libarchive-2/libarchive/archive_read_support_format_iso9660.c b/contrib/libarchive-2/libarchive/archive_read_support_format_iso9660.c index e0825a36e1..481220dd47 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_format_iso9660.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_format_iso9660.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1.25 2008/02/19 06:02:01 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_iso9660.c,v 1.26 2008/05/26 17:00:22 kientzle Exp $"); #ifdef HAVE_ERRNO_H #include diff --git a/contrib/libarchive-2/libarchive/archive_read_support_format_mtree.c b/contrib/libarchive-2/libarchive/archive_read_support_format_mtree.c index 72232ed7e0..33597e0de6 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_format_mtree.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_format_mtree.c @@ -25,7 +25,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_mtree.c,v 1.5 2008/05/19 18:06:48 cperciva Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_mtree.c,v 1.9 2008/06/21 19:06:37 kientzle Exp $"); #ifdef HAVE_SYS_STAT_H #include @@ -308,7 +308,7 @@ process_global_unset(struct archive_read *a, size_t len; line += 6; - if ((next = strchr(line, '=')) != NULL) { + if (strchr(line, '=') != NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "/unset shall not contain `='"); return ARCHIVE_FATAL; @@ -663,7 +663,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry, *use_next = 1; } /* Don't hold a non-regular file open. */ - close(mtree->fd); + if (mtree->fd >= 0) + close(mtree->fd); mtree->fd = -1; st = NULL; return r; @@ -759,7 +760,7 @@ parse_device(struct archive *a, struct archive_entry *entry, char *val) } ++comma1; comma2 = strchr(comma1, ','); - if (comma1 == NULL) { + if (comma2 == NULL) { archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, "Malformed device attribute"); return (ARCHIVE_WARN); @@ -1019,7 +1020,7 @@ skip(struct archive_read *a) } /* - * Since parsing octal escapes always makes strings shorter, + * Since parsing backslash sequences always makes strings shorter, * we can always do this conversion in-place. */ static void @@ -1040,13 +1041,57 @@ parse_escapes(char *src, struct mtree_entry *mentry) if (c == '/' && mentry != NULL) mentry->full = 1; if (c == '\\') { - if (src[0] >= '0' && src[0] <= '3' - && src[1] >= '0' && src[1] <= '7' - && src[2] >= '0' && src[2] <= '7') { - c = (src[0] - '0') << 6; - c |= (src[1] - '0') << 3; - c |= (src[2] - '0'); - src += 3; + switch (src[0]) { + case '0': + if (src[1] < '0' || src[1] > '7') { + c = 0; + ++src; + break; + } + /* FALLTHROUGH */ + case '1': + case '2': + case '3': + if (src[1] >= '0' && src[1] <= '7' && + src[2] >= '0' && src[2] <= '7') { + c = (src[0] - '0') << 6; + c |= (src[1] - '0') << 3; + c |= (src[2] - '0'); + src += 3; + } + break; + case 'a': + c = '\a'; + ++src; + break; + case 'b': + c = '\b'; + ++src; + break; + case 'f': + c = '\f'; + ++src; + break; + case 'n': + c = '\n'; + ++src; + break; + case 'r': + c = '\r'; + ++src; + break; + case 's': + c = ' '; + ++src; + break; + case 't': + c = '\t'; + ++src; + break; + case 'v': + c = '\v'; + ++src; + break; } } *dest++ = c; @@ -1189,6 +1234,7 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limi const void *t; const char *s; void *p; + char *u; /* Accumulate line in a line buffer. */ for (;;) { @@ -1221,10 +1267,32 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limi total_size += bytes_read; /* Null terminate. */ mtree->line.s[total_size] = '\0'; - /* If we found '\n', clean up and return. */ - if (p != NULL) { - *start = mtree->line.s; - return (total_size); + /* If we found an unescaped '\n', clean up and return. */ + if (p == NULL) + continue; + for (u = mtree->line.s; *u; ++u) { + if (u[0] == '\n') { + *start = mtree->line.s; + return total_size; + } + if (u[0] == '#') { + if (p == NULL) + break; + *start = mtree->line.s; + return total_size; + } + if (u[0] != '\\') + continue; + if (u[1] == '\\') { + ++u; + continue; + } + if (u[1] == '\n') { + memmove(u, u + 1, + total_size - (u - mtree->line.s) + 1); + --total_size; + continue; + } } } } diff --git a/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c b/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c index 6d7f048a40..0c2f0077c1 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_tar.c,v 1.67 2008/03/15 01:43:58 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_tar.c,v 1.69 2008/05/27 04:46:12 kientzle Exp $"); #ifdef HAVE_ERRNO_H #include @@ -2362,7 +2362,7 @@ url_decode(const char *in) if (out == NULL) return (NULL); for (s = in, d = out; *s != '\0'; ) { - if (*s == '%') { + if (s[0] == '%' && s[1] != '\0' && s[2] != '\0') { /* Try to convert % escape */ int digit1 = tohex(s[1]); int digit2 = tohex(s[2]); diff --git a/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c b/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c index a105297ad4..f04f69bb20 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_zip.c,v 1.22 2008/02/27 06:05:59 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_zip.c,v 1.24 2008/06/15 05:15:53 kientzle Exp $"); #ifdef HAVE_ERRNO_H #include @@ -564,8 +564,8 @@ archive_read_format_zip_read_data(struct archive_read *a, */ r = ARCHIVE_FATAL; } else { - /* We know compressed size; just skip it. */ - archive_read_format_zip_read_data_skip(a); + /* We can't decompress this entry, but we will + * be able to skip() it and try the next entry. */ r = ARCHIVE_WARN; } break; @@ -747,6 +747,10 @@ archive_read_format_zip_read_data_skip(struct archive_read *a) zip = (struct zip *)(a->format->data); + /* If we've already read to end of data, we're done. */ + if (zip->end_of_entry_cleanup) + return (ARCHIVE_OK); + /* * If the length is at the end, we have no choice but * to decompress all the data to find the end marker. diff --git a/contrib/libarchive-2/libarchive/archive_string.c b/contrib/libarchive-2/libarchive/archive_string.c index 7c378deead..21fe571151 100644 --- a/contrib/libarchive-2/libarchive/archive_string.c +++ b/contrib/libarchive-2/libarchive/archive_string.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_string.c,v 1.11 2007/07/15 19:13:59 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_string.c,v 1.16 2008/06/15 11:28:56 kientzle Exp $"); /* * Basic resizable string support, to simplify manipulating arbitrary-sized @@ -41,14 +41,6 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_string.c,v 1.11 2007/07/15 19:13: #include #endif -#ifdef __sgi -/* - * The following prototype is missing on IRXI, - * even though the function is implemented in libc. - */ -size_t wcrtomb(char *, wchar_t, mbstate_t *); -#endif - #include "archive_private.h" #include "archive_string.h" @@ -172,14 +164,13 @@ __archive_strappend_int(struct archive_string *as, int d, int base) } /* - * Home-grown wcrtomb for UTF-8. + * Home-grown wctomb for UTF-8. */ -static size_t -my_wcrtomb_utf8(char *p, wchar_t wc, mbstate_t *s) +static int +my_wctomb_utf8(char *p, wchar_t wc) { - (void)s; /* UNUSED */ - if (p == NULL) + /* UTF-8 doesn't use shift states. */ return (0); if (wc <= 0x7f) { p[0] = (char)wc; @@ -208,24 +199,25 @@ my_wcrtomb_utf8(char *p, wchar_t wc, mbstate_t *s) * Awkward point: UTF-8 <-> wchar_t conversions * can actually fail. */ - return ((size_t)-1); + return (-1); } static int my_wcstombs(struct archive_string *as, const wchar_t *w, - size_t (*func)(char *, wchar_t, mbstate_t *)) + int (*func)(char *, wchar_t)) { - size_t n; + int n; char *p; - mbstate_t shift_state; char buff[256]; + /* Clear the shift state before starting. */ + (*func)(NULL, L'\0'); + /* * Convert one wide char at a time into 'buff', whenever that * fills, append it to the string. */ p = buff; - wcrtomb(NULL, L'\0', &shift_state); while (*w != L'\0') { /* Flush the buffer when we have <=16 bytes free. */ /* (No encoding has a single character >16 bytes.) */ @@ -234,8 +226,8 @@ my_wcstombs(struct archive_string *as, const wchar_t *w, archive_strcat(as, buff); p = buff; } - n = (*func)(p, *w++, &shift_state); - if (n == (size_t)-1) + n = (*func)(p, *w++); + if (n == -1) return (-1); p += n; } @@ -251,7 +243,7 @@ my_wcstombs(struct archive_string *as, const wchar_t *w, struct archive_string * __archive_strappend_w_utf8(struct archive_string *as, const wchar_t *w) { - if (my_wcstombs(as, w, my_wcrtomb_utf8)) + if (my_wcstombs(as, w, my_wctomb_utf8)) return (NULL); return (as); } @@ -260,42 +252,40 @@ __archive_strappend_w_utf8(struct archive_string *as, const wchar_t *w) * Translates a wide character string into current locale character set * and appends to the archive_string. Note: returns NULL if conversion * fails. - * - * TODO: use my_wcrtomb_utf8 if !HAVE_WCRTOMB (add configure logic first!) */ struct archive_string * __archive_strappend_w_mbs(struct archive_string *as, const wchar_t *w) { - if (my_wcstombs(as, w, wcrtomb)) +#if HAVE_WCTOMB + if (my_wcstombs(as, w, wctomb)) + return (NULL); +#else + /* TODO: Can we do better than this? Are there platforms + * that have locale support but don't have wctomb()? */ + if (my_wcstombs(as, w, my_wctomb_utf8)) return (NULL); +#endif return (as); } /* - * Home-grown mbrtowc for UTF-8. Some systems lack UTF-8 - * (or even lack mbrtowc()) and we need UTF-8 support for pax + * Home-grown mbtowc for UTF-8. Some systems lack UTF-8 + * (or even lack mbtowc()) and we need UTF-8 support for pax * format. So please don't replace this with a call to the - * standard mbrtowc() function! + * standard mbtowc() function! */ -static size_t -my_mbrtowc_utf8(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +static int +my_mbtowc_utf8(wchar_t *pwc, const char *s, size_t n) { int ch; - /* - * This argument is here to make the prototype identical to the - * standard mbrtowc(), so I can build generic string processors - * that just accept a pointer to a suitable mbrtowc() function. - */ - (void)ps; /* UNUSED */ - /* Standard behavior: a NULL value for 's' just resets shift state. */ if (s == NULL) return (0); /* If length argument is zero, don't look at the first character. */ if (n <= 0) - return ((size_t)-2); + return (-1); /* * Decode 1-4 bytes depending on the value of the first byte. @@ -310,16 +300,16 @@ my_mbrtowc_utf8(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } if ((ch & 0xe0) == 0xc0) { if (n < 2) - return ((size_t)-2); - if ((s[1] & 0xc0) != 0x80) return (size_t)-1; + return (-1); + if ((s[1] & 0xc0) != 0x80) return (-1); *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f); return (2); } if ((ch & 0xf0) == 0xe0) { if (n < 3) - return ((size_t)-2); - if ((s[1] & 0xc0) != 0x80) return (size_t)-1; - if ((s[2] & 0xc0) != 0x80) return (size_t)-1; + return (-1); + if ((s[1] & 0xc0) != 0x80) return (-1); + if ((s[2] & 0xc0) != 0x80) return (-1); *pwc = ((ch & 0x0f) << 12) | ((s[1] & 0x3f) << 6) | (s[2] & 0x3f); @@ -327,10 +317,10 @@ my_mbrtowc_utf8(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } if ((ch & 0xf8) == 0xf0) { if (n < 4) - return ((size_t)-2); - if ((s[1] & 0xc0) != 0x80) return (size_t)-1; - if ((s[2] & 0xc0) != 0x80) return (size_t)-1; - if ((s[3] & 0xc0) != 0x80) return (size_t)-1; + return (-1); + if ((s[1] & 0xc0) != 0x80) return (-1); + if ((s[2] & 0xc0) != 0x80) return (-1); + if ((s[3] & 0xc0) != 0x80) return (-1); *pwc = ((ch & 0x07) << 18) | ((s[1] & 0x3f) << 12) | ((s[2] & 0x3f) << 6) @@ -338,7 +328,7 @@ my_mbrtowc_utf8(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) return (4); } /* Invalid first byte. */ - return ((size_t)-1); + return (-1); } /* @@ -350,7 +340,7 @@ __archive_string_utf8_w(struct archive_string *as) { wchar_t *ws, *dest; const char *src; - size_t n; + int n; int err; ws = (wchar_t *)malloc((as->length + 1) * sizeof(wchar_t)); @@ -360,10 +350,10 @@ __archive_string_utf8_w(struct archive_string *as) dest = ws; src = as->s; while (*src != '\0') { - n = my_mbrtowc_utf8(dest, src, 8, NULL); + n = my_mbtowc_utf8(dest, src, 8); if (n == 0) break; - if (n == (size_t)-1 || n == (size_t)-2) { + if (n < 0) { free(ws); return (NULL); } diff --git a/contrib/libarchive-2/libarchive/archive_string.h b/contrib/libarchive-2/libarchive/archive_string.h index 61e70777f1..e59c33af19 100644 --- a/contrib/libarchive-2/libarchive/archive_string.h +++ b/contrib/libarchive-2/libarchive/archive_string.h @@ -22,7 +22,7 @@ * (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: src/lib/libarchive/archive_string.h,v 1.10 2008/03/14 22:00:09 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive_string.h,v 1.12 2008/06/15 05:11:08 kientzle Exp $ * */ @@ -30,6 +30,9 @@ #define ARCHIVE_STRING_H_INCLUDED #include +#ifdef HAVE_STDLIB_H +#include /* required for wchar_t on some systems */ +#endif #ifdef HAVE_STRING_H #include #endif diff --git a/contrib/libarchive-2/libarchive/archive_util.c b/contrib/libarchive-2/libarchive/archive_util.c index 55dd1fa10c..7fb4696771 100644 --- a/contrib/libarchive-2/libarchive/archive_util.c +++ b/contrib/libarchive-2/libarchive/archive_util.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_util.c,v 1.17 2008/03/14 22:31:57 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_util.c,v 1.18 2008/05/26 17:00:22 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include diff --git a/contrib/libarchive-2/libarchive/archive_write.3 b/contrib/libarchive-2/libarchive/archive_write.3 index fff84f7cdd..14003f43c3 100644 --- a/contrib/libarchive-2/libarchive/archive_write.3 +++ b/contrib/libarchive-2/libarchive/archive_write.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/archive_write.3,v 1.23 2008/03/10 14:44:41 jkoshy Exp $ +.\" $FreeBSD: src/lib/libarchive/archive_write.3,v 1.24 2008/05/26 17:00:23 kientzle Exp $ .\" .Dd May 11, 2008 .Dt archive_write 3 diff --git a/contrib/libarchive-2/libarchive/archive_write_disk.3 b/contrib/libarchive-2/libarchive/archive_write_disk.3 index f71d7d5485..d68a0ffca3 100644 --- a/contrib/libarchive-2/libarchive/archive_write_disk.3 +++ b/contrib/libarchive-2/libarchive/archive_write_disk.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/archive_write_disk.3,v 1.2 2008/03/10 14:44:41 jkoshy Exp $ +.\" $FreeBSD: src/lib/libarchive/archive_write_disk.3,v 1.3 2008/05/26 17:00:23 kientzle Exp $ .\" .Dd March 2, 2007 .Dt archive_write_disk 3 diff --git a/contrib/libarchive-2/libarchive/archive_write_disk.c b/contrib/libarchive-2/libarchive/archive_write_disk.c index 8010c1330e..238173c42a 100644 --- a/contrib/libarchive-2/libarchive/archive_write_disk.c +++ b/contrib/libarchive-2/libarchive/archive_write_disk.c @@ -25,7 +25,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.24 2008/03/15 04:20:50 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.26 2008/06/21 19:05:29 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include @@ -64,9 +64,6 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.24 2008/03/15 04 #ifdef HAVE_LINUX_FS_H #include /* for Linux file flags */ #endif -#ifdef HAVE_LINUX_EXT2_FS_H -#include /* for Linux file flags */ -#endif #ifdef HAVE_LIMITS_H #include #endif @@ -613,8 +610,8 @@ _archive_write_finish_entry(struct archive *_a) /* Restore metadata. */ /* - * Look up the "real" UID only if we're going to need it. We - * need this for TODO_SGID because chown() requires both. + * Look up the "real" UID only if we're going to need it. + * TODO: the TODO_SGID condition can be dropped here, can't it? */ if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) { a->uid = a->lookup_uid(a->lookup_uid_data, @@ -622,6 +619,7 @@ _archive_write_finish_entry(struct archive *_a) archive_entry_uid(a->entry)); } /* Look up the "real" GID only if we're going to need it. */ + /* TODO: the TODO_SUID condition can be dropped here, can't it? */ if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) { a->gid = a->lookup_gid(a->lookup_gid_data, archive_entry_gname(a->entry), @@ -1023,7 +1021,10 @@ create_filesystem_object(struct archive_write_disk *a) a->deferred |= (a->todo & TODO_TIMES); a->todo &= ~TODO_TIMES; /* Never use an immediate chmod(). */ - if (mode != final_mode) + /* We can't avoid the chmod() entirely if EXTRACT_PERM + * because of SysV SGID inheritance. */ + if ((mode != final_mode) + || (a->flags & ARCHIVE_EXTRACT_PERM)) a->deferred |= (a->todo & TODO_MODE); a->todo &= ~TODO_MODE; } @@ -1351,7 +1352,7 @@ cleanup_pathname(struct archive_write_disk *a) if (*src == '\0') { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid empty pathname"); - return (ARCHIVE_WARN); + return (ARCHIVE_FAILED); } /* Skip leading '/'. */ @@ -1382,7 +1383,7 @@ cleanup_pathname(struct archive_write_disk *a) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Path contains '..'"); - return (ARCHIVE_WARN); + return (ARCHIVE_FAILED); } lastdotdot = 1; } else @@ -1421,7 +1422,7 @@ cleanup_pathname(struct archive_write_disk *a) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Path contains trailing '..'"); - return (ARCHIVE_WARN); + return (ARCHIVE_FAILED); } if (dest == a->name) { /* @@ -1565,8 +1566,8 @@ create_dir(struct archive_write_disk *a, char *path) /* * Note: Although we can skip setting the user id if the desired user * id matches the current user, we cannot skip setting the group, as - * many systems set the gid bit based on the containing directory. So - * we have to perform a chown syscall if we want to restore the SGID + * many systems set the gid based on the containing directory. So + * we have to perform a chown syscall if we want to set the SGID * bit. (The alternative is to stat() and then possibly chown(); it's * more efficient to skip the stat() and just always chown().) Note * that a successful chown() here clears the TODO_SGID_CHECK bit, which diff --git a/contrib/libarchive-2/libarchive/archive_write_set_compression_program.c b/contrib/libarchive-2/libarchive/archive_write_set_compression_program.c index b8b20c86cf..69c5d42863 100644 --- a/contrib/libarchive-2/libarchive/archive_write_set_compression_program.c +++ b/contrib/libarchive-2/libarchive/archive_write_set_compression_program.c @@ -25,10 +25,12 @@ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_program.c,v 1.1 2007/05/29 01:00:19 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_program.c,v 1.3 2008/06/15 10:45:57 kientzle Exp $"); /* This capability is only available on POSIX systems. */ -#if !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) +#if !defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \ + !(defined(HAVE_FORK) || defined(HAVE_VFORK)) +#include "archive.h" /* * On non-Posix systems, allow the program to build, but choke if @@ -180,6 +182,12 @@ restart_write: if (ret == -1 && errno != EAGAIN) return (-1); + if (state->child_stdout == -1) { + fcntl(state->child_stdin, F_SETFL, 0); + __archive_check_child(state->child_stdin, state->child_stdout); + goto restart_write; + } + do { ret = read(state->child_stdout, state->child_buf + state->child_buf_avail, diff --git a/contrib/libarchive-2/libarchive/archive_write_set_format_ar.c b/contrib/libarchive-2/libarchive/archive_write_set_format_ar.c index 1731844d33..7176e6e2f4 100644 --- a/contrib/libarchive-2/libarchive/archive_write_set_format_ar.c +++ b/contrib/libarchive-2/libarchive/archive_write_set_format_ar.c @@ -26,7 +26,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_ar.c,v 1.6 2008/03/15 11:04:45 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_ar.c,v 1.7 2008/05/26 17:00:23 kientzle Exp $"); #ifdef HAVE_ERRNO_H #include diff --git a/contrib/libarchive-2/libarchive/archive_write_set_format_pax.c b/contrib/libarchive-2/libarchive/archive_write_set_format_pax.c index 89f89bc9f5..3e294cdf0a 100644 --- a/contrib/libarchive-2/libarchive/archive_write_set_format_pax.c +++ b/contrib/libarchive-2/libarchive/archive_write_set_format_pax.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_pax.c,v 1.46 2008/03/15 11:04:45 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_pax.c,v 1.47 2008/05/26 17:00:23 kientzle Exp $"); #ifdef HAVE_ERRNO_H #include diff --git a/contrib/libarchive-2/libarchive/archive_write_set_format_ustar.c b/contrib/libarchive-2/libarchive/archive_write_set_format_ustar.c index 970fee8db1..8aed25d1f9 100644 --- a/contrib/libarchive-2/libarchive/archive_write_set_format_ustar.c +++ b/contrib/libarchive-2/libarchive/archive_write_set_format_ustar.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_ustar.c,v 1.26 2008/03/15 11:04:45 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_ustar.c,v 1.27 2008/05/26 17:00:23 kientzle Exp $"); #ifdef HAVE_ERRNO_H diff --git a/contrib/libarchive-2/libarchive/cpio.5 b/contrib/libarchive-2/libarchive/cpio.5 index 8f024c546a..f54462818a 100644 --- a/contrib/libarchive-2/libarchive/cpio.5 +++ b/contrib/libarchive-2/libarchive/cpio.5 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/cpio.5,v 1.1 2007/12/30 04:58:22 kientzle Exp $ +.\" $FreeBSD: src/lib/libarchive/cpio.5,v 1.2 2008/05/26 17:00:23 kientzle Exp $ .\" .Dd October 5, 2007 .Dt CPIO 5 diff --git a/contrib/libarchive-2/libarchive/filter_fork.c b/contrib/libarchive-2/libarchive/filter_fork.c index 3c2d829d05..c746a186f5 100644 --- a/contrib/libarchive-2/libarchive/filter_fork.c +++ b/contrib/libarchive-2/libarchive/filter_fork.c @@ -26,9 +26,10 @@ #include "archive_platform.h" /* This capability is only available on POSIX systems. */ -#if defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL) +#if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \ + (defined(HAVE_FORK) || defined(HAVE_VFORK)) -__FBSDID("$FreeBSD: src/lib/libarchive/filter_fork.c,v 1.2 2007/12/30 04:58:22 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/filter_fork.c,v 1.4 2008/06/15 10:45:57 kientzle Exp $"); #if defined(HAVE_POLL) # if defined(HAVE_POLL_H) @@ -75,7 +76,11 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) stdout_pipe[1] = tmp; } +#if HAVE_VFORK switch ((child = vfork())) { +#else + switch ((child = fork())) { +#endif case -1: goto stdout_opened; case 0: @@ -118,23 +123,35 @@ __archive_check_child(int in, int out) { #if defined(HAVE_POLL) struct pollfd fds[2]; + int idx; - fds[0].fd = in; - fds[0].events = POLLOUT; - fds[1].fd = out; - fds[1].events = POLLIN; + idx = 0; + if (in != -1) { + fds[idx].fd = in; + fds[idx].events = POLLOUT; + ++idx; + } + if (out != -1) { + fds[idx].fd = out; + fds[idx].events = POLLIN; + ++idx; + } - poll(fds, 2, -1); /* -1 == INFTIM, wait forever */ + poll(fds, idx, -1); /* -1 == INFTIM, wait forever */ #elif defined(HAVE_SELECT) fd_set fds_in, fds_out, fds_error; FD_ZERO(&fds_in); - FD_SET(out, &fds_in); FD_ZERO(&fds_out); - FD_SET(in, &fds_out); FD_ZERO(&fds_error); - FD_SET(in, &fds_error); - FD_SET(out, &fds_error); + if (out != -1) { + FD_SET(out, &fds_in); + FD_SET(out, &fds_error); + } + if (in != -1) { + FD_SET(in, &fds_out); + FD_SET(in, &fds_error); + } select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL); #else sleep(1); diff --git a/contrib/libarchive-2/libarchive/libarchive-formats.5 b/contrib/libarchive-2/libarchive/libarchive-formats.5 index f570935c82..dd054a9391 100644 --- a/contrib/libarchive-2/libarchive/libarchive-formats.5 +++ b/contrib/libarchive-2/libarchive/libarchive-formats.5 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/libarchive-formats.5,v 1.15 2007/12/30 04:58:22 kientzle Exp $ +.\" $FreeBSD: src/lib/libarchive/libarchive-formats.5,v 1.16 2008/05/26 17:00:23 kientzle Exp $ .\" .Dd April 27, 2004 .Dt libarchive-formats 3 diff --git a/contrib/libarchive-2/libarchive/tar.5 b/contrib/libarchive-2/libarchive/tar.5 index c873a938f4..0687326809 100644 --- a/contrib/libarchive-2/libarchive/tar.5 +++ b/contrib/libarchive-2/libarchive/tar.5 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/tar.5,v 1.17 2007/01/09 08:05:56 kientzle Exp $ +.\" $FreeBSD: src/lib/libarchive/tar.5,v 1.18 2008/05/26 17:00:23 kientzle Exp $ .\" .Dd May 20, 2004 .Dt TAR 5 diff --git a/contrib/libarchive-2/tar/bsdtar.1 b/contrib/libarchive-2/tar/bsdtar.1 index 542b0f3f50..e790d60ccb 100644 --- a/contrib/libarchive-2/tar/bsdtar.1 +++ b/contrib/libarchive-2/tar/bsdtar.1 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.bin/tar/bsdtar.1,v 1.42 2008/05/17 15:55:29 cperciva Exp $ +.\" $FreeBSD: src/usr.bin/tar/bsdtar.1,v 1.43 2008/05/26 17:10:10 kientzle Exp $ .\" .Dd May 15, 2008 .Dt BSDTAR 1 diff --git a/contrib/libarchive-2/tar/bsdtar.c b/contrib/libarchive-2/tar/bsdtar.c index 2491dda6bc..1c13cc6bfb 100644 --- a/contrib/libarchive-2/tar/bsdtar.c +++ b/contrib/libarchive-2/tar/bsdtar.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.90 2008/05/19 18:38:01 cperciva Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.91 2008/05/26 17:10:10 kientzle Exp $"); #ifdef HAVE_SYS_PARAM_H #include diff --git a/contrib/libarchive-2/tar/bsdtar.h b/contrib/libarchive-2/tar/bsdtar.h index 9d4733c504..4153a44f94 100644 --- a/contrib/libarchive-2/tar/bsdtar.h +++ b/contrib/libarchive-2/tar/bsdtar.h @@ -22,7 +22,7 @@ * (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: src/usr.bin/tar/bsdtar.h,v 1.32 2008/05/22 21:08:36 cperciva Exp $ + * $FreeBSD: src/usr.bin/tar/bsdtar.h,v 1.33 2008/05/26 17:10:10 kientzle Exp $ */ #include "bsdtar_platform.h" diff --git a/contrib/libarchive-2/tar/matching.c b/contrib/libarchive-2/tar/matching.c index 59be17b9a3..952055fe8a 100644 --- a/contrib/libarchive-2/tar/matching.c +++ b/contrib/libarchive-2/tar/matching.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/matching.c,v 1.12 2008/03/18 06:18:49 kientzle Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/matching.c,v 1.13 2008/05/26 17:10:10 kientzle Exp $"); #ifdef HAVE_ERRNO_H #include diff --git a/contrib/libarchive-2/tar/read.c b/contrib/libarchive-2/tar/read.c index e1905b2486..fbb82533a7 100644 --- a/contrib/libarchive-2/tar/read.c +++ b/contrib/libarchive-2/tar/read.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.37 2008/05/18 06:24:47 cperciva Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.38 2008/05/26 17:10:10 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include @@ -388,7 +388,7 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) if (abs(tim - now) > (365/2)*86400) fmt = bsdtar->day_first ? "%e %b %Y" : "%b %e %Y"; else - fmt = bsdtar->day_first ? "%e %b %R" : "%b %e %R"; + fmt = bsdtar->day_first ? "%e %b %H:%M" : "%b %e %H:%M"; strftime(tmp, sizeof(tmp), fmt, localtime(&tim)); fprintf(out, " %s ", tmp); safe_fprintf(out, "%s", archive_entry_pathname(entry)); diff --git a/contrib/libarchive-2/tar/subst.c b/contrib/libarchive-2/tar/subst.c index 9fcd4d95fc..1c32fb0752 100644 --- a/contrib/libarchive-2/tar/subst.c +++ b/contrib/libarchive-2/tar/subst.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: src/usr.bin/tar/subst.c,v 1.4 2008/06/15 10:08:16 kientzle Exp $"); #if HAVE_REGEX_H #include "bsdtar.h" @@ -34,11 +34,15 @@ __FBSDID("$FreeBSD$"); #include #include +#ifndef REG_BASIC +#define REG_BASIC 0 +#endif + struct subst_rule { struct subst_rule *next; regex_t re; char *result; - int global:1, print:1, symlink:1; + unsigned int global:1, print:1, symlink:1; }; struct substitution { @@ -222,7 +226,15 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, int s realloc_strncat(bsdtar, result, rule->result + j, i - j - 1); j = i; break; - case '1' ... '9': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': realloc_strncat(bsdtar, result, rule->result + j, i - j - 1); if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) { free(*result); diff --git a/contrib/libarchive-2/tar/util.c b/contrib/libarchive-2/tar/util.c index 1d50dcd801..ee1e40dbf2 100644 --- a/contrib/libarchive-2/tar/util.c +++ b/contrib/libarchive-2/tar/util.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.18 2008/01/02 00:21:27 kientzle Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.20 2008/06/09 14:03:55 cperciva Exp $"); #ifdef HAVE_SYS_STAT_H #include @@ -369,9 +369,11 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry) } if (r == 1) { archive_entry_copy_pathname(entry, subst_name); - free(subst_name); - if (*subst_name == '\0') + if (*subst_name == '\0') { + free(subst_name); return -1; + } else + free(subst_name); name = archive_entry_pathname(entry); } diff --git a/contrib/libarchive-2/tar/write.c b/contrib/libarchive-2/tar/write.c index 432612ac7a..1a6e9289ab 100644 --- a/contrib/libarchive-2/tar/write.c +++ b/contrib/libarchive-2/tar/write.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.69 2008/05/23 05:07:22 cperciva Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.70 2008/05/26 17:10:10 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include @@ -62,9 +62,6 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.69 2008/05/23 05:07:22 cperciva #ifdef HAVE_LINUX_FS_H #include /* for Linux file flags */ #endif -#ifdef HAVE_LINUX_EXT2_FS_H -#include /* for Linux file flags */ -#endif #ifdef HAVE_PWD_H #include #endif diff --git a/contrib/libarchive-2/version b/contrib/libarchive-2/version index bd20368be5..b50fb110a5 100644 --- a/contrib/libarchive-2/version +++ b/contrib/libarchive-2/version @@ -1 +1 @@ -2005004b +2005005 -- 2.11.4.GIT