summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/tar/write.c')
-rw-r--r--usr.bin/tar/write.c337
1 files changed, 204 insertions, 133 deletions
diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c
index efc94de..31005eb 100644
--- a/usr.bin/tar/write.c
+++ b/usr.bin/tar/write.c
@@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-#ifdef HAVE_SYS_ACL_H
-#include <sys/acl.h>
-#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -47,12 +44,12 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#ifdef HAVE_FNMATCH_H
-#include <fnmatch.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
@@ -73,6 +70,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>
@@ -85,6 +85,8 @@ __FBSDID("$FreeBSD$");
#endif
#include "bsdtar.h"
+#include "err.h"
+#include "line_reader.h"
#include "tree.h"
/* Size of buffer for holding file data prior to writing. */
@@ -124,12 +126,12 @@ static int append_archive_filename(struct bsdtar *,
struct archive *, const char *fname);
static void archive_names_from_file(struct bsdtar *bsdtar,
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 *,
@@ -139,6 +141,23 @@ static int write_file_data(struct bsdtar *, struct archive *,
static void write_hierarchy(struct bsdtar *, struct archive *,
const char *);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+/* Not a full lseek() emulation, but enough for our needs here. */
+static int
+seek_file(int fd, int64_t offset, int whence)
+{
+ LARGE_INTEGER distance;
+ (void)whence; /* UNUSED */
+ distance.QuadPart = offset;
+ return (SetFilePointerEx((HANDLE)_get_osfhandle(fd),
+ distance, NULL, FILE_BEGIN) ? 1 : -1);
+}
+#define open _open
+#define close _close
+#define read _read
+#define lseek seek_file
+#endif
+
void
tar_mode_c(struct bsdtar *bsdtar)
{
@@ -146,7 +165,7 @@ tar_mode_c(struct bsdtar *bsdtar)
int r;
if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
- bsdtar_errc(bsdtar, 1, 0, "no files or directories specified");
+ bsdtar_errc(1, 0, "no files or directories specified");
a = archive_write_new();
@@ -161,7 +180,7 @@ tar_mode_c(struct bsdtar *bsdtar)
fprintf(stderr, "Can't use format %s: %s\n",
bsdtar->create_format,
archive_error_string(a));
- usage(bsdtar);
+ usage();
}
/*
@@ -182,40 +201,39 @@ tar_mode_c(struct bsdtar *bsdtar)
} else {
switch (bsdtar->create_compression) {
case 0:
- archive_write_set_compression_none(a);
+ r = archive_write_set_compression_none(a);
break;
-#ifdef HAVE_LIBBZ2
case 'j': case 'y':
- archive_write_set_compression_bzip2(a);
+ r = archive_write_set_compression_bzip2(a);
break;
-#endif
-#ifdef HAVE_LIBLZMA
case 'J':
- archive_write_set_compression_xz(a);
+ r = archive_write_set_compression_xz(a);
break;
case OPTION_LZMA:
- archive_write_set_compression_lzma(a);
+ r = archive_write_set_compression_lzma(a);
break;
-#endif
-#ifdef HAVE_LIBZ
case 'z':
- archive_write_set_compression_gzip(a);
+ r = archive_write_set_compression_gzip(a);
break;
-#endif
case 'Z':
- archive_write_set_compression_compress(a);
+ r = archive_write_set_compression_compress(a);
break;
default:
- bsdtar_errc(bsdtar, 1, 0,
+ bsdtar_errc(1, 0,
"Unrecognized compression option -%c",
bsdtar->create_compression);
}
+ if (r != ARCHIVE_OK) {
+ bsdtar_errc(1, 0,
+ "Unsupported compression option -%c",
+ bsdtar->create_compression);
+ }
}
if (ARCHIVE_OK != archive_write_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_OK != archive_write_open_file(a, bsdtar->filename))
- bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
+ bsdtar_errc(1, 0, "%s", archive_error_string(a));
write_archive(a, bsdtar);
}
@@ -226,7 +244,7 @@ tar_mode_c(struct bsdtar *bsdtar)
void
tar_mode_r(struct bsdtar *bsdtar)
{
- off_t end_offset;
+ int64_t end_offset;
int format;
struct archive *a;
struct archive_entry *entry;
@@ -237,9 +255,13 @@ tar_mode_r(struct bsdtar *bsdtar)
format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
+#if defined(__BORLANDC__)
+ bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT);
+#else
bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT, 0666);
+#endif
if (bsdtar->fd < 0)
- bsdtar_errc(bsdtar, 1, errno,
+ bsdtar_errc(1, errno,
"Cannot open %s", bsdtar->filename);
a = archive_read_new();
@@ -248,14 +270,14 @@ tar_mode_r(struct bsdtar *bsdtar)
archive_read_support_format_gnutar(a);
r = archive_read_open_fd(a, bsdtar->fd, 10240);
if (r != ARCHIVE_OK)
- bsdtar_errc(bsdtar, 1, archive_errno(a),
+ bsdtar_errc(1, archive_errno(a),
"Can't read archive %s: %s", bsdtar->filename,
archive_error_string(a));
while (0 == archive_read_next_header(a, &entry)) {
if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
archive_read_finish(a);
close(bsdtar->fd);
- bsdtar_errc(bsdtar, 1, 0,
+ bsdtar_errc(1, 0,
"Cannot append to compressed archive.");
}
/* Keep going until we hit end-of-archive */
@@ -284,7 +306,7 @@ tar_mode_r(struct bsdtar *bsdtar)
format &= ARCHIVE_FORMAT_BASE_MASK;
if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
&& format != ARCHIVE_FORMAT_EMPTY) {
- bsdtar_errc(bsdtar, 1, 0,
+ bsdtar_errc(1, 0,
"Format %s is incompatible with the archive %s.",
bsdtar->create_format, bsdtar->filename);
}
@@ -300,11 +322,12 @@ tar_mode_r(struct bsdtar *bsdtar)
format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
archive_write_set_format(a, format);
}
- lseek(bsdtar->fd, end_offset, SEEK_SET); /* XXX check return val XXX */
+ if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
+ bsdtar_errc(1, errno, "Could not seek to archive end");
if (ARCHIVE_OK != archive_write_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_OK != archive_write_open_fd(a, bsdtar->fd))
- bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
+ bsdtar_errc(1, 0, "%s", archive_error_string(a));
write_archive(a, bsdtar); /* XXX check return val XXX */
@@ -315,7 +338,7 @@ tar_mode_r(struct bsdtar *bsdtar)
void
tar_mode_u(struct bsdtar *bsdtar)
{
- off_t end_offset;
+ int64_t end_offset;
struct archive *a;
struct archive_entry *entry;
int format;
@@ -332,7 +355,7 @@ tar_mode_u(struct bsdtar *bsdtar)
bsdtar->fd = open(bsdtar->filename, O_RDWR);
if (bsdtar->fd < 0)
- bsdtar_errc(bsdtar, 1, errno,
+ bsdtar_errc(1, errno,
"Cannot open %s", bsdtar->filename);
a = archive_read_new();
@@ -342,7 +365,7 @@ tar_mode_u(struct bsdtar *bsdtar)
if (archive_read_open_fd(a, bsdtar->fd,
bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
- bsdtar_errc(bsdtar, 1, 0,
+ bsdtar_errc(1, 0,
"Can't open %s: %s", bsdtar->filename,
archive_error_string(a));
}
@@ -352,7 +375,7 @@ tar_mode_u(struct bsdtar *bsdtar)
if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
archive_read_finish(a);
close(bsdtar->fd);
- bsdtar_errc(bsdtar, 1, 0,
+ bsdtar_errc(1, 0,
"Cannot append to compressed archive.");
}
add_dir_list(bsdtar, archive_entry_pathname(entry),
@@ -382,12 +405,12 @@ tar_mode_u(struct bsdtar *bsdtar)
bsdtar->bytes_per_block);
} else
archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);
- lseek(bsdtar->fd, end_offset, SEEK_SET);
- ftruncate(bsdtar->fd, end_offset);
+ if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
+ bsdtar_errc(1, errno, "Could not seek to archive end");
if (ARCHIVE_OK != archive_write_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_OK != archive_write_open_fd(a, bsdtar->fd))
- bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
+ bsdtar_errc(1, 0, "%s", archive_error_string(a));
write_archive(a, bsdtar);
@@ -413,19 +436,16 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
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(bsdtar, 1, 0, "cannot allocate memory");
+ bsdtar_errc(1, 0, "cannot allocate memory");
if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL)
- bsdtar_errc(bsdtar, 1, 0, "cannot create link resolver");
+ bsdtar_errc(1, 0, "cannot create link resolver");
archive_entry_linkresolver_set_strategy(bsdtar->resolver,
archive_format(a));
if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
- bsdtar_errc(bsdtar, 1, 0, "Cannot create read_disk object");
+ bsdtar_errc(1, 0, "Cannot create read_disk object");
archive_read_disk_set_standard_lookup(bsdtar->diskreader);
if (bsdtar->names_from_file != NULL)
@@ -439,7 +459,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
bsdtar->argv++;
arg = *bsdtar->argv;
if (arg == NULL) {
- bsdtar_warnc(bsdtar, 1, 0,
+ bsdtar_warnc(0, "%s",
"Missing argument for -C");
bsdtar->return_value = 1;
goto cleanup;
@@ -454,12 +474,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
arg + 1) != 0)
break;
} else
-#if defined(_WIN32) && !defined(__CYGWIN__)
- write_hierarchy_win(bsdtar, a, arg,
- write_hierarchy);
-#else
write_hierarchy(bsdtar, a, arg);
-#endif
}
bsdtar->argv++;
}
@@ -474,7 +489,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
}
if (archive_write_close(a)) {
- bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ bsdtar_warnc(0, "%s", archive_error_string(a));
bsdtar->return_value = 1;
}
@@ -487,14 +502,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);
}
/*
@@ -504,36 +516,34 @@ cleanup:
* cause the next line to be a directory to pass to chdir(). If
* --null is specified, then a line "-C" is just another filename.
*/
-void
+static void
archive_names_from_file(struct bsdtar *bsdtar, struct archive *a)
{
- bsdtar->archive = a;
+ struct lafe_line_reader *lr;
+ const char *line;
bsdtar->next_line_is_dir = 0;
- process_lines(bsdtar, bsdtar->names_from_file,
- archive_names_from_file_helper);
+
+ lr = lafe_line_reader(bsdtar->names_from_file, bsdtar->option_null);
+ while ((line = lafe_line_reader_next(lr)) != NULL) {
+ if (bsdtar->next_line_is_dir) {
+ set_chdir(bsdtar, line);
+ bsdtar->next_line_is_dir = 0;
+ } else if (!bsdtar->option_null && strcmp(line, "-C") == 0)
+ bsdtar->next_line_is_dir = 1;
+ else {
+ if (*line != '/')
+ do_chdir(bsdtar); /* Handle a deferred -C */
+ write_hierarchy(bsdtar, a, line);
+ }
+ }
+ lafe_line_reader_free(lr);
if (bsdtar->next_line_is_dir)
- bsdtar_errc(bsdtar, 1, errno,
+ bsdtar_errc(1, errno,
"Unexpected end of filename list; "
"directory expected after -C");
}
-static int
-archive_names_from_file_helper(struct bsdtar *bsdtar, const char *line)
-{
- if (bsdtar->next_line_is_dir) {
- set_chdir(bsdtar, line);
- bsdtar->next_line_is_dir = 0;
- } else if (!bsdtar->option_null && strcmp(line, "-C") == 0)
- bsdtar->next_line_is_dir = 1;
- else {
- if (*line != '/')
- do_chdir(bsdtar); /* Handle a deferred -C */
- write_hierarchy(bsdtar, bsdtar->archive, line);
- }
- return (0);
-}
-
/*
* Copy from specified archive to current archive. Returns non-zero
* for write errors (which force us to terminate the entire archiving
@@ -555,15 +565,15 @@ append_archive_filename(struct bsdtar *bsdtar, struct archive *a,
archive_read_support_format_all(ina);
archive_read_support_compression_all(ina);
if (archive_read_open_file(ina, filename, 10240)) {
- bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(ina));
+ bsdtar_warnc(0, "%s", archive_error_string(ina));
bsdtar->return_value = 1;
return (0);
}
rc = append_archive(bsdtar, a, ina);
- if (archive_errno(ina)) {
- bsdtar_warnc(bsdtar, 0, "Error reading archive %s: %s",
+ if (rc != ARCHIVE_OK) {
+ bsdtar_warnc(0, "Error reading archive %s: %s",
filename, archive_error_string(ina));
bsdtar->return_value = 1;
}
@@ -582,7 +592,7 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
if (!new_enough(bsdtar, archive_entry_pathname(in_entry),
archive_entry_stat(in_entry)))
continue;
- if (excluded(bsdtar, archive_entry_pathname(in_entry)))
+ if (lafe_excluded(bsdtar->matching, archive_entry_pathname(in_entry)))
continue;
if (bsdtar->option_interactive &&
!yes("copy '%s'", archive_entry_pathname(in_entry)))
@@ -590,15 +600,13 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
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 (!bsdtar->verbose)
- bsdtar_warnc(bsdtar, 0, "%s: %s",
+ bsdtar_warnc(0, "%s: %s",
archive_entry_pathname(in_entry),
archive_error_string(a));
else
@@ -610,7 +618,7 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
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);
}
@@ -624,20 +632,22 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
/* 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 (bytes_written < bytes_read) {
- bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ bsdtar_warnc(0, "%s", archive_error_string(a));
return (-1);
}
progress += bytes_written;
@@ -664,12 +674,12 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
tree = tree_open(path);
if (!tree) {
- bsdtar_warnc(bsdtar, errno, "%s: Cannot open", path);
+ bsdtar_warnc(errno, "%s: Cannot open", path);
bsdtar->return_value = 1;
return;
}
- while ((tree_ret = tree_next(tree))) {
+ while ((tree_ret = tree_next(tree)) != 0) {
int r;
const char *name = tree_current_path(tree);
const struct stat *st = NULL; /* info to use for this entry */
@@ -677,11 +687,11 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
int descend;
if (tree_ret == TREE_ERROR_FATAL)
- bsdtar_errc(bsdtar, 1, tree_errno(tree),
+ bsdtar_errc(1, tree_errno(tree),
"%s: Unable to continue traversing directory tree",
name);
if (tree_ret == TREE_ERROR_DIR) {
- bsdtar_warnc(bsdtar, errno,
+ bsdtar_warnc(errno,
"%s: Couldn't visit directory", name);
bsdtar->return_value = 1;
}
@@ -692,7 +702,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
* If this file/dir is excluded by a filename
* pattern, skip it.
*/
- if (excluded(bsdtar, name))
+ if (lafe_excluded(bsdtar->matching, name))
continue;
/*
@@ -701,7 +711,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
lst = tree_current_lstat(tree);
if (lst == NULL) {
/* Couldn't lstat(); must not exist. */
- bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name);
+ bsdtar_warnc(errno, "%s: Cannot stat", name);
/* Return error if files disappear during traverse. */
bsdtar->return_value = 1;
continue;
@@ -739,17 +749,38 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
}
/*
- * If user has asked us not to cross mount points,
- * then don't descend into into a dir on a different
- * device.
+ * Are we about to cross to a new filesystem?
*/
if (!dev_recorded) {
+ /* This is the initial file system. */
first_dev = lst->st_dev;
dev_recorded = 1;
- }
- if (bsdtar->option_dont_traverse_mounts) {
- if (lst->st_dev != first_dev)
- descend = 0;
+ } else if (lst->st_dev == first_dev) {
+ /* The starting file system is always acceptable. */
+ } else if (descend == 0) {
+ /* We're not descending, so no need to check. */
+ } else if (bsdtar->option_dont_traverse_mounts) {
+ /* User has asked us not to cross mount points. */
+ descend = 0;
+ } else {
+ /* We're prepared to cross a mount point. */
+
+ /* XXX TODO: check whether this filesystem is
+ * synthetic and/or local. Add a new
+ * --local-only option to skip non-local
+ * filesystems. Skip synthetic filesystems
+ * regardless.
+ *
+ * The results should be cached, since
+ * tree.c doesn't usually visit a directory
+ * and the directory contents together. A simple
+ * move-to-front list should perform quite well.
+ *
+ * This is going to be heavily OS dependent:
+ * FreeBSD's statfs() in conjunction with getvfsbyname()
+ * provides all of this; NetBSD's statvfs() does
+ * most of it; other systems will vary.
+ */
}
/*
@@ -771,11 +802,27 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
* calling this so we can pass in an fd and shorten
* the race to query metadata. The linkify dance
* makes this more complex than it might sound. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* TODO: tree.c uses stat(), which is badly broken
+ * on Windows. To fix this, we should
+ * deprecate tree_current_stat() and provide a new
+ * call tree_populate_entry(t, entry). This call
+ * would use stat() internally on POSIX and
+ * GetInfoByFileHandle() internally on Windows.
+ * This would be another step towards a tree-walker
+ * that can be integrated deep into libarchive.
+ * For now, just set st to NULL on Windows;
+ * archive_read_disk_entry_from_file() should
+ * be smart enough to use platform-appropriate
+ * ways to probe file information.
+ */
+ st = NULL;
+#endif
r = archive_read_disk_entry_from_file(bsdtar->diskreader,
entry, -1, st);
if (r != ARCHIVE_OK)
- bsdtar_warnc(bsdtar, archive_errno(bsdtar->diskreader),
- archive_error_string(bsdtar->diskreader));
+ bsdtar_warnc(archive_errno(bsdtar->diskreader),
+ "%s", archive_error_string(bsdtar->diskreader));
if (r < ARCHIVE_WARN)
continue;
@@ -786,7 +833,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
* If this file/dir is flagged "nodump" and we're
* honoring such flags, skip this file/dir.
*/
-#ifdef HAVE_STRUCT_STAT_ST_FLAGS
+#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
/* BSD systems store flags in struct stat */
if (bsdtar->option_honor_nodump &&
(lst->st_flags & UF_NODUMP))
@@ -835,17 +882,11 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
archive_entry_pathname(entry));
/* Non-regular files get archived with zero size. */
- if (!S_ISREG(st->st_mode))
+ if (archive_entry_filetype(entry) != AE_IFREG)
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);
@@ -875,7 +916,7 @@ write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
fd = open(pathname, O_RDONLY);
if (fd == -1) {
if (!bsdtar->verbose)
- bsdtar_warnc(bsdtar, errno,
+ bsdtar_warnc(errno,
"%s: could not open file", pathname);
else
fprintf(stderr, ": %s", strerror(errno));
@@ -886,7 +927,7 @@ write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
e = archive_write_header(a, entry);
if (e != ARCHIVE_OK) {
if (!bsdtar->verbose)
- bsdtar_warnc(bsdtar, 0, "%s: %s",
+ bsdtar_warnc(0, "%s: %s",
archive_entry_pathname(entry),
archive_error_string(a));
else
@@ -915,6 +956,28 @@ write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
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
@@ -923,22 +986,23 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a,
{
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);
if (bytes_written < 0) {
/* Write failed; this is bad */
- bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
+ bsdtar_warnc(0, "%s", archive_error_string(a));
return (-1);
}
if (bytes_written < bytes_read) {
/* Write was truncated; warn but continue. */
- bsdtar_warnc(bsdtar, 0,
+ bsdtar_warnc(0,
"%s: Truncated write; file may have grown while being archived.",
archive_entry_pathname(entry));
return (0);
@@ -952,7 +1016,7 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a,
/*
* Test if the specified file is new enough to include in the archive.
*/
-int
+static int
new_enough(struct bsdtar *bsdtar, const char *path, const struct stat *st)
{
struct archive_dir_entry *p;
@@ -1023,11 +1087,11 @@ add_dir_list(struct bsdtar *bsdtar, const char *path,
p = malloc(sizeof(*p));
if (p == NULL)
- bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read archive directory");
+ bsdtar_errc(1, ENOMEM, "Can't read archive directory");
p->name = strdup(path);
if (p->name == NULL)
- bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read archive directory");
+ bsdtar_errc(1, ENOMEM, "Can't read archive directory");
p->mtime_sec = mtime_sec;
p->mtime_nsec = mtime_nsec;
p->next = NULL;
@@ -1039,25 +1103,32 @@ add_dir_list(struct bsdtar *bsdtar, const char *path,
}
}
-void
+static void
test_for_append(struct bsdtar *bsdtar)
{
struct stat s;
if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
- bsdtar_errc(bsdtar, 1, 0, "no files or directories specified");
+ bsdtar_errc(1, 0, "no files or directories specified");
if (bsdtar->filename == NULL)
- bsdtar_errc(bsdtar, 1, 0, "Cannot append to stdout.");
+ bsdtar_errc(1, 0, "Cannot append to stdout.");
if (bsdtar->create_compression != 0)
- bsdtar_errc(bsdtar, 1, 0,
+ bsdtar_errc(1, 0,
"Cannot append to %s with compression", bsdtar->filename);
if (stat(bsdtar->filename, &s) != 0)
return;
if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode))
- bsdtar_errc(bsdtar, 1, 0,
+ bsdtar_errc(1, 0,
"Cannot append to %s: not a regular file.",
bsdtar->filename);
+
+/* Is this an appropriate check here on Windows? */
+/*
+ if (GetFileType(handle) != FILE_TYPE_DISK)
+ bsdtar_errc(1, 0, "Cannot append");
+*/
+
}
OpenPOWER on IntegriCloud