summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-04-18 04:36:11 +0000
committerkientzle <kientzle@FreeBSD.org>2007-04-18 04:36:11 +0000
commit4db8f3e0cc218ebbc69857ffdd274e67b815cd31 (patch)
treef7575fe8ec9a6364e144e6276dfd9d3fe5f71227 /usr.bin/tar
parent1722334e06a0542c3c0a8579f523257bd886d4a5 (diff)
downloadFreeBSD-src-4db8f3e0cc218ebbc69857ffdd274e67b815cd31.zip
FreeBSD-src-4db8f3e0cc218ebbc69857ffdd274e67b815cd31.tar.gz
Ignore trailing '/' when comparing pathnames, so that
"tar -u" works again. Otherwise, "tar -u" wants to treat every dir as new and re-adds it.
Diffstat (limited to 'usr.bin/tar')
-rw-r--r--usr.bin/tar/util.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/usr.bin/tar/util.c b/usr.bin/tar/util.c
index 9cc19d7..080252c 100644
--- a/usr.bin/tar/util.c
+++ b/usr.bin/tar/util.c
@@ -449,16 +449,39 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
/*
* Like strcmp(), but try to be a little more aware of the fact that
- * we're comparing two paths.
+ * we're comparing two paths. Right now, it just handles leading
+ * "./" and trailing '/' specially, so that "a/b/" == "./a/b"
*
- * TODO: Make this better, so that "./a//b/./c" == "a/b/c"
+ * TODO: Make this better, so that "./a//b/./c/" == "a/b/c"
+ * TODO: After this works, push it down into libarchive.
+ * TODO: Publish the path normalization routines in libarchive so
+ * that bsdtar can normalize paths and use fast strcmp() instead
+ * of this.
*/
+
int
pathcmp(const char *a, const char *b)
{
+ /* Skip leading './' */
if (a[0] == '.' && a[1] == '/' && a[2] != '\0')
a += 2;
if (b[0] == '.' && b[1] == '/' && b[2] != '\0')
b += 2;
- return (strcmp(a, b));
+ /* Find the first difference, or return (0) if none. */
+ while (*a == *b) {
+ if (*a == '\0')
+ return (0);
+ a++;
+ b++;
+ }
+ /*
+ * If one ends in '/' and the other one doesn't,
+ * they're the same.
+ */
+ if (a[0] == '/' && a[1] == '\0' && b[0] == '\0')
+ return (0);
+ if (a[0] == '\0' && b[0] == '/' && b[1] == '\0')
+ return (0);
+ /* They're really different, return the correct sign. */
+ return (*(const unsigned char *)a - *(const unsigned char *)b);
}
OpenPOWER on IntegriCloud