tar/cmdline.c \
tar/getdate.c \
tar/read.c \
- tar/siginfo.c \
tar/subst.c \
tar/tree.c \
tar/tree.h \
cmdline.c
getdate.c
read.c
- siginfo.c
subst.c
tree.c
tree.h
PROG= bsdtar
BSDTAR_VERSION_STRING=2.7.900a
-SRCS= bsdtar.c cmdline.c getdate.c read.c siginfo.c subst.c tree.c util.c write.c
+SRCS= bsdtar.c cmdline.c getdate.c read.c subst.c tree.c util.c write.c
SRCS+= err.c line_reader.c matching.c pathmatch.c
WARNS?= 5
DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ}
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#define _PATH_DEFTAPE "/dev/tape"
#endif
-/* External function to parse a date/time string (from getdate.y) */
+static struct bsdtar *_bsdtar;
+
+#if defined(SIGINFO) || defined(SIGUSR1)
+static volatile int siginfo_occurred;
+
+static void
+siginfo_handler(int sig)
+{
+ (void)sig; /* UNUSED */
+ siginfo_occurred = 1;
+}
+
+int
+need_report(void)
+{
+ int r = siginfo_occurred;
+ siginfo_occurred = 0;
+ return (r);
+}
+#else
+int
+need_report(void)
+{
+ return (0);
+}
+#endif
+
+/* External function to parse a date/time string */
time_t get_date(time_t, const char *);
static void long_help(void);
* Use a pointer for consistency, but stack-allocated storage
* for ease of cleanup.
*/
- bsdtar = &bsdtar_storage;
+ _bsdtar = bsdtar = &bsdtar_storage;
memset(bsdtar, 0, sizeof(*bsdtar));
bsdtar->fd = -1; /* Mark as "unused" */
option_o = 0;
+#if defined(SIGINFO) || defined(SIGUSR1)
+ { /* Catch SIGINFO and SIGUSR1, if they exist. */
+ struct sigaction sa;
+ sa.sa_handler = siginfo_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+#ifdef SIGINFO
+ if (sigaction(SIGINFO, &sa, NULL))
+ lafe_errc(1, errno, "sigaction(SIGINFO) failed");
+#endif
+#ifdef SIGUSR1
+ /* ... and treat SIGUSR1 the same way as SIGINFO. */
+ if (sigaction(SIGUSR1, &sa, NULL))
+ lafe_errc(1, errno, "sigaction(SIGUSR1) failed");
+#endif
+ }
+#endif
+
+
/* Need lafe_progname before calling lafe_warnc. */
if (*argv == NULL)
lafe_progname = "bsdtar";
int fd;
/* Miscellaneous state information */
- struct archive *archive;
int argc;
char **argv;
const char *optarg;
int bsdtar_getopt(struct bsdtar *);
void do_chdir(struct bsdtar *);
int edit_pathname(struct bsdtar *, struct archive_entry *);
+int need_report(void);
int pathcmp(const char *a, const char *b);
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);
#define HAVE_PWD_H 1
#define HAVE_REGEX_H 1
#define HAVE_SETLOCALE 1
+#define HAVE_SIGNAL_H 1
#define HAVE_STDARG_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#include "bsdtar.h"
#include "err.h"
+struct progress_data {
+ struct bsdtar *bsdtar;
+ struct archive *archive;
+ struct archive_entry *entry;
+};
+
static void list_item_verbose(struct bsdtar *, FILE *,
struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode);
void
tar_mode_x(struct bsdtar *bsdtar)
{
- /* We want to catch SIGINFO and SIGUSR1. */
- siginfo_init(bsdtar);
-
read_archive(bsdtar, 'x');
if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0)
bsdtar->return_value = 1;
- /* Restore old SIGINFO + SIGUSR1 handlers. */
- siginfo_done(bsdtar);
}
static void
-progress_func(void * cookie)
+progress_func(void *cookie)
{
- struct bsdtar * bsdtar = cookie;
-
- siginfo_printinfo(bsdtar, 0);
+ struct progress_data *progress_data = cookie;
+ struct bsdtar *bsdtar = progress_data->bsdtar;
+ struct archive *a = progress_data->archive;
+ struct archive_entry *entry = progress_data->entry;
+ uintmax_t comp, uncomp;
+
+ if (!need_report())
+ return;
+
+ if (bsdtar->verbose)
+ fprintf(stderr, "\n");
+ if (a != NULL) {
+ comp = archive_position_compressed(a);
+ uncomp = archive_position_uncompressed(a);
+ fprintf(stderr,
+ "In: %ju bytes, compression %d%%;",
+ comp, (int)((uncomp - comp) * 100 / uncomp));
+ fprintf(stderr, " Out: %d files, %ju bytes\n",
+ archive_file_count(a), uncomp);
+ }
+ if (entry != NULL) {
+ safe_fprintf(stderr, "Current: %s (%ju bytes)",
+ archive_entry_pathname(entry),
+ (uintmax_t)archive_entry_size(entry));
+ fprintf(stderr, "\n");
+ }
}
/*
static void
read_archive(struct bsdtar *bsdtar, char mode)
{
+ struct progress_data progress_data;
FILE *out;
struct archive *a;
struct archive_entry *entry;
if (mode == 'x') {
/* Set an extract callback so that we can handle SIGINFO. */
+ progress_data.bsdtar = bsdtar;
+ progress_data.archive = a;
archive_read_extract_set_progress_callback(a, progress_func,
- bsdtar);
+ &progress_data);
}
if (mode == 'x' && bsdtar->option_chroot) {
break;
r = archive_read_next_header(a, &entry);
+ progress_data.entry = entry;
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
fflush(stderr);
}
- /* Tell the SIGINFO-handler code what we're doing. */
- siginfo_setinfo(bsdtar, "extracting",
- archive_entry_pathname(entry), 0);
- siginfo_printinfo(bsdtar, 0);
+ // TODO siginfo_printinfo(bsdtar, 0);
if (bsdtar->option_stdout)
r = archive_read_data_into_fd(a, 1);
+++ /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.2 2008/05/22 21:08:36 cperciva Exp $");
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "bsdtar.h"
-#include "err.h"
-
-/* Is there a pending SIGINFO or SIGUSR1? */
-static volatile sig_atomic_t siginfo_received = 0;
-
-struct siginfo_data {
- /* 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
- struct sigaction siginfo_old;
-#endif
-#ifdef SIGUSR1
- struct sigaction sigusr1_old;
-#endif
-};
-
-#if defined(SIGINFO) || defined(SIGUSR1)
-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)
-{
- struct sigaction sa;
-
- /* Allocate space for internal structure. */
- if ((bsdtar->siginfo = malloc(sizeof(struct siginfo_data))) == NULL)
- lafe_errc(1, errno, "malloc failed");
-
- /* Set the strings to NULL so that free() is safe. */
- bsdtar->siginfo->path = bsdtar->siginfo->oper = NULL;
-
- /* We want to catch SIGINFO, if it exists. */
- sa.sa_handler = siginfo_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-#ifdef SIGINFO
- if (sigaction(SIGINFO, &sa, &bsdtar->siginfo->siginfo_old))
- lafe_errc(1, errno, "sigaction(SIGINFO) failed");
-#endif
-#ifdef SIGUSR1
- /* ... and treat SIGUSR1 the same way as SIGINFO. */
- if (sigaction(SIGUSR1, &sa, &bsdtar->siginfo->sigusr1_old))
- lafe_errc(1, errno, "sigaction(SIGUSR1) failed");
-#endif
-}
-#else
-void
-siginfo_init(struct bsdtar *bsdtar)
-{
- /* Set the strings to NULL so that free() is safe. */
- bsdtar->siginfo = NULL;
-}
-#endif
-
-void
-siginfo_setinfo(struct bsdtar *bsdtar, const char * oper, const char * path,
- int64_t size)
-{
-
- /* Free old operation and path strings. */
- if (bsdtar->siginfo == NULL)
- return;
- free(bsdtar->siginfo->oper);
- free(bsdtar->siginfo->path);
-
- /* Duplicate strings and store entry size. */
- if ((bsdtar->siginfo->oper = strdup(oper)) == NULL)
- lafe_errc(1, errno, "Cannot strdup");
- if ((bsdtar->siginfo->path = strdup(path)) == NULL)
- lafe_errc(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. */
- sigaction(SIGINFO, &bsdtar->siginfo->siginfo_old, NULL);
-#endif
-#ifdef SIGUSR1
- /* And the old SIGUSR1 handler, too. */
- sigaction(SIGUSR1, &bsdtar->siginfo->sigusr1_old, NULL);
-#endif
-
- if (bsdtar->siginfo) {
- /* Free strings. */
- free(bsdtar->siginfo->path);
- free(bsdtar->siginfo->oper);
-
- /* Free internal data structure. */
- free(bsdtar->siginfo);
- }
-}
struct archive *, const char *fname);
static void archive_names_from_file(struct bsdtar *bsdtar,
struct archive *a);
-static int copy_file_data(struct bsdtar *bsdtar,
- struct archive *a, struct archive *ina);
+static int copy_file_data(struct bsdtar *, struct archive *a,
+ struct archive *ina, struct archive_entry *);
static int new_enough(struct bsdtar *, const char *path,
const struct stat *);
+static void report_write(struct bsdtar *, struct archive *,
+ struct archive_entry *, int64_t progress);
static void test_for_append(struct bsdtar *);
static void write_archive(struct archive *, struct bsdtar *);
static void write_entry_backend(struct bsdtar *, struct archive *,
const char *arg;
struct archive_entry *entry, *sparse_entry;
- /* We want to catch SIGINFO and SIGUSR1. */
- siginfo_init(bsdtar);
-
/* Allocate a buffer for file data. */
if ((bsdtar->buff = malloc(FILEDATABUFLEN)) == NULL)
lafe_errc(1, 0, "cannot allocate memory");
}
archive_write_finish(a);
-
- /* Restore old SIGINFO + SIGUSR1 handlers. */
- siginfo_done(bsdtar);
}
/*
struct lafe_line_reader *lr;
const char *line;
- bsdtar->archive = a;
-
bsdtar->next_line_is_dir = 0;
lr = lafe_line_reader(bsdtar->names_from_file, '\n');
else {
if (*line != '/')
do_chdir(bsdtar); /* Handle a deferred -C */
- write_hierarchy(bsdtar, bsdtar->archive, line);
+ write_hierarchy(bsdtar, a, line);
}
}
lafe_line_reader_free(lr);
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);
+ if (need_report())
+ report_write(bsdtar, a, in_entry, 0);
e = archive_write_header(a, in_entry);
if (e != ARCHIVE_OK) {
if (e >= ARCHIVE_WARN) {
if (archive_entry_size(in_entry) == 0)
archive_read_data_skip(ina);
- else if (copy_file_data(bsdtar, a, ina))
+ else if (copy_file_data(bsdtar, a, ina, in_entry))
exit(1);
}
/* Helper function to copy data between archives. */
static int
-copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
+copy_file_data(struct bsdtar *bsdtar, struct archive *a,
+ struct archive *ina, struct archive_entry *entry)
{
ssize_t bytes_read;
ssize_t bytes_written;
- off_t progress = 0;
+ int64_t progress = 0;
bytes_read = archive_read_data(ina, bsdtar->buff, FILEDATABUFLEN);
while (bytes_read > 0) {
- siginfo_printinfo(bsdtar, progress);
+ if (need_report())
+ report_write(bsdtar, a, entry, progress);
bytes_written = archive_write_data(a, bsdtar->buff,
bytes_read);
if (!S_ISREG(st->st_mode))
archive_entry_set_size(entry, 0);
- /* Record what we're doing, for SIGINFO / SIGUSR1. */
- siginfo_setinfo(bsdtar, "adding",
- archive_entry_pathname(entry), archive_entry_size(entry));
archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry);
- /* Handle SIGINFO / SIGUSR1 request if one was made. */
- siginfo_printinfo(bsdtar, 0);
-
while (entry != NULL) {
write_entry_backend(bsdtar, a, entry);
archive_entry_free(entry);
close(fd);
}
+static void
+report_write(struct bsdtar *bsdtar, struct archive *a,
+ struct archive_entry *entry, int64_t progress)
+{
+ uintmax_t comp, uncomp;
+ if (bsdtar->verbose)
+ fprintf(stderr, "\n");
+ comp = archive_position_compressed(a);
+ uncomp = archive_position_uncompressed(a);
+ fprintf(stderr, "In: %d files, %ju bytes;",
+ archive_file_count(a), uncomp);
+ fprintf(stderr,
+ " Out: %ju bytes, compression %d%%\n",
+ comp, (int)((uncomp - comp) * 100 / uncomp));
+ safe_fprintf(stderr, "Current: %s (%ju/%ju bytes)",
+ archive_entry_pathname(entry),
+ (uintmax_t)progress,
+ (uintmax_t)archive_entry_size(entry));
+ fprintf(stderr, "\n");
+}
+
/* Helper function to copy file to archive. */
static int
{
ssize_t bytes_read;
ssize_t bytes_written;
- off_t progress = 0;
+ int64_t progress = 0;
bytes_read = read(fd, bsdtar->buff, FILEDATABUFLEN);
while (bytes_read > 0) {
- siginfo_printinfo(bsdtar, progress);
+ if (need_report())
+ report_write(bsdtar, a, entry, progress);
bytes_written = archive_write_data(a, bsdtar->buff,
bytes_read);