diff options
author | kientzle <kientzle@FreeBSD.org> | 2007-04-18 04:36:11 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2007-04-18 04:36:11 +0000 |
commit | 4db8f3e0cc218ebbc69857ffdd274e67b815cd31 (patch) | |
tree | f7575fe8ec9a6364e144e6276dfd9d3fe5f71227 | |
parent | 1722334e06a0542c3c0a8579f523257bd886d4a5 (diff) | |
download | FreeBSD-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.
-rw-r--r-- | usr.bin/tar/util.c | 29 |
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); } |