summaryrefslogtreecommitdiff
path: root/archivers/libarchive/files/cpio
diff options
context:
space:
mode:
Diffstat (limited to 'archivers/libarchive/files/cpio')
-rw-r--r--archivers/libarchive/files/cpio/cmdline.c13
-rw-r--r--archivers/libarchive/files/cpio/cpio.c206
-rw-r--r--archivers/libarchive/files/cpio/cpio.h12
-rw-r--r--archivers/libarchive/files/cpio/matching.c13
-rw-r--r--archivers/libarchive/files/cpio/test/main.c53
-rw-r--r--archivers/libarchive/files/cpio/test/test.h39
6 files changed, 243 insertions, 93 deletions
diff --git a/archivers/libarchive/files/cpio/cmdline.c b/archivers/libarchive/files/cpio/cmdline.c
index 4b337279271..a602e39c179 100644
--- a/archivers/libarchive/files/cpio/cmdline.c
+++ b/archivers/libarchive/files/cpio/cmdline.c
@@ -26,7 +26,7 @@
#include "cpio_platform.h"
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/cpio/cmdline.c,v 1.3 2008/06/21 02:20:20 kientzle Exp $");
#ifdef HAVE_ERRNO_H
#include <errno.h>
@@ -66,7 +66,7 @@ struct option {
*/
-static const char *cpio_opts = "AaBC:F:O:cdE:f:H:hijLlmopR:rtuvW:yZz";
+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
@@ -82,12 +82,21 @@ static const char *cpio_opts = "AaBC:F:O:cdE:f:H:hijLlmopR:rtuvW:yZz";
* 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 }
diff --git a/archivers/libarchive/files/cpio/cpio.c b/archivers/libarchive/files/cpio/cpio.c
index 1d78ce1266f..76a91cf7152 100644
--- a/archivers/libarchive/files/cpio/cpio.c
+++ b/archivers/libarchive/files/cpio/cpio.c
@@ -26,7 +26,7 @@
#include "cpio_platform.h"
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.4 2008/06/24 15:18:40 kientzle Exp $");
#include <sys/types.h>
#include <archive.h>
@@ -101,6 +101,7 @@ main(int argc, char *argv[])
cpio->gid_override = -1;
cpio->argv = argv;
cpio->argc = argc;
+ cpio->line_separator = '\n';
cpio->mode = '\0';
cpio->verbose = 0;
cpio->compress = '\0';
@@ -116,6 +117,9 @@ main(int argc, char *argv[])
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;
@@ -178,6 +182,7 @@ main(int argc, char *argv[])
break;
case 'p': /* POSIX 1997 */
cpio->mode = opt;
+ cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
break;
case OPTION_QUIET: /* GNU cpio */
cpio->quiet = 1;
@@ -341,8 +346,10 @@ version(void)
static void
mode_out(struct cpio *cpio)
{
- struct archive_entry *entry, *spare;
unsigned long blocks;
+ struct archive_entry *entry, *spare;
+ struct line_reader *lr;
+ const char *p;
int r;
if (cpio->option_append)
@@ -375,7 +382,10 @@ mode_out(struct cpio *cpio)
r = archive_write_open_file(cpio->archive, cpio->filename);
if (r != ARCHIVE_OK)
cpio_errc(1, 0, archive_error_string(cpio->archive));
- process_lines(cpio, "-", file_to_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
@@ -525,17 +535,42 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
fprintf(stderr,"%s", destpath);
/*
- * Obviously, this only gets invoked in pass mode.
+ * 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) {
- /* Note: link(2) doesn't create parent directories. */
- archive_entry_set_hardlink(entry, srcpath);
- r = archive_write_header(cpio->archive, entry);
+ 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);
}
@@ -793,6 +828,8 @@ mode_list(struct cpio *cpio)
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. */
@@ -809,7 +846,10 @@ mode_pass(struct cpio *cpio, const char *destdir)
cpio_errc(1, 0, archive_error_string(cpio->archive));
cpio->linkresolver = archive_entry_linkresolver_new();
archive_write_disk_set_standard_lookup(cpio->archive);
- process_lines(cpio, "-", file_to_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);
@@ -868,79 +908,119 @@ cpio_rename(const char *name)
* terminated with newlines.
*
* This uses a self-sizing buffer to handle arbitrarily-long lines.
- * If the "process" function returns non-zero for any line, this
- * function will return non-zero after attempting to process all
- * remaining lines.
*/
-int
-process_lines(struct cpio *cpio, const char *pathname,
- int (*process)(struct cpio *, const char *))
-{
+struct line_reader {
FILE *f;
char *buff, *buff_end, *line_start, *line_end, *p;
- size_t buff_length, bytes_read, bytes_wanted;
+ 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);
- separator = cpio->option_null ? '\0' : '\n';
- ret = 0;
+ lr->separator = separator;
+ lr->pathname = strdup(pathname);
if (strcmp(pathname, "-") == 0)
- f = stdin;
+ lr->f = stdin;
else
- f = fopen(pathname, "r");
- if (f == NULL)
+ lr->f = fopen(pathname, "r");
+ if (lr->f == NULL)
cpio_errc(1, errno, "Couldn't open %s", pathname);
- buff_length = 8192;
- buff = malloc(buff_length);
- if (buff == NULL)
+ lr->buff_length = 8192;
+ lr->buff = malloc(lr->buff_length);
+ if (lr->buff == NULL)
cpio_errc(1, ENOMEM, "Can't read %s", pathname);
- line_start = line_end = buff_end = buff;
+ 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 (;;) {
- /* Get some more data into the buffer. */
- bytes_wanted = buff + buff_length - buff_end;
- bytes_read = fread(buff_end, 1, bytes_wanted, f);
- buff_end += bytes_read;
- /* Process all complete lines in the buffer. */
- while (line_end < buff_end) {
- if (*line_end == separator) {
- *line_end = '\0';
- if ((*process)(cpio, line_start) != 0)
- ret = -1;
- line_start = line_end + 1;
- line_end = line_start;
+ /* 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
- line_end++;
+ lr->line_end++;
}
- if (feof(f))
- break;
- if (ferror(f))
- cpio_errc(1, errno, "Can't read %s", pathname);
- if (line_start > buff) {
+
+ /* 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(buff, line_start, buff_end - line_start);
- buff_end -= line_start - buff;
- line_end -= line_start - buff;
- line_start = buff;
+ 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. */
- p = realloc(buff, buff_length *= 2);
+ 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", pathname);
- buff_end = p + (buff_end - buff);
- line_end = p + (line_end - buff);
- line_start = buff = p;
+ "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;
}
}
- /* At end-of-file, handle the final line. */
- if (line_end > line_start) {
- *line_end = '\0';
- if ((*process)(cpio, line_start) != 0)
- ret = -1;
- }
- free(buff);
- if (f != stdin)
- fclose(f);
- return (ret);
+}
+
+void
+process_lines_free(struct line_reader *lr)
+{
+ free(lr->buff);
+ free(lr->pathname);
+ free(lr);
}
diff --git a/archivers/libarchive/files/cpio/cpio.h b/archivers/libarchive/files/cpio/cpio.h
index ecec2eeec8e..3afd9520309 100644
--- a/archivers/libarchive/files/cpio/cpio.h
+++ b/archivers/libarchive/files/cpio/cpio.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$
+ * $FreeBSD: src/usr.bin/cpio/cpio.h,v 1.2 2008/06/21 02:20:20 kientzle Exp $
*/
#ifndef CPIO_H_INCLUDED
@@ -53,12 +53,12 @@ struct cpio {
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_null; /* -0 --null */
int option_rename; /* -r */
char *destdir;
size_t pass_destpath_alloc;
@@ -98,9 +98,13 @@ enum {
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 process_lines(struct cpio *cpio, const char *pathname,
- int (*process)(struct cpio *, const char *));
int include_from_file(struct cpio *, const char *);
#endif
diff --git a/archivers/libarchive/files/cpio/matching.c b/archivers/libarchive/files/cpio/matching.c
index f98421e2df4..3e4ddc3bfdb 100644
--- a/archivers/libarchive/files/cpio/matching.c
+++ b/archivers/libarchive/files/cpio/matching.c
@@ -24,7 +24,7 @@
*/
#include "cpio_platform.h"
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/cpio/matching.c,v 1.2 2008/06/21 02:20:20 kientzle Exp $");
#ifdef HAVE_ERRNO_H
#include <errno.h>
@@ -107,7 +107,16 @@ include(struct cpio *cpio, const char *pattern)
int
include_from_file(struct cpio *cpio, const char *pathname)
{
- return (process_lines(cpio, pathname, &include));
+ 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
diff --git a/archivers/libarchive/files/cpio/test/main.c b/archivers/libarchive/files/cpio/test/main.c
index c88dd2ac341..e0f8c2e1175 100644
--- a/archivers/libarchive/files/cpio/test/main.c
+++ b/archivers/libarchive/files/cpio/test/main.c
@@ -27,13 +27,13 @@
* Various utility routines useful for test programs.
* Each test program is linked against this file.
*/
+#include "test.h"
+
#include <errno.h>
#include <locale.h>
#include <stdarg.h>
#include <time.h>
-#include "test.h"
-
/*
* This same file is used pretty much verbatim for all test harnesses.
*
@@ -44,7 +44,7 @@
#undef EXTRA_DUMP /* How to dump extra data */
/* How to generate extra version info. */
#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.2 2008/06/21 02:17:18 kientzle Exp $");
/*
* "list.h" is simply created by "grep DEFINE_TEST"; it has
@@ -541,6 +541,48 @@ test_assert_equal_file(const char *f1, const char *f2pattern, ...)
return (0);
}
+int
+test_assert_file_exists(const char *fpattern, ...)
+{
+ char f[1024];
+ va_list ap;
+
+ va_start(ap, fpattern);
+ vsprintf(f, fpattern, ap);
+ va_end(ap);
+
+ if (!access(f, F_OK))
+ return (1);
+ if (!previous_failures(test_filename, test_line)) {
+ fprintf(stderr, "%s:%d: File doesn't exist\n",
+ test_filename, test_line);
+ fprintf(stderr, " file=\"%s\"\n", f);
+ report_failure(test_extra);
+ }
+ return (0);
+}
+
+int
+test_assert_file_not_exists(const char *fpattern, ...)
+{
+ char f[1024];
+ va_list ap;
+
+ va_start(ap, fpattern);
+ vsprintf(f, fpattern, ap);
+ va_end(ap);
+
+ if (access(f, F_OK))
+ return (1);
+ if (!previous_failures(test_filename, test_line)) {
+ fprintf(stderr, "%s:%d: File exists and shouldn't\n",
+ test_filename, test_line);
+ fprintf(stderr, " file=\"%s\"\n", f);
+ report_failure(test_extra);
+ }
+ return (0);
+}
+
/* assertFileContents() asserts the contents of a file. */
int
test_assert_file_contents(const void *buff, int s, const char *fpattern, ...)
@@ -670,8 +712,11 @@ static int test_run(int i, const char *tmpdir)
{
int failures_before = failures;
- if (!quiet_flag)
+ if (!quiet_flag) {
printf("%d: %s\n", i, tests[i].name);
+ fflush(stdout);
+ }
+
/*
* Always explicitly chdir() in case the last test moved us to
* a strange place.
diff --git a/archivers/libarchive/files/cpio/test/test.h b/archivers/libarchive/files/cpio/test/test.h
index 06e6d903fc8..431d5d7c4d5 100644
--- a/archivers/libarchive/files/cpio/test/test.h
+++ b/archivers/libarchive/files/cpio/test/test.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$
+ * $FreeBSD: src/usr.bin/cpio/test/test.h,v 1.2 2008/06/21 02:17:18 kientzle Exp $
*/
/* Every test program should #include "test.h" as the first thing. */
@@ -31,8 +31,18 @@
* The goal of this file (and the matching test.c) is to
* simplify the very repetitive test-*.c test programs.
*/
-#ifndef _FILE_OFFSET_BITS
-#define _FILE_OFFSET_BITS 64
+#if defined(HAVE_CONFIG_H)
+/* Most POSIX platforms use the 'configure' script to build config.h */
+#include "../../config.h"
+#elif defined(__FreeBSD__)
+/* Building as part of FreeBSD system requires a pre-built config.h. */
+#include "../config_freebsd.h"
+#elif defined(_WIN32)
+/* Win32 can't run the 'configure' script. */
+#include "../config_windows.h"
+#else
+/* Warn if the library hasn't been (automatically or manually) configured. */
+#error Oops: No config.h and no pre-built configuration in test.h.
#endif
#include <dirent.h>
@@ -51,20 +61,6 @@
#include <dmalloc.h>
#endif
-#if defined(HAVE_CONFIG_H)
-/* Most POSIX platforms use the 'configure' script to build config.h */
-#include "../../config.h"
-#elif defined(__FreeBSD__)
-/* Building as part of FreeBSD system requires a pre-built config.h. */
-#include "../config_freebsd.h"
-#elif defined(_WIN32)
-/* Win32 can't run the 'configure' script. */
-#include "../config_windows.h"
-#else
-/* Warn if the library hasn't been (automatically or manually) configured. */
-#error Oops: No config.h and no pre-built configuration in test.h.
-#endif
-
/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
#ifdef __FreeBSD__
#include <sys/cdefs.h> /* For __FBSDID */
@@ -102,6 +98,12 @@
/* Assert that a file is empty; supports printf-style arguments. */
#define assertEmptyFile \
test_setup(__FILE__, __LINE__);test_assert_empty_file
+/* Assert that a file exists; supports printf-style arguments. */
+#define assertFileExists \
+ test_setup(__FILE__, __LINE__);test_assert_file_exists
+/* Assert that a file exists; supports printf-style arguments. */
+#define assertFileNotExists \
+ test_setup(__FILE__, __LINE__);test_assert_file_not_exists
/* Assert that file contents match a string; supports printf-style arguments. */
#define assertFileContents \
test_setup(__FILE__, __LINE__);test_assert_file_contents
@@ -127,6 +129,8 @@ int test_assert_equal_string(const char *, int, const char *v1, const char *, co
int test_assert_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
int test_assert_equal_mem(const char *, int, const char *, const char *, const char *, const char *, size_t, const char *, void *);
int test_assert_file_contents(const void *, int, const char *, ...);
+int test_assert_file_exists(const char *, ...);
+int test_assert_file_not_exists(const char *, ...);
/* Like sprintf, then system() */
int systemf(const char * fmt, ...);
@@ -144,4 +148,3 @@ void extract_reference_file(const char *);
/* Pathname of exe to be tested. */
char *testprog;
-