static void progress_func(void *cookie) { 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; int compression; if (!need_report()) return; if (bsdtar->verbose) fprintf(stderr, "\n"); if (a != NULL) { comp = archive_position_compressed(a); uncomp = archive_position_uncompressed(a); if (comp > uncomp) compression = 0; else compression = (int)((uncomp - comp) * 100 / uncomp); fprintf(stderr, "In: %s bytes, compression %d%%;", tar_i64toa(comp), compression); 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))); } }
/* Helper function to copy data between archives. */ static int copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina, struct archive_entry *entry) { ssize_t bytes_read; ssize_t bytes_written; int64_t progress = 0; bytes_read = archive_read_data(ina, bsdtar->buff, bsdtar->buff_size); while (bytes_read > 0) { if (need_report()) report_write(bsdtar, a, entry, progress); bytes_written = archive_write_data(a, bsdtar->buff, bytes_read); if (bytes_written < bytes_read) { lafe_warnc(0, "%s", archive_error_string(a)); return (-1); } progress += bytes_written; bytes_read = archive_read_data(ina, bsdtar->buff, bsdtar->buff_size); } return (0); }
static int append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina) { struct archive_entry *in_entry; int e; while (ARCHIVE_OK == (e = archive_read_next_header(ina, &in_entry))) { if (archive_match_excluded(bsdtar->matching, in_entry)) continue; if (bsdtar->option_interactive && !yes("copy '%s'", archive_entry_pathname(in_entry))) continue; if (bsdtar->verbose > 1) { safe_fprintf(stderr, "a "); list_item_verbose(bsdtar, stderr, in_entry); } else if (bsdtar->verbose > 0) safe_fprintf(stderr, "a %s", archive_entry_pathname(in_entry)); if (need_report()) report_write(bsdtar, a, in_entry, 0); e = archive_write_header(a, in_entry); if (e != ARCHIVE_OK) { if (!bsdtar->verbose) lafe_warnc(0, "%s: %s", archive_entry_pathname(in_entry), archive_error_string(a)); else fprintf(stderr, ": %s", archive_error_string(a)); } if (e == ARCHIVE_FATAL) exit(1); if (e >= ARCHIVE_WARN) { if (archive_entry_size(in_entry) == 0) archive_read_data_skip(ina); else if (copy_file_data_block(bsdtar, a, ina, in_entry)) exit(1); } if (bsdtar->verbose) fprintf(stderr, "\n"); } return (e == ARCHIVE_EOF ? ARCHIVE_OK : e); }
/* Helper function to copy file to archive. */ static int write_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive_entry *entry, int fd, size_t align) { ssize_t bytes_read; ssize_t bytes_written; int64_t progress = 0; size_t buff_size; char *buff = bsdtar->buff; /* Round 'buff' up to the next multiple of 'align' and reduce * 'buff_size' accordingly. */ buff = (char *)((((uintptr_t)buff + align - 1) / align) * align); buff_size = bsdtar->buff + bsdtar->buff_size - buff; buff_size = (buff_size / align) * align; bytes_read = read(fd, buff, buff_size); while (bytes_read > 0) { if (need_report()) report_write(bsdtar, a, entry, progress); bytes_written = archive_write_data(a, buff, bytes_read); if (bytes_written < 0) { /* Write failed; this is bad */ lafe_warnc(0, "%s", archive_error_string(a)); return (-1); } if (bytes_written < bytes_read) { /* Write was truncated; warn but continue. */ lafe_warnc(0, "%s: Truncated write; file may have grown while being archived.", archive_entry_pathname(entry)); return (0); } progress += bytes_written; bytes_read = read(fd, buff, buff_size); } return 0; }
/* Helper function to copy file to archive. */ static int copy_file_data_block(struct bsdtar *bsdtar, struct archive *a, struct archive *in_a, struct archive_entry *entry) { size_t bytes_read; ssize_t bytes_written; int64_t offset, progress = 0; char *null_buff = NULL; const void *buff; int r; while ((r = archive_read_data_block(in_a, &buff, &bytes_read, &offset)) == ARCHIVE_OK) { if (need_report()) report_write(bsdtar, a, entry, progress); if (offset > progress) { int64_t sparse = offset - progress; size_t ns; if (null_buff == NULL) { null_buff = bsdtar->buff; memset(null_buff, 0, bsdtar->buff_size); } while (sparse > 0) { if (sparse > (int64_t)bsdtar->buff_size) ns = bsdtar->buff_size; else ns = (size_t)sparse; bytes_written = archive_write_data(a, null_buff, ns); if (bytes_written < 0) { /* Write failed; this is bad */ lafe_warnc(0, "%s", archive_error_string(a)); return (-1); } if ((size_t)bytes_written < ns) { /* Write was truncated; warn but * continue. */ lafe_warnc(0, "%s: Truncated write; file may " "have grown while being archived.", archive_entry_pathname(entry)); return (0); } progress += bytes_written; sparse -= bytes_written; } } bytes_written = archive_write_data(a, buff, bytes_read); if (bytes_written < 0) { /* Write failed; this is bad */ lafe_warnc(0, "%s", archive_error_string(a)); return (-1); } if ((size_t)bytes_written < bytes_read) { /* Write was truncated; warn but continue. */ lafe_warnc(0, "%s: Truncated write; file may have grown " "while being archived.", archive_entry_pathname(entry)); return (0); } progress += bytes_written; } if (r < ARCHIVE_WARN) { lafe_warnc(archive_errno(a), "%s", archive_error_string(a)); return (-1); } return (0); }