From owner-svn-src-all@FreeBSD.ORG Sat Feb 6 20:27:36 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AF7EF106566C; Sat, 6 Feb 2010 20:27:36 +0000 (UTC) (envelope-from kientzle@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 9B4138FC16; Sat, 6 Feb 2010 20:27:36 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o16KRaOb030406; Sat, 6 Feb 2010 20:27:36 GMT (envelope-from kientzle@svn.freebsd.org) Received: (from kientzle@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o16KRach030399; Sat, 6 Feb 2010 20:27:36 GMT (envelope-from kientzle@svn.freebsd.org) Message-Id: <201002062027.o16KRach030399@svn.freebsd.org> From: Tim Kientzle Date: Sat, 6 Feb 2010 20:27:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r203568 - head/usr.bin/tar X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 06 Feb 2010 20:27:36 -0000 Author: kientzle Date: Sat Feb 6 20:27:36 2010 New Revision: 203568 URL: http://svn.freebsd.org/changeset/base/203568 Log: Refactor the siginfo/sigusr1 handling. The read/write reporting is sufficiently different that it was simpler to just put separate reporting functions into read.c and write.c rather than try to have a single all-purpose reporting function. Switch to a custom function for converting int64_t to a string; in the portable version, this saves a lot of configuration headaches trying to decipher the platform printf(). Deleted: head/usr.bin/tar/siginfo.c Modified: head/usr.bin/tar/Makefile head/usr.bin/tar/bsdtar.c head/usr.bin/tar/bsdtar.h head/usr.bin/tar/read.c head/usr.bin/tar/util.c head/usr.bin/tar/write.c Modified: head/usr.bin/tar/Makefile ============================================================================== --- head/usr.bin/tar/Makefile Sat Feb 6 20:21:03 2010 (r203567) +++ head/usr.bin/tar/Makefile Sat Feb 6 20:27:36 2010 (r203568) @@ -9,7 +9,6 @@ SRCS= bsdtar.c \ getdate.c \ matching.c \ read.c \ - siginfo.c \ subst.c \ tree.c \ util.c \ Modified: head/usr.bin/tar/bsdtar.c ============================================================================== --- head/usr.bin/tar/bsdtar.c Sat Feb 6 20:21:03 2010 (r203567) +++ head/usr.bin/tar/bsdtar.c Sat Feb 6 20:27:36 2010 (r203568) @@ -47,6 +47,9 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_PATHS_H #include #endif +#ifdef HAVE_SIGNAL_H +#include +#endif #include #ifdef HAVE_STDLIB_H #include @@ -82,7 +85,32 @@ __FBSDID("$FreeBSD$"); #define _PATH_DEFTAPE "/dev/tape" #endif -/* External function to parse a date/time string (from getdate.y) */ +#if defined(HAVE_SIGACTION) && (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); @@ -114,11 +142,23 @@ main(int argc, char **argv) memset(bsdtar, 0, sizeof(*bsdtar)); bsdtar->fd = -1; /* Mark as "unused" */ option_o = 0; -#if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure open() function will be used with a binary mode. */ - /* on cygwin, we need something similar, but instead link against */ - /* a special startup object, binmode.o */ - _set_fmode(_O_BINARY); + +#if defined(HAVE_SIGACTION) && (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)) + bsdtar_errc(1, errno, "sigaction(SIGINFO) failed"); +#endif +#ifdef SIGUSR1 + /* ... and treat SIGUSR1 the same way as SIGINFO. */ + if (sigaction(SIGUSR1, &sa, NULL)) + bsdtar_errc(1, errno, "sigaction(SIGUSR1) failed"); +#endif + } #endif /* Need bsdtar_progname before calling bsdtar_warnc. */ Modified: head/usr.bin/tar/bsdtar.h ============================================================================== --- head/usr.bin/tar/bsdtar.h Sat Feb 6 20:21:03 2010 (r203567) +++ head/usr.bin/tar/bsdtar.h Sat Feb 6 20:27:36 2010 (r203568) @@ -142,16 +142,13 @@ int exclude_from_file(struct bsdtar *, c int excluded(struct bsdtar *, const char *pathname); int include(struct bsdtar *, const char *pattern); int include_from_file(struct bsdtar *, const char *pathname); +int need_report(void); int pathcmp(const char *a, const char *b); 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 *); +const char *tar_i64toa(int64_t); void tar_mode_c(struct bsdtar *bsdtar); void tar_mode_r(struct bsdtar *bsdtar); void tar_mode_t(struct bsdtar *bsdtar); Modified: head/usr.bin/tar/read.c ============================================================================== --- head/usr.bin/tar/read.c Sat Feb 6 20:21:03 2010 (r203567) +++ head/usr.bin/tar/read.c Sat Feb 6 20:27:36 2010 (r203568) @@ -70,6 +70,12 @@ __FBSDID("$FreeBSD$"); #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); @@ -84,22 +90,40 @@ 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) +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; + uint64_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: %s bytes, compression %d%%;", + tar_i64toa(comp), (int)((uncomp - comp) * 100 / uncomp)); + fprintf(stderr, " Out: %d files, %s bytes\n", + archive_file_count(a), tar_i64toa(uncomp)); + } + if (entry != NULL) { + safe_fprintf(stderr, "Current: %s", + archive_entry_pathname(entry)); + fprintf(stderr, " (%s bytes)\n", + tar_i64toa(archive_entry_size(entry))); + } } /* @@ -108,6 +132,7 @@ progress_func(void * cookie) static void read_archive(struct bsdtar *bsdtar, char mode) { + struct progress_data progress_data; FILE *out; struct archive *a; struct archive_entry *entry; @@ -140,8 +165,10 @@ read_archive(struct bsdtar *bsdtar, char 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) { @@ -161,6 +188,7 @@ read_archive(struct bsdtar *bsdtar, char break; r = archive_read_next_header(a, &entry); + progress_data.entry = entry; if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_OK) @@ -268,10 +296,7 @@ read_archive(struct bsdtar *bsdtar, char 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); Modified: head/usr.bin/tar/util.c ============================================================================== --- head/usr.bin/tar/util.c Sat Feb 6 20:21:03 2010 (r203567) +++ head/usr.bin/tar/util.c Sat Feb 6 20:27:36 2010 (r203568) @@ -559,6 +559,28 @@ edit_pathname(struct bsdtar *bsdtar, str } /* + * It would be nice to just use printf() for formatting large numbers, + * but the compatibility problems are quite a headache. Hence the + * following simple utility function. + */ +const char * +tar_i64toa(int64_t n0) +{ + static char buff[24]; + int64_t n = n0 < 0 ? -n0 : n0; + char *p = buff + sizeof(buff); + + *--p = '\0'; + do { + *--p = '0' + (int)(n % 10); + n /= 10; + } while (n > 0); + if (n0 < 0) + *--p = '-'; + return p; +} + +/* * Like strcmp(), but try to be a little more aware of the fact that * we're comparing two paths. Right now, it just handles leading * "./" and trailing '/' specially, so that "a/b/" == "./a/b" Modified: head/usr.bin/tar/write.c ============================================================================== --- head/usr.bin/tar/write.c Sat Feb 6 20:21:03 2010 (r203567) +++ head/usr.bin/tar/write.c Sat Feb 6 20:27:36 2010 (r203568) @@ -127,10 +127,12 @@ static void archive_names_from_file(st struct archive *a); static int archive_names_from_file_helper(struct bsdtar *bsdtar, const char *line); -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 *, @@ -414,9 +416,6 @@ write_archive(struct archive *a, struct 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) bsdtar_errc(1, 0, "cannot allocate memory"); @@ -488,14 +487,11 @@ cleanup: bsdtar->diskreader = NULL; if (bsdtar->option_totals) { - fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n", - (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a)); + fprintf(stderr, "Total bytes written: %s\n", + tar_i64toa(archive_position_compressed(a))); } archive_write_finish(a); - - /* Restore old SIGINFO + SIGUSR1 handlers. */ - siginfo_done(bsdtar); } /* @@ -591,10 +587,8 @@ append_archive(struct bsdtar *bsdtar, st 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) { @@ -611,7 +605,7 @@ append_archive(struct bsdtar *bsdtar, st 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); } @@ -625,7 +619,8 @@ append_archive(struct bsdtar *bsdtar, st /* 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; @@ -633,7 +628,8 @@ copy_file_data(struct bsdtar *bsdtar, st 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); @@ -839,14 +835,8 @@ write_hierarchy(struct bsdtar *bsdtar, s 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); @@ -916,6 +906,28 @@ write_entry_backend(struct bsdtar *bsdta close(fd); } +static void +report_write(struct bsdtar *bsdtar, struct archive *a, + struct archive_entry *entry, int64_t progress) +{ + uint64_t comp, uncomp; + if (bsdtar->verbose) + fprintf(stderr, "\n"); + comp = archive_position_compressed(a); + uncomp = archive_position_uncompressed(a); + fprintf(stderr, "In: %d files, %s bytes;", + archive_file_count(a), tar_i64toa(uncomp)); + fprintf(stderr, + " Out: %s bytes, compression %d%%\n", + tar_i64toa(comp), (int)((uncomp - comp) * 100 / uncomp)); + /* Can't have two calls to tar_i64toa() pending, so split the output. */ + safe_fprintf(stderr, "Current: %s (%s", + archive_entry_pathname(entry), + tar_i64toa(progress)); + fprintf(stderr, "/%s bytes)\n", + tar_i64toa(archive_entry_size(entry))); +} + /* Helper function to copy file to archive. */ static int @@ -928,7 +940,8 @@ write_file_data(struct bsdtar *bsdtar, s 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);