diff options
Diffstat (limited to 'usr.bin/tar/read.c')
-rw-r--r-- | usr.bin/tar/read.c | 143 |
1 files changed, 81 insertions, 62 deletions
diff --git a/usr.bin/tar/read.c b/usr.bin/tar/read.c index 0756cd8..c0e5bcb 100644 --- a/usr.bin/tar/read.c +++ b/usr.bin/tar/read.c @@ -29,11 +29,6 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif -#ifdef MAJOR_IN_MKDEV -#include <sys/mkdev.h> -#elif defined(MAJOR_IN_SYSMACROS) -#include <sys/sysmacros.h> -#endif #ifdef HAVE_SYS_PARAM_H #include <sys/param.h> #endif @@ -53,6 +48,9 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_PWD_H #include <pwd.h> #endif +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif #include <stdio.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> @@ -68,6 +66,13 @@ __FBSDID("$FreeBSD$"); #endif #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 *); @@ -77,28 +82,48 @@ void tar_mode_t(struct bsdtar *bsdtar) { read_archive(bsdtar, 't'); - unmatched_inclusions_warn(bsdtar, "Not found in archive"); + if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0) + bsdtar->return_value = 1; } 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); + if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0) + bsdtar->return_value = 1; } 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))); + } } /* @@ -107,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; @@ -114,12 +140,13 @@ read_archive(struct bsdtar *bsdtar, char mode) int r; while (*bsdtar->argv) { - include(bsdtar, *bsdtar->argv); + lafe_include(&bsdtar->matching, *bsdtar->argv); bsdtar->argv++; } if (bsdtar->names_from_file != NULL) - include_from_file(bsdtar, bsdtar->names_from_file); + lafe_include_from_file(&bsdtar->matching, + bsdtar->names_from_file, bsdtar->option_null); a = archive_read_new(); if (bsdtar->compress_program != NULL) @@ -128,27 +155,29 @@ read_archive(struct bsdtar *bsdtar, char mode) archive_read_support_compression_all(a); archive_read_support_format_all(a); if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options)) - bsdtar_errc(bsdtar, 1, 0, archive_error_string(a)); + bsdtar_errc(1, 0, "%s", archive_error_string(a)); if (archive_read_open_file(a, bsdtar->filename, bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block : DEFAULT_BYTES_PER_BLOCK)) - bsdtar_errc(bsdtar, 1, 0, "Error opening archive: %s", + bsdtar_errc(1, 0, "Error opening archive: %s", archive_error_string(a)); do_chdir(bsdtar); 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) { #if HAVE_CHROOT if (chroot(".") != 0) - bsdtar_errc(bsdtar, 1, errno, "Can't chroot to \".\""); + bsdtar_errc(1, errno, "Can't chroot to \".\""); #else - bsdtar_errc(bsdtar, 1, 0, + bsdtar_errc(1, 0, "chroot isn't supported on this platform"); #endif } @@ -156,19 +185,20 @@ read_archive(struct bsdtar *bsdtar, char mode) for (;;) { /* Support --fast-read option */ if (bsdtar->option_fast_read && - unmatched_inclusions(bsdtar) == 0) + lafe_unmatched_inclusions(bsdtar->matching) == 0) break; r = archive_read_next_header(a, &entry); + progress_data.entry = entry; if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_OK) - bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); + bsdtar_warnc(0, "%s", archive_error_string(a)); if (r <= ARCHIVE_WARN) bsdtar->return_value = 1; if (r == ARCHIVE_RETRY) { /* Retryable error: try again */ - bsdtar_warnc(bsdtar, 0, "Retrying..."); + bsdtar_warnc(0, "Retrying..."); continue; } if (r == ARCHIVE_FATAL) @@ -209,7 +239,7 @@ read_archive(struct bsdtar *bsdtar, char mode) * rewrite, there would be no way to exclude foo1/bar * while allowing foo2/bar.) */ - if (excluded(bsdtar, archive_entry_pathname(entry))) + if (lafe_excluded(bsdtar->matching, archive_entry_pathname(entry))) continue; /* Excluded by a pattern test. */ if (mode == 't') { @@ -232,17 +262,17 @@ read_archive(struct bsdtar *bsdtar, char mode) r = archive_read_data_skip(a); if (r == ARCHIVE_WARN) { fprintf(out, "\n"); - bsdtar_warnc(bsdtar, 0, "%s", + bsdtar_warnc(0, "%s", archive_error_string(a)); } if (r == ARCHIVE_RETRY) { fprintf(out, "\n"); - bsdtar_warnc(bsdtar, 0, "%s", + bsdtar_warnc(0, "%s", archive_error_string(a)); } if (r == ARCHIVE_FATAL) { fprintf(out, "\n"); - bsdtar_warnc(bsdtar, 0, "%s", + bsdtar_warnc(0, "%s", archive_error_string(a)); bsdtar->return_value = 1; break; @@ -267,10 +297,7 @@ read_archive(struct bsdtar *bsdtar, char mode) 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); @@ -297,7 +324,7 @@ read_archive(struct bsdtar *bsdtar, char mode) r = archive_read_close(a); if (r != ARCHIVE_OK) - bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); + bsdtar_warnc(0, "%s", archive_error_string(a)); if (r <= ARCHIVE_WARN) bsdtar->return_value = 1; @@ -320,7 +347,6 @@ read_archive(struct bsdtar *bsdtar, char mode) static void list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) { - const struct stat *st; char tmp[100]; size_t w; const char *p; @@ -328,8 +354,6 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) time_t tim; static time_t now; - st = archive_entry_stat(entry); - /* * We avoid collecting the entire list in memory at once by * listing things as we see them. However, that also means we can't @@ -345,12 +369,13 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) time(&now); fprintf(out, "%s %d ", archive_entry_strmode(entry), - (int)(st->st_nlink)); + archive_entry_nlink(entry)); /* Use uname if it's present, else uid. */ p = archive_entry_uname(entry); if ((p == NULL) || (*p == '\0')) { - sprintf(tmp, "%lu ", (unsigned long)st->st_uid); + sprintf(tmp, "%lu ", + (unsigned long)archive_entry_uid(entry)); p = tmp; } w = strlen(p); @@ -364,7 +389,8 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) fprintf(out, "%s", p); w = strlen(p); } else { - sprintf(tmp, "%lu", (unsigned long)st->st_gid); + sprintf(tmp, "%lu", + (unsigned long)archive_entry_gid(entry)); w = strlen(tmp); fprintf(out, "%s", tmp); } @@ -374,37 +400,30 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) * total width of group and devnum/filesize fields be gs_width. * If gs_width is too small, grow it. */ - if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { + if (archive_entry_filetype(entry) == AE_IFCHR + || archive_entry_filetype(entry) == AE_IFBLK) { sprintf(tmp, "%lu,%lu", - (unsigned long)major(st->st_rdev), - (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */ + (unsigned long)archive_entry_rdevmajor(entry), + (unsigned long)archive_entry_rdevminor(entry)); } else { - /* - * Note the use of platform-dependent macros to format - * the filesize here. We need the format string and the - * corresponding type for the cast. - */ - sprintf(tmp, BSDTAR_FILESIZE_PRINTF, - (BSDTAR_FILESIZE_TYPE)st->st_size); + strcpy(tmp, tar_i64toa(archive_entry_size(entry))); } if (w + strlen(tmp) >= bsdtar->gs_width) bsdtar->gs_width = w+strlen(tmp)+1; fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp); /* Format the time using 'ls -l' conventions. */ - tim = (time_t)st->st_mtime; + tim = archive_entry_mtime(entry); +#define HALF_YEAR (time_t)365 * 86400 / 2 #if defined(_WIN32) && !defined(__CYGWIN__) - /* Windows' strftime function does not support %e format. */ - if (abs(tim - now) > (365/2)*86400) - fmt = bsdtar->day_first ? "%d %b %Y" : "%b %d %Y"; - else - fmt = bsdtar->day_first ? "%d %b %H:%M" : "%b %d %H:%M"; +#define DAY_FMT "%d" /* Windows' strftime function does not support %e format. */ #else - if (abs(tim - now) > (365/2)*86400) - fmt = bsdtar->day_first ? "%e %b %Y" : "%b %e %Y"; - else - fmt = bsdtar->day_first ? "%e %b %H:%M" : "%b %e %H:%M"; +#define DAY_FMT "%e" /* Day number without leading zeros */ #endif + if (tim < now - HALF_YEAR || tim > now + HALF_YEAR) + fmt = bsdtar->day_first ? DAY_FMT " %b %Y" : "%b " DAY_FMT " %Y"; + else + fmt = bsdtar->day_first ? DAY_FMT " %b %H:%M" : "%b " DAY_FMT " %H:%M"; strftime(tmp, sizeof(tmp), fmt, localtime(&tim)); fprintf(out, " %s ", tmp); safe_fprintf(out, "%s", archive_entry_pathname(entry)); @@ -413,6 +432,6 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) if (archive_entry_hardlink(entry)) /* Hard link */ safe_fprintf(out, " link to %s", archive_entry_hardlink(entry)); - else if (S_ISLNK(st->st_mode)) /* Symbolic link */ + else if (archive_entry_symlink(entry)) /* Symbolic link */ safe_fprintf(out, " -> %s", archive_entry_symlink(entry)); } |