Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Sep 2005 22:36:41 -0700
From:      Tim Kientzle <kientzle@freebsd.org>
To:        Lowell Gilbert <freebsd-questions-local@be-well.ilk.org>
Cc:        gjbailey@gmail.com, freebsd-questions <freebsd-questions@freebsd.org>
Subject:   Re: tar -u adds all files regardless of mod date
Message-ID:  <433242E9.2060100@freebsd.org>
In-Reply-To: <44u0guw0ou.fsf@be-well.ilk.org>
References:  <48a5f32a05090901591a16c062@mail.gmail.com> <44u0guw0ou.fsf@be-well.ilk.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------050000000803000805090904
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Lowell Gilbert wrote:
> Gareth Bailey <gjbailey@gmail.com> writes:
> 
>>... If i then try to update modified files by doing this:
>>
>># tar -uf dir_b.tar /usr/dir_a/dir_b
>>
>>and I end up with dir_b.tar being 130MB (double size) which
>>should not be the case since no files have been modified in
>> /usr/dir_a/dir_b.

The attached patch should fix this problem for 6-STABLE and 7-CURRENT
systems.  If someone could try it for me and let me know if
it works for them, I'd greatly appreciate it.

5-STABLE is sufficiently different that the patch doesn't apply,
unfortunately.  It will take me a few days to figure out whether
it's best to work up a different patch for 5-STABLE or whether
I should MFC a lot of work from 6-STABLE to 5-STABLE.

The crux of the problem is that bsdtar compares files on disk
to files in the archive by pathname before it strips leading '/'
characters.  As a result, it tries to compare "/usr/dir_a" on disk
to "usr/dir_a" in the archive, which fails.

A temporary workaround is to not use absolute pathnames:

    cd / ; tar -uf dir_b.tar usr/dir_a/dir_b

Another workaround is to use -P both when creating and when
updating the archive.

The attached patch causes bsdtar to do all pathname editing
before it does the time comparison for -u.  I think that
correctly fixes this problem.

Tim

P.S. If you're testing this, do not use "touch" to update
timestamps.  If you do, you will get some very confusing
results because "touch" updates high-precision timestamps,
but the default tar format only stores whole seconds.
This seems hard to fix.

--------------050000000803000805090904
Content-Type: text/plain;
 name="fix-u-uption"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="fix-u-uption"

Index: write.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/tar/write.c,v
retrieving revision 1.41
diff -u -r1.41 write.c
--- write.c	8 May 2005 06:25:15 -0000	1.41
+++ write.c	22 Sep 2005 04:46:00 -0000
@@ -643,15 +643,12 @@
 			tree_descend(tree);
 
 		/*
-		 * In -u mode, we need to check whether this
-		 * is newer than what's already in the archive.
-		 * In all modes, we need to obey --newerXXX flags.
+		 * Write the entry.  Note that write_entry() handles
+		 * pathname editing and newness testing.
 		 */
-		if (new_enough(bsdtar, name, lst)) {
-			write_entry(bsdtar, a, lst, name,
-			    tree_current_pathlen(tree),
-			    tree_current_access_path(tree));
-		}
+		write_entry(bsdtar, a, lst, name,
+		    tree_current_pathlen(tree),
+		    tree_current_access_path(tree));
 	}
 	tree_close(tree);
 }
@@ -686,6 +683,13 @@
 	if (edit_pathname(bsdtar, entry))
 		goto abort;
 
+	/*
+	 * In -u mode, check that the file is newer than what's
+	 * already in the archive; in all modes, obey --newerXXX flags.
+	 */
+	if (!new_enough(bsdtar, archive_entry_pathname(entry), st))
+		goto abort;
+
 	if (!S_ISDIR(st->st_mode) && (st->st_nlink > 1))
 		lookup_hardlink(bsdtar, entry, st);
 
@@ -1235,10 +1239,6 @@
 	 */
 	if (bsdtar->archive_dir != NULL &&
 	    bsdtar->archive_dir->head != NULL) {
-		/* Ignore leading './' when comparing names. */
-		if (path[0] == '.' && path[1] == '/' && path[2] != '\0')
-			path += 2;
-
 		for (p = bsdtar->archive_dir->head; p != NULL; p = p->next) {
 			if (strcmp(path, p->name)==0)
 				return (p->mtime_sec < st->st_mtime ||

--------------050000000803000805090904--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?433242E9.2060100>