summaryrefslogtreecommitdiff
path: root/tar/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'tar/read.c')
-rw-r--r--tar/read.c153
1 files changed, 44 insertions, 109 deletions
diff --git a/tar/read.c b/tar/read.c
index e2bacad9573c2..e94cb3da8ac70 100644
--- a/tar/read.c
+++ b/tar/read.c
@@ -39,9 +39,19 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.40 2008/08/21 06:41:14 kientzle E
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -74,8 +84,6 @@ struct progress_data {
struct archive_entry *entry;
};
-static void list_item_verbose(struct bsdtar *, FILE *,
- struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode, struct archive *);
static int unmatched_inclusions_warn(struct archive *matching, const char *);
@@ -112,7 +120,7 @@ tar_mode_x(struct bsdtar *bsdtar)
static void
progress_func(void *cookie)
{
- struct progress_data *progress_data = cookie;
+ struct progress_data *progress_data = (struct progress_data *)cookie;
struct bsdtar *bsdtar = progress_data->bsdtar;
struct archive *a = progress_data->archive;
struct archive_entry *entry = progress_data->entry;
@@ -182,7 +190,7 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
if (reader_options != NULL) {
char *p;
/* Set default read options. */
- p = malloc(sizeof(IGNORE_WRONG_MODULE_NAME)
+ p = (char *)malloc(sizeof(IGNORE_WRONG_MODULE_NAME)
+ strlen(reader_options) + 1);
if (p == NULL)
lafe_errc(1, errno, "Out of memory");
@@ -201,6 +209,17 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
}
if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
lafe_errc(1, 0, "%s", archive_error_string(a));
+ if (bsdtar->option_ignore_zeros)
+ if (archive_read_set_options(a,
+ "read_concatenated_archives") != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(a));
+ if (bsdtar->passphrase != NULL)
+ r = archive_read_add_passphrase(a, bsdtar->passphrase);
+ else
+ r = archive_read_set_passphrase_callback(a, bsdtar,
+ &passphrase_callback);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(a));
if (archive_read_open_filename(a, bsdtar->filename,
bsdtar->bytes_per_block))
lafe_errc(1, 0, "Error opening archive: %s",
@@ -226,8 +245,15 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
#endif
}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (mode == 'x' && bsdtar->option_stdout) {
+ _setmode(1, _O_BINARY);
+ }
+#endif
+
for (;;) {
/* Support --fast-read option */
+ const char *p;
if (bsdtar->option_fast_read &&
archive_match_path_unmatched_inclusions(bsdtar->matching) == 0)
break;
@@ -247,6 +273,12 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
}
if (r == ARCHIVE_FATAL)
break;
+ p = archive_entry_pathname(entry);
+ if (p == NULL || p[0] == '\0') {
+ lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping.");
+ bsdtar->return_value = 1;
+ continue;
+ }
if (bsdtar->uid >= 0) {
archive_entry_set_uid(entry, bsdtar->uid);
@@ -318,11 +350,14 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
!yes("extract '%s'", archive_entry_pathname(entry)))
continue;
- /*
- * Format here is from SUSv2, including the
- * deferred '\n'.
- */
- if (bsdtar->verbose) {
+ if (bsdtar->verbose > 1) {
+ /* GNU tar uses -tv format with -xvv */
+ safe_fprintf(stderr, "x ");
+ list_item_verbose(bsdtar, stderr, entry);
+ fflush(stderr);
+ } else if (bsdtar->verbose > 0) {
+ /* Format follows SUSv2, including the
+ * deferred '\n'. */
safe_fprintf(stderr, "x %s",
archive_entry_pathname(entry));
fflush(stderr);
@@ -366,106 +401,6 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
}
-/*
- * Display information about the current file.
- *
- * The format here roughly duplicates the output of 'ls -l'.
- * This is based on SUSv2, where 'tar tv' is documented as
- * listing additional information in an "unspecified format,"
- * and 'pax -l' is documented as using the same format as 'ls -l'.
- */
-static void
-list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
-{
- char tmp[100];
- size_t w;
- const char *p;
- const char *fmt;
- time_t tim;
- static time_t now;
-
- /*
- * We avoid collecting the entire list in memory at once by
- * listing things as we see them. However, that also means we can't
- * just pre-compute the field widths. Instead, we start with guesses
- * and just widen them as necessary. These numbers are completely
- * arbitrary.
- */
- if (!bsdtar->u_width) {
- bsdtar->u_width = 6;
- bsdtar->gs_width = 13;
- }
- if (!now)
- time(&now);
- fprintf(out, "%s %d ",
- archive_entry_strmode(entry),
- 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)archive_entry_uid(entry));
- p = tmp;
- }
- w = strlen(p);
- if (w > bsdtar->u_width)
- bsdtar->u_width = w;
- fprintf(out, "%-*s ", (int)bsdtar->u_width, p);
-
- /* Use gname if it's present, else gid. */
- p = archive_entry_gname(entry);
- if (p != NULL && p[0] != '\0') {
- fprintf(out, "%s", p);
- w = strlen(p);
- } else {
- sprintf(tmp, "%lu",
- (unsigned long)archive_entry_gid(entry));
- w = strlen(tmp);
- fprintf(out, "%s", tmp);
- }
-
- /*
- * Print device number or file size, right-aligned so as to make
- * total width of group and devnum/filesize fields be gs_width.
- * If gs_width is too small, grow it.
- */
- if (archive_entry_filetype(entry) == AE_IFCHR
- || archive_entry_filetype(entry) == AE_IFBLK) {
- sprintf(tmp, "%lu,%lu",
- (unsigned long)archive_entry_rdevmajor(entry),
- (unsigned long)archive_entry_rdevminor(entry));
- } else {
- 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 = archive_entry_mtime(entry);
-#define HALF_YEAR (time_t)365 * 86400 / 2
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define DAY_FMT "%d" /* Windows' strftime function does not support %e format. */
-#else
-#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));
-
- /* Extra information for links. */
- if (archive_entry_hardlink(entry)) /* Hard link */
- safe_fprintf(out, " link to %s",
- archive_entry_hardlink(entry));
- else if (archive_entry_symlink(entry)) /* Symbolic link */
- safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
-}
-
static int
unmatched_inclusions_warn(struct archive *matching, const char *msg)
{