X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fcreate.c;h=645bcb65428634659bd36f54490ce291f43dbd07;hb=f6458a827ae7a2c41616490f653714068072b257;hp=6381f9fe6ff71d14e01b87484e8f51b277c190f9;hpb=d659cbaccdc1f3279c49107cf15f15a639738529;p=chaz%2Ftar diff --git a/src/create.c b/src/create.c index 6381f9f..645bcb6 100644 --- a/src/create.c +++ b/src/create.c @@ -350,16 +350,20 @@ string_to_chars (char const *str, char *p, size_t s) } -/* A file is not dumpable if +/* A file is considered dumpable if it is sparse and both --sparse and --totals + are specified. + Otherwise, it is dumpable unless any of the following conditions occur: + a) it is empty *and* world-readable, or b) current archive is /dev/null */ bool file_dumpable_p (struct tar_stat_info *st) { - return !(dev_null_output - || (st->archive_file_size == 0 - && (st->stat.st_mode & MODE_R) == MODE_R)); + if (dev_null_output) + return totals_option && sparse_option && sparse_file_p (st); + return !(st->archive_file_size == 0 + && (st->stat.st_mode & MODE_R) == MODE_R); } @@ -694,7 +698,7 @@ start_header (struct tar_stat_info *st) } { - struct timespec mtime = get_stat_mtime (&st->stat); + struct timespec mtime = st->mtime; if (archive_format == POSIX_FORMAT) { if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec @@ -743,8 +747,8 @@ start_header (struct tar_stat_info *st) else if (incremental_option) if (archive_format == OLDGNU_FORMAT || archive_format == GNU_FORMAT) { - TIME_TO_CHARS (st->stat.st_atime, header->oldgnu_header.atime); - TIME_TO_CHARS (st->stat.st_ctime, header->oldgnu_header.ctime); + TIME_TO_CHARS (st->atime.tv_sec, header->oldgnu_header.atime); + TIME_TO_CHARS (st->ctime.tv_sec, header->oldgnu_header.ctime); } header->header.typeflag = archive_format == V7_FORMAT ? AREGTYPE : REGTYPE; @@ -950,9 +954,8 @@ dump_regular_finish (int fd, struct tar_stat_info *st, { stat_diag (st->orig_file_name); } - else if (final_stat.st_ctime != original_ctime.tv_sec - || (get_stat_ctime (&final_stat).tv_nsec - != original_ctime.tv_nsec)) + else if (timespec_cmp (get_stat_ctime (&final_stat), original_ctime) + != 0) { WARN ((0, 0, _("%s: file changed as we read it"), quotearg_colon (st->orig_file_name))); @@ -1026,7 +1029,7 @@ dump_dir0 (char *directory, if (!blk) return; - if (incremental_option) + if (incremental_option && archive_format != POSIX_FORMAT) blk->header.typeflag = GNUTYPE_DUMPDIR; else /* if (standard_option) */ blk->header.typeflag = DIRTYPE; @@ -1037,51 +1040,54 @@ dump_dir0 (char *directory, finish_header (st, blk, block_ordinal); else if (gnu_list_name->dir_contents) { - off_t size_left; - off_t totsize; - size_t bufsize; - ssize_t count; - const char *buffer, *p_buffer; - - block_ordinal = current_block_ordinal (); - buffer = gnu_list_name->dir_contents; /* FOO */ - totsize = 0; - if (buffer) - for (p_buffer = buffer; *p_buffer; ) - { - size_t size = strlen (p_buffer) + 1; - totsize += size; - p_buffer += size; - } - totsize++; - OFF_TO_CHARS (totsize, blk->header.size); - finish_header (st, blk, block_ordinal); - p_buffer = buffer; - size_left = totsize; - while (size_left > 0) + if (archive_format == POSIX_FORMAT) { - if (multi_volume_option) - { - assign_string (&save_name, st->orig_file_name); - save_sizeleft = size_left; - save_totsize = totsize; - } - blk = find_next_block (); - bufsize = available_space_after (blk); - if (size_left < bufsize) + xheader_store ("GNU.dumpdir", st, gnu_list_name->dir_contents); + finish_header (st, blk, block_ordinal); + } + else + { + off_t size_left; + off_t totsize; + size_t bufsize; + ssize_t count; + const char *buffer, *p_buffer; + + block_ordinal = current_block_ordinal (); + buffer = gnu_list_name->dir_contents; /* FOO */ + if (buffer) + totsize = dumpdir_size (buffer); + else + totsize = 0; + OFF_TO_CHARS (totsize, blk->header.size); + finish_header (st, blk, block_ordinal); + p_buffer = buffer; + size_left = totsize; + while (size_left > 0) { - bufsize = size_left; - count = bufsize % BLOCKSIZE; - if (count) - memset (blk->buffer + size_left, 0, BLOCKSIZE - count); + if (multi_volume_option) + { + assign_string (&save_name, st->orig_file_name); + save_sizeleft = size_left; + save_totsize = totsize; + } + blk = find_next_block (); + bufsize = available_space_after (blk); + if (size_left < bufsize) + { + bufsize = size_left; + count = bufsize % BLOCKSIZE; + if (count) + memset (blk->buffer + size_left, 0, BLOCKSIZE - count); + } + memcpy (blk->buffer, p_buffer, bufsize); + size_left -= bufsize; + p_buffer += bufsize; + set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE); } - memcpy (blk->buffer, p_buffer, bufsize); - size_left -= bufsize; - p_buffer += bufsize; - set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE); + if (multi_volume_option) + assign_string (&save_name, 0); } - if (multi_volume_option) - assign_string (&save_name, 0); return; } } @@ -1404,9 +1410,9 @@ dump_file0 (struct tar_stat_info *st, char *p, return; } st->archive_file_size = st->stat.st_size; - original_ctime = get_stat_ctime (&st->stat); - restore_times[0] = get_stat_atime (&st->stat); - restore_times[1] = get_stat_mtime (&st->stat); + st->atime = restore_times[0] = get_stat_atime (&st->stat); + st->mtime = restore_times[1] = get_stat_mtime (&st->stat); + st->ctime = original_ctime = get_stat_ctime (&st->stat); #ifdef S_ISHIDDEN if (S_ISHIDDEN (st->stat.st_mode)) @@ -1429,8 +1435,8 @@ dump_file0 (struct tar_stat_info *st, char *p, if (!(incremental_option && !is_individual_file (p)) && !S_ISDIR (st->stat.st_mode) - && OLDER_STAT_TIME (st->stat, m) - && (!after_date_option || OLDER_STAT_TIME (st->stat, c))) + && OLDER_TAR_STAT_TIME (*st, m) + && (!after_date_option || OLDER_TAR_STAT_TIME (*st, c))) { if (!incremental_option && verbose_option) WARN ((0, 0, _("%s: file is unchanged; not dumped"), @@ -1486,7 +1492,7 @@ dump_file0 (struct tar_stat_info *st, char *p, else fd = -1; - if (sparse_option && sparse_file_p (st)) + if (fd != -1 && sparse_option && sparse_file_p (st)) { status = sparse_dump_file (fd, st); if (status == dump_status_not_implemented) @@ -1619,5 +1625,7 @@ dump_file (char *p, int top_level, dev_t parent_device) struct tar_stat_info st; tar_stat_init (&st); dump_file0 (&st, p, top_level, parent_device); + if (listed_incremental_option) + update_parent_directory (p); tar_stat_destroy (&st); }