*/
#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>
-# $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
.\" 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
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.
*/
#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>
OPTION_FORMAT,
OPTION_HELP,
OPTION_INCLUDE,
+ OPTION_KEEP_NEWER_FILES,
OPTION_NEWER_CTIME,
OPTION_NEWER_CTIME_THAN,
OPTION_NEWER_MTIME,
{ "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' },
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;
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;
* (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"
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 */
};
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);
*/
#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>
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);
}
/*
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)
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
--- /dev/null
+/*-
+ * 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);
+}
*/
#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>
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. */
}
archive_write_finish(a);
+
+ /* Restore old SIGINFO + SIGUSR1 handlers. */
+ siginfo_done(bsdtar);
}
/*
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) {
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));
}
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);
if (fd >= 0)
close(fd);
- if (entry != NULL)
- archive_entry_free(entry);
+ archive_entry_free(entry);
}
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 */
"Truncated write; file may have grown while being archived.");
return (0);
}
+ progress += bytes_written;
bytes_read = read(fd, buff, sizeof(buff));
}
return 0;