[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-tar] CVS tar "make check" failures on files with ns-resolution
From: |
Paul Eggert |
Subject: |
Re: [Bug-tar] CVS tar "make check" failures on files with ns-resolution time stamps |
Date: |
Mon, 07 Nov 2005 23:22:57 -0800 |
User-agent: |
Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux) |
"Sergey Poznyakoff" <address@hidden> writes:
> For example, judging by the update.at results, on hosts with nanosecond
> precision, tar will in the majority of cases add non-changed directories
> to the archive when updating, which clearly is a bug. Moreover, even
> simple `tar --diff' has strong chances for issuing a lot of spurious
> 'Mod time differs' diagnostics.
Thanks, I see your point. I looked over the draft patch you sent me
and it looked good, except it substituted tar_timespec_cmp for
timespec_cmp in a few places where the time stamps came from the file
system and not from a tar archive, which as I understand it isn't the
intended use of tar_timespec_cmp. These places were OLDER_STAT_TIME,
OLDER_TAR_STAT_TIME, extract_link, and apply_delayed_links. I undid
that part of the draft patch, verified that the result works on
Solaris 8, and installed the following modified patch.
2005-11-07 Sergey Poznyakoff <address@hidden>
and Paul Eggert <address@hidden>
* src/tar.c (NS_PRECISION_FORMAT_MASK): New macro.
(tar_timespec_cmp): New function. Wrapper over
timespec_cmp using the timespec precision provided by the
current archive format.
* src/common.h (tar_timespec_cmp): New declaration.
* src/compare.c (diff_file): Use tar_timespec_cmp.
* src/extract.c (file_newer_p): Likewise.
* src/update.c (update_archive): Likewise.
* tests/truncate.at: Reverted changes
* tests/update.at: Reverted changes
Index: src/common.h
===================================================================
RCS file: /cvsroot/tar/tar/src/common.h,v
retrieving revision 1.64
diff -p -u -r1.64 common.h
--- src/common.h 7 Nov 2005 05:11:55 -0000 1.64
+++ src/common.h 8 Nov 2005 07:18:09 -0000
@@ -600,6 +600,7 @@ void request_stdin (const char *);
void tar_stat_init (struct tar_stat_info *st);
void tar_stat_destroy (struct tar_stat_info *st);
void usage (int) __attribute__ ((noreturn));
+int tar_timespec_cmp (struct timespec a, struct timespec b);
/* Module update.c. */
Index: src/compare.c
===================================================================
RCS file: /cvsroot/tar/tar/src/compare.c,v
retrieving revision 1.30
diff -p -u -r1.30 compare.c
--- src/compare.c 28 Oct 2005 09:28:20 -0000 1.30
+++ src/compare.c 8 Nov 2005 07:18:09 -0000
@@ -224,7 +224,8 @@ diff_file (void)
if (!sys_compare_gid (&stat_data, ¤t_stat_info.stat))
report_difference (¤t_stat_info, _("Gid differs"));
- if (timespec_cmp (get_stat_mtime (&stat_data), current_stat_info.mtime))
+ if (tar_timespec_cmp (get_stat_mtime (&stat_data),
+ current_stat_info.mtime))
report_difference (¤t_stat_info, _("Mod time differs"));
if (current_header->header.typeflag != GNUTYPE_SPARSE &&
stat_data.st_size != current_stat_info.stat.st_size)
Index: src/extract.c
===================================================================
RCS file: /cvsroot/tar/tar/src/extract.c,v
retrieving revision 1.82
diff -p -u -r1.82 extract.c
--- src/extract.c 4 Nov 2005 21:25:47 -0000 1.82
+++ src/extract.c 8 Nov 2005 07:18:09 -0000
@@ -469,7 +469,7 @@ file_newer_p (const char *file_name, str
return errno != ENOENT;
}
if (!S_ISDIR (st.st_mode)
- && timespec_cmp (tar_stat->mtime, get_stat_mtime (&st)) <= 0)
+ && tar_timespec_cmp (tar_stat->mtime, get_stat_mtime (&st)) <= 0)
{
return true;
}
Index: src/tar.c
===================================================================
RCS file: /cvsroot/tar/tar/src/tar.c,v
retrieving revision 1.127
diff -p -u -r1.127 tar.c
--- src/tar.c 7 Nov 2005 02:50:14 -0000 1.127
+++ src/tar.c 8 Nov 2005 07:18:09 -0000
@@ -162,7 +162,7 @@ archive_format_string (enum archive_form
static void
assert_format(unsigned fmt_mask)
{
- if ((FORMAT_MASK(archive_format) & fmt_mask) == 0)
+ if ((FORMAT_MASK (archive_format) & fmt_mask) == 0)
USAGE_ERROR ((0, 0,
_("GNU features wanted on incompatible archive format")));
}
@@ -314,7 +314,7 @@ static struct argp_option options[] = {
{"occurrence", OCCURRENCE_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
N_("process only the NUMBERth occurrence of each file in the archive. This
option is valid only in conjunction with one of the subcommands --delete,
--diff, --extract or --list and when a list of files is given either on the
command line or via -T option. NUMBER defaults to 1."), 21 },
{"seek", 'n', NULL, 0,
- N_("archive is seekable"), 21 },
+ N_("archive is seekable"), 21 },
{NULL, 0, NULL, 0,
N_("Overwrite control:"), 30},
@@ -557,7 +557,7 @@ static struct argp_option options[] = {
{"show-stored-names", SHOW_STORED_NAMES_OPTION, 0, 0,
N_("When creating archive in verbose mode, list member names as stored in
the archive"),
102 },
-
+
{NULL, 0, NULL, 0,
N_("Compatibility options:"), 110 },
@@ -1047,7 +1047,7 @@ parse_opt (int key, char *arg, struct ar
set_subcommand_option (LIST_SUBCOMMAND);
test_label_option = true;
break;
-
+
case 'T':
update_argv (arg, state);
/* Indicate we've been given -T option. This is for backward
@@ -1323,7 +1323,7 @@ parse_opt (int key, char *arg, struct ar
case SHOW_STORED_NAMES_OPTION:
show_stored_names_option = true;
break;
-
+
case SUFFIX_OPTION:
backup_option = true;
args->backup_suffix_string = arg;
@@ -1679,7 +1679,7 @@ decode_options (int argc, char **argv)
if (multi_volume_option)
assert_format (FORMAT_MASK (OLDGNU_FORMAT) | FORMAT_MASK (GNU_FORMAT));
-
+
if (sparse_option)
assert_format (FORMAT_MASK (OLDGNU_FORMAT)
| FORMAT_MASK (GNU_FORMAT)
@@ -1980,4 +1980,18 @@ tar_stat_destroy (struct tar_stat_info *
free (st->sparse_map);
free (st->dumpdir);
memset (st, 0, sizeof (*st));
+}
+
+/* Format mask for all available formats that support nanosecond
+ timestamp resolution. */
+#define NS_PRECISION_FORMAT_MASK FORMAT_MASK (POSIX_FORMAT)
+
+/* Same as timespec_cmp, but ignore nanoseconds if current archive
+ format does not provide sufficient resolution. */
+int
+tar_timespec_cmp (struct timespec a, struct timespec b)
+{
+ if (!(FORMAT_MASK (current_format) & NS_PRECISION_FORMAT_MASK))
+ a.tv_nsec = b.tv_nsec = 0;
+ return timespec_cmp (a, b);
}
Index: src/update.c
===================================================================
RCS file: /cvsroot/tar/tar/src/update.c,v
retrieving revision 1.33
diff -p -u -r1.33 update.c
--- src/update.c 17 Sep 2005 06:41:56 -0000 1.33
+++ src/update.c 8 Nov 2005 07:18:09 -0000
@@ -138,8 +138,8 @@ update_archive (void)
chdir_do (name->change_dir);
if (deref_stat (dereference_option,
current_stat_info.file_name, &s) == 0
- && (timespec_cmp (get_stat_mtime (&s),
- current_stat_info.mtime)
+ && (tar_timespec_cmp (get_stat_mtime (&s),
+ current_stat_info.mtime)
<= 0))
add_avoided_name (current_stat_info.file_name);
}
Index: tests/truncate.at
===================================================================
RCS file: /cvsroot/tar/tar/tests/truncate.at,v
retrieving revision 1.4
diff -p -u -r1.4 truncate.at
--- tests/truncate.at 7 Nov 2005 04:03:29 -0000 1.4
+++ tests/truncate.at 8 Nov 2005 07:18:09 -0000
@@ -31,7 +31,6 @@ AT_KEYWORDS([truncated files])
AT_TAR_CHECK([
genfile --file foo --length 50000k
genfile --file baz
-touch -t 197001030000 baz # avoid subsecond resolution
genfile --run 'tar -vcf bar foo baz' --checkpoint 10 --length 49995k
--truncate foo
echo separator
sleep 1
Index: tests/update.at
===================================================================
RCS file: /cvsroot/tar/tar/tests/update.at,v
retrieving revision 1.4
diff -p -u -r1.4 update.at
--- tests/update.at 7 Nov 2005 04:03:30 -0000 1.4
+++ tests/update.at 8 Nov 2005 07:18:09 -0000
@@ -31,7 +31,6 @@ AT_TAR_CHECK([
mkdir directory
genfile --length 10240 --pattern zeros --file directory/file1
genfile --length 10240 --pattern default --file directory/file2
-touch -t 197001030000 directory directory/* # avoid subsecond resolution
tar cf archive directory || exit 1
echo separator