From: Tim Kientzle Date: Tue, 20 May 2008 18:47:23 +0000 (-0400) Subject: IFC X-Git-Tag: v2.6.0~217 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=58337c84f22ccbec7e0fd282a943f7bdcbf1e05b;p=thirdparty%2Flibarchive.git IFC SVN-Revision: 75 --- diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index c8b785d93..f24f091c1 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/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.4 2008/03/15 11:02:47 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_mtree.c,v 1.5 2008/05/19 18:06:48 cperciva Exp $"); #ifdef HAVE_SYS_STAT_H #include diff --git a/tar/Makefile b/tar/Makefile index 29f1d15c5..b6a6a7768 100644 --- a/tar/Makefile +++ b/tar/Makefile @@ -1,8 +1,8 @@ -# $FreeBSD: src/usr.bin/tar/Makefile,v 1.34 2008/03/18 06:18:49 kientzle Exp $ +# $FreeBSD: src/usr.bin/tar/Makefile,v 1.35 2008/05/18 06:24:47 cperciva Exp $ PROG= bsdtar BSDTAR_VERSION_STRING=2.5.3b -SRCS= bsdtar.c getdate.y matching.c read.c tree.c util.c write.c +SRCS= bsdtar.c getdate.y matching.c read.c siginfo.c tree.c util.c write.c WARNS?= 5 DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ} LDADD= -larchive -lbz2 -lz diff --git a/tar/bsdtar.1 b/tar/bsdtar.1 index 3bef4fa35..542b0f3f5 100644 --- a/tar/bsdtar.1 +++ b/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.41 2008/05/02 05:40:05 kientzle Exp $ +.\" $FreeBSD: src/usr.bin/tar/bsdtar.1,v 1.42 2008/05/17 15:55:29 cperciva Exp $ .\" .Dd May 15, 2008 .Dt BSDTAR 1 @@ -225,6 +225,10 @@ automatically when reading archives. Do not overwrite existing files. In particular, if a file appears more than once in an archive, later copies will not overwrite earlier copies. +.It Fl -keep-newer-files ( Fl W Cm keep-newer-files ) +(x mode only) +Do not overwrite existing files that are newer than the +versions appearing in the archive being extracted. .It Fl L (c and r mode only) All symbolic links will be followed. diff --git a/tar/bsdtar.c b/tar/bsdtar.c index ba69e64ee..2491dda6b 100644 --- a/tar/bsdtar.c +++ b/tar/bsdtar.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.88 2008/05/02 05:40:05 kientzle Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.90 2008/05/19 18:38:01 cperciva Exp $"); #ifdef HAVE_SYS_PARAM_H #include @@ -142,6 +142,7 @@ enum { OPTION_FORMAT, OPTION_HELP, OPTION_INCLUDE, + OPTION_KEEP_NEWER_FILES, OPTION_NEWER_CTIME, OPTION_NEWER_CTIME_THAN, OPTION_NEWER_MTIME, @@ -191,6 +192,7 @@ static const struct option tar_longopts[] = { { "include", required_argument, NULL, OPTION_INCLUDE }, { "interactive", no_argument, NULL, 'w' }, { "insecure", no_argument, NULL, 'P' }, + { "keep-newer-files", no_argument, NULL, OPTION_KEEP_NEWER_FILES }, { "keep-old-files", no_argument, NULL, 'k' }, { "list", no_argument, NULL, 't' }, { "modification-time", no_argument, NULL, 'm' }, @@ -394,6 +396,9 @@ main(int argc, char **argv) case 'k': /* GNU tar */ bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE; break; + case OPTION_KEEP_NEWER_FILES: /* GNU tar */ + bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + break; case 'L': /* BSD convention */ bsdtar->symlink_mode = 'L'; break; @@ -741,8 +746,8 @@ rewrite_argv(struct bsdtar *bsdtar, int *argc, char **src_argv, const char *p; char *src, *dest; - if (src_argv[0] == NULL || - src_argv[1] == NULL || src_argv[1][0] == '-') + if (src_argv[0] == NULL || src_argv[1] == NULL || + src_argv[1][0] == '-' || src_argv[1][0] == '\0') return (src_argv); *argc += strlen(src_argv[1]) - 1; diff --git a/tar/bsdtar.h b/tar/bsdtar.h index 9f1f28625..840322caa 100644 --- a/tar/bsdtar.h +++ b/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.30 2008/03/15 03:06:46 kientzle Exp $ + * $FreeBSD: src/usr.bin/tar/bsdtar.h,v 1.31 2008/05/18 06:24:47 cperciva Exp $ */ #include "bsdtar_platform.h" @@ -97,6 +97,7 @@ struct bsdtar { struct matching *matching; /* for matching.c */ struct security *security; /* for read.c */ struct name_cache *uname_cache; /* for write.c */ + struct siginfo *siginfo; /* for siginfo.c */ struct substitution *substitution; /* for subst.c */ }; @@ -116,6 +117,11 @@ int process_lines(struct bsdtar *bsdtar, const char *pathname, int (*process)(struct bsdtar *, const char *)); void safe_fprintf(FILE *, const char *fmt, ...); void set_chdir(struct bsdtar *, const char *newdir); +void siginfo_init(struct bsdtar *); +void siginfo_setinfo(struct bsdtar *, const char * oper, + const char * path, int64_t size); +void siginfo_printinfo(struct bsdtar *, off_t progress); +void siginfo_done(struct bsdtar *); void tar_mode_c(struct bsdtar *bsdtar); void tar_mode_r(struct bsdtar *bsdtar); void tar_mode_t(struct bsdtar *bsdtar); diff --git a/tar/read.c b/tar/read.c index edb33cb45..e1905b248 100644 --- a/tar/read.c +++ b/tar/read.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.36 2008/03/15 03:06:46 kientzle Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.37 2008/05/18 06:24:47 cperciva Exp $"); #ifdef HAVE_SYS_TYPES_H #include @@ -83,8 +83,22 @@ tar_mode_t(struct bsdtar *bsdtar) void tar_mode_x(struct bsdtar *bsdtar) { + /* We want to catch SIGINFO and SIGUSR1. */ + siginfo_init(bsdtar); + read_archive(bsdtar, 'x'); + unmatched_inclusions_warn(bsdtar, "Not found in archive"); + /* Restore old SIGINFO + SIGUSR1 handlers. */ + siginfo_done(bsdtar); +} + +static void +progress_func(void * cookie) +{ + struct bsdtar * bsdtar = cookie; + + siginfo_printinfo(bsdtar, 0); } /* @@ -121,6 +135,12 @@ read_archive(struct bsdtar *bsdtar, char mode) do_chdir(bsdtar); + if (mode == 'x') { + /* Set an extract callback so that we can handle SIGINFO. */ + archive_read_extract_set_progress_callback(a, progress_func, + bsdtar); + } + if (mode == 'x' && bsdtar->option_chroot) { #if HAVE_CHROOT if (chroot(".") != 0) @@ -245,6 +265,12 @@ read_archive(struct bsdtar *bsdtar, char mode) archive_entry_pathname(entry)); fflush(stderr); } + + /* Tell the SIGINFO-handler code what we're doing. */ + siginfo_setinfo(bsdtar, "extracting", + archive_entry_pathname(entry), 0); + siginfo_printinfo(bsdtar, 0); + if (bsdtar->option_stdout) r = archive_read_data_into_fd(a, 1); else diff --git a/tar/siginfo.c b/tar/siginfo.c new file mode 100644 index 000000000..5e459cbd4 --- /dev/null +++ b/tar/siginfo.c @@ -0,0 +1,147 @@ +/*- + * Copyright 2008 Colin Percival + * 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 "bsdtar_platform.h" +__FBSDID("$FreeBSD: src/usr.bin/tar/siginfo.c,v 1.1 2008/05/18 06:24:47 cperciva Exp $"); + +#include +#include +#include +#include +#include + +#include "bsdtar.h" + +/* Is there a pending SIGINFO or SIGUSR1? */ +static volatile sig_atomic_t siginfo_received = 0; + +struct siginfo { + /* What sort of operation are we doing? */ + char * oper; + + /* What path are we handling? */ + char * path; + + /* How large is the archive entry? */ + int64_t size; + + /* Old signal handlers. */ +#ifdef SIGINFO + void (*siginfo_old)(int); +#endif + void (*sigusr1_old)(int); +}; + +static void siginfo_handler(int sig); + +/* Handler for SIGINFO / SIGUSR1. */ +static void +siginfo_handler(int sig) +{ + + (void)sig; /* UNUSED */ + + /* Record that SIGINFO or SIGUSR1 has been received. */ + siginfo_received = 1; +} + +void +siginfo_init(struct bsdtar *bsdtar) +{ + + /* Allocate space for internal structure. */ + if ((bsdtar->siginfo = malloc(sizeof(struct siginfo))) == NULL) + bsdtar_errc(bsdtar, 1, errno, "malloc failed"); + + /* Set the strings to NULL so that free() is safe. */ + bsdtar->siginfo->path = bsdtar->siginfo->oper = NULL; + +#ifdef SIGINFO + /* We want to catch SIGINFO, if it exists. */ + bsdtar->siginfo->siginfo_old = signal(SIGINFO, siginfo_handler); +#endif + /* ... and treat SIGUSR1 the same way as SIGINFO. */ + bsdtar->siginfo->sigusr1_old = signal(SIGUSR1, siginfo_handler); +} + +void +siginfo_setinfo(struct bsdtar *bsdtar, const char * oper, const char * path, + int64_t size) +{ + + /* Free old operation and path strings. */ + free(bsdtar->siginfo->oper); + free(bsdtar->siginfo->path); + + /* Duplicate strings and store entry size. */ + if ((bsdtar->siginfo->oper = strdup(oper)) == NULL) + bsdtar_errc(bsdtar, 1, errno, "Cannot strdup"); + if ((bsdtar->siginfo->path = strdup(path)) == NULL) + bsdtar_errc(bsdtar, 1, errno, "Cannot strdup"); + bsdtar->siginfo->size = size; +} + +void +siginfo_printinfo(struct bsdtar *bsdtar, off_t progress) +{ + + /* If there's a signal to handle and we know what we're doing... */ + if ((siginfo_received == 1) && + (bsdtar->siginfo->path != NULL) && + (bsdtar->siginfo->oper != NULL)) { + if (bsdtar->verbose) + fprintf(stderr, "\n"); + if (bsdtar->siginfo->size > 0) { + safe_fprintf(stderr, "%s %s (%ju / %" PRId64 ")", + bsdtar->siginfo->oper, bsdtar->siginfo->path, + (uintmax_t)progress, bsdtar->siginfo->size); + } else { + safe_fprintf(stderr, "%s %s", + bsdtar->siginfo->oper, bsdtar->siginfo->path); + } + if (!bsdtar->verbose) + fprintf(stderr, "\n"); + siginfo_received = 0; + } +} + +void +siginfo_done(struct bsdtar *bsdtar) +{ + +#ifdef SIGINFO + /* Restore old SIGINFO handler. */ + signal(SIGINFO, bsdtar->siginfo->siginfo_old); +#endif + /* And the old SIGUSR1 handler, too. */ + signal(SIGUSR1, bsdtar->siginfo->sigusr1_old); + + /* Free strings. */ + free(bsdtar->siginfo->path); + free(bsdtar->siginfo->oper); + + /* Free internal data structure. */ + free(bsdtar->siginfo); +} diff --git a/tar/write.c b/tar/write.c index 1dac23cff..2bcf2514c 100644 --- a/tar/write.c +++ b/tar/write.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.66 2008/05/02 05:14:58 kientzle Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/write.c,v 1.68 2008/05/19 18:09:26 cperciva Exp $"); #ifdef HAVE_SYS_TYPES_H #include @@ -155,6 +155,9 @@ tar_mode_c(struct bsdtar *bsdtar) if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) bsdtar_errc(bsdtar, 1, 0, "no files or directories specified"); + /* We want to catch SIGINFO and SIGUSR1. */ + siginfo_init(bsdtar); + a = archive_write_new(); /* Support any format that the library supports. */ @@ -223,6 +226,9 @@ tar_mode_c(struct bsdtar *bsdtar) } archive_write_finish(a); + + /* Restore old SIGINFO + SIGUSR1 handlers. */ + siginfo_done(bsdtar); } /* @@ -571,6 +577,10 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina) if (bsdtar->verbose) safe_fprintf(stderr, "a %s", archive_entry_pathname(in_entry)); + siginfo_setinfo(bsdtar, "copying", + archive_entry_pathname(in_entry), + archive_entry_size(in_entry)); + siginfo_printinfo(bsdtar, 0); e = archive_write_header(a, in_entry); if (e != ARCHIVE_OK) { @@ -606,14 +616,18 @@ copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina) char buff[64*1024]; ssize_t bytes_read; ssize_t bytes_written; + off_t progress = 0; bytes_read = archive_read_data(ina, buff, sizeof(buff)); while (bytes_read > 0) { + siginfo_printinfo(bsdtar, progress); + bytes_written = archive_write_data(a, buff, bytes_read); if (bytes_written < bytes_read) { bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); return (-1); } + progress += bytes_written; bytes_read = archive_read_data(ina, buff, sizeof(buff)); } @@ -913,8 +927,14 @@ write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st, if (!S_ISREG(st->st_mode)) archive_entry_set_size(entry, 0); + /* Record what we're doing, for the benefit of SIGINFO / SIGUSR1. */ + siginfo_setinfo(bsdtar, "adding", archive_entry_pathname(entry), + archive_entry_size(entry)); archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry); + /* Handle SIGINFO / SIGUSR1 request if one was made. */ + siginfo_printinfo(bsdtar, 0); + while (entry != NULL) { write_entry_backend(bsdtar, a, entry, &fd); archive_entry_free(entry); @@ -930,8 +950,7 @@ abort: if (fd >= 0) close(fd); - if (entry != NULL) - archive_entry_free(entry); + archive_entry_free(entry); } @@ -942,12 +961,15 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a, int fd) char buff[64*1024]; ssize_t bytes_read; ssize_t bytes_written; + off_t progress = 0; /* XXX TODO: Allocate buffer on heap and store pointer to * it in bsdtar structure; arrange cleanup as well. XXX */ bytes_read = read(fd, buff, sizeof(buff)); while (bytes_read > 0) { + siginfo_printinfo(bsdtar, progress); + bytes_written = archive_write_data(a, buff, bytes_read); if (bytes_written < 0) { /* Write failed; this is bad */ @@ -960,6 +982,7 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a, int fd) "Truncated write; file may have grown while being archived."); return (0); } + progress += bytes_written; bytes_read = read(fd, buff, sizeof(buff)); } return 0;