]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
IFC
authorTim Kientzle <kientzle@gmail.com>
Tue, 20 May 2008 18:47:23 +0000 (14:47 -0400)
committerTim Kientzle <kientzle@gmail.com>
Tue, 20 May 2008 18:47:23 +0000 (14:47 -0400)
SVN-Revision: 75

libarchive/archive_read_support_format_mtree.c
tar/Makefile
tar/bsdtar.1
tar/bsdtar.c
tar/bsdtar.h
tar/read.c
tar/siginfo.c [new file with mode: 0644]
tar/write.c

index c8b785d93330b7a82e6021c6a88fb7d989cd83ce..f24f091c12604efc98c4af6b96a6411c8505fa1d 100644 (file)
@@ -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 <sys/stat.h>
index 29f1d15c592b72537eb78d8f0a4ab36b0d3de711..b6a6a7768ac8f5a5e43c99e0cbd1c85ce0fc4392 100644 (file)
@@ -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
index 3bef4fa35b54bf494bc16dc0664bbc0d3ca2b37d..542b0f3f509f6ce5791d0b01f662e548336f3b80 100644 (file)
@@ -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.
index ba69e64eef04019f49bc3a9592c52ccfbff4fa36..2491dda6bca8e960b3ca88b76c0fde9133bfc591 100644 (file)
@@ -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 <sys/param.h>
@@ -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;
index 9f1f28625bd8d91b688339792c2c092387708283..840322caa66ddee9dbe553e2c801ddc30649cfe8 100644 (file)
@@ -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);
index edb33cb45431213a335a18b9c1c8549e482bdc1b..e1905b24867b7d4f7379c1487cba2d078628677c 100644 (file)
@@ -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 <sys/types.h>
@@ -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 (file)
index 0000000..5e459cb
--- /dev/null
@@ -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 <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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);
+}
index 1dac23cff2a3585253058b98ed556b107b3195ac..2bcf2514c4da1898415a3cb1c94a218b5522ba28 100644 (file)
@@ -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 <sys/types.h>
@@ -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;