summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-06-11 05:17:30 +0000
committerkientzle <kientzle@FreeBSD.org>2007-06-11 05:17:30 +0000
commit38906e07a0380901105855d09ef8d45bfb5402d7 (patch)
tree7be2e12a244988cd91c7f96d20f26ae1a7efeee9 /lib
parent1f5ee5cc4f4a98060ee7b74f237169570dcda597 (diff)
downloadFreeBSD-src-38906e07a0380901105855d09ef8d45bfb5402d7.zip
FreeBSD-src-38906e07a0380901105855d09ef8d45bfb5402d7.tar.gz
Don't lose leading '/' for pathnames exactly 101 bytes long.
Also, update the test harness to exercise this case.
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/archive_write_set_format_ustar.c10
-rw-r--r--lib/libarchive/test/test_tar_filenames.c23
2 files changed, 25 insertions, 8 deletions
diff --git a/lib/libarchive/archive_write_set_format_ustar.c b/lib/libarchive/archive_write_set_format_ustar.c
index f43c23a..390b1a0 100644
--- a/lib/libarchive/archive_write_set_format_ustar.c
+++ b/lib/libarchive/archive_write_set_format_ustar.c
@@ -279,6 +279,16 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
/* Store in two pieces, splitting at a '/'. */
p = strchr(pp + strlen(pp) - USTAR_name_size - 1, '/');
/*
+ * If the separator we found is the first '/', find
+ * the next one. (This is a pathological case that
+ * occurs for paths of exactly 101 bytes that start with
+ * '/'; it occurs because the separating '/' is not
+ * stored explicitly and the reconstruction assumes that
+ * an empty prefix means there is no '/' separator.)
+ */
+ if (p == pp)
+ p = strchr(p + 1, '/');
+ /*
* If there is no path separator, or the prefix or
* remaining name are too large, return an error.
*/
diff --git a/lib/libarchive/test/test_tar_filenames.c b/lib/libarchive/test/test_tar_filenames.c
index fb15a96..b534174 100644
--- a/lib/libarchive/test/test_tar_filenames.c
+++ b/lib/libarchive/test/test_tar_filenames.c
@@ -31,8 +31,8 @@ __FBSDID("$FreeBSD$");
* filenames into prefix/suffix.
*/
-static void
-test_filename(int dlen, int flen)
+static
+test_filename(const char *prefix, int dlen, int flen)
{
char buff[8192];
char filename[400];
@@ -40,12 +40,17 @@ test_filename(int dlen, int flen)
struct archive_entry *ae;
struct archive *a;
size_t used;
- int i;
+ size_t prefix_length = 0;
+ int i = 0;
- for (i = 0; i < dlen; i++)
+ if (prefix) {
+ strcpy(filename, prefix);
+ i = prefix_length = strlen(prefix);
+ }
+ for (; i < prefix_length + dlen; i++)
filename[i] = 'a';
filename[i++] = '/';
- for (; i < dlen + flen + 1; i++)
+ for (; i < prefix_length + dlen + flen + 1; i++)
filename[i] = 'b';
filename[i++] = '\0';
@@ -111,7 +116,7 @@ test_filename(int dlen, int flen)
assertA(0 == archive_read_next_header(a, &ae));
failure("Pathname %d/%d: %s", dlen, flen, archive_entry_pathname(ae));
assertEqualString(filename, archive_entry_pathname(ae));
- assert((S_IFREG | 0755) == archive_entry_mode(ae));
+ assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
/*
* Read the two dirs and check the names.
@@ -147,13 +152,15 @@ DEFINE_TEST(test_tar_filenames)
/* Repeat the following for a variety of dir/file lengths. */
for (dlen = 40; dlen < 60; dlen++) {
for (flen = 40; flen < 60; flen++) {
- test_filename(dlen, flen);
+ test_filename(NULL, dlen, flen);
+ test_filename("/", dlen, flen);
}
}
for (dlen = 140; dlen < 160; dlen++) {
for (flen = 90; flen < 110; flen++) {
- test_filename(dlen, flen);
+ test_filename(NULL, dlen, flen);
+ test_filename("/", dlen, flen);
}
}
}
OpenPOWER on IntegriCloud