diff options
author | kientzle <kientzle@FreeBSD.org> | 2007-04-14 08:20:31 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2007-04-14 08:20:31 +0000 |
commit | f22ef7785ff8379a306fdaf2ee3838a132d04f2d (patch) | |
tree | 8cfbedf61d20f0a3edf0efe3a5de037f19df7f4d /lib/libarchive/test | |
parent | aed3c204260197526cb450a788cfdd1199023e67 (diff) | |
download | FreeBSD-src-f22ef7785ff8379a306fdaf2ee3838a132d04f2d.zip FreeBSD-src-f22ef7785ff8379a306fdaf2ee3838a132d04f2d.tar.gz |
Conventionally, tar archives have always included a trailing '/'
for directories. bsdtar used to add this, but that recently got
lost somehow. So now I'm adding it back in libarchive.
The only odd part of doing this in libarchive: Adding a directory to
a tar archive and then reading it back again can yield a different name.
Add a test case to exercise some boundary conditions with
tar filenames and ensure that trailing slashes are added to
dir names only as necessary.
Thanks to: Oliver Lehmann for bringing this regression to my attention.
Diffstat (limited to 'lib/libarchive/test')
-rw-r--r-- | lib/libarchive/test/Makefile | 1 | ||||
-rw-r--r-- | lib/libarchive/test/test_tar_filenames.c | 156 |
2 files changed, 157 insertions, 0 deletions
diff --git a/lib/libarchive/test/Makefile b/lib/libarchive/test/Makefile index b5da3ab..b436bbd 100644 --- a/lib/libarchive/test/Makefile +++ b/lib/libarchive/test/Makefile @@ -28,6 +28,7 @@ TESTS= \ test_read_large.c \ test_read_position.c \ test_read_truncated.c \ + test_tar_filenames.c \ test_write_disk.c \ test_write_disk_perms.c \ test_write_disk_secure.c \ diff --git a/lib/libarchive/test/test_tar_filenames.c b/lib/libarchive/test/test_tar_filenames.c new file mode 100644 index 0000000..57545ba --- /dev/null +++ b/lib/libarchive/test/test_tar_filenames.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Exercise various lengths of filenames in tar archives, + * especially around the magic sizes where ustar breaks + * filenames into prefix/suffix. + */ + +static +test_filename(int dlen, int flen) +{ + char buff[8192]; + char filename[400]; + char dirname[400]; + struct archive_entry *ae; + struct archive *a; + size_t used; + int i; + + for (i = 0; i < dlen; i++) + filename[i] = 'a'; + filename[i++] = '/'; + for (; i < dlen + flen + 1; i++) + filename[i] = 'b'; + filename[i++] = '\0'; + + strcpy(dirname, filename); + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_pax_restricted(a)); + assertA(0 == archive_write_set_compression_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a,0)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, filename); + archive_entry_set_mode(ae, S_IFREG | 0755); + failure("Pathname %d/%d", dlen, flen); + assertA(0 == archive_write_header(a, ae)); + + /* + * Write a dir to it (without trailing '/'). + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFDIR | 0755); + failure("Dirname %d/%d", dlen, flen); + assertA(0 == archive_write_header(a, ae)); + + /* Tar adds a '/' to directory names. */ + strcat(dirname, "/"); + + /* + * Write a dir to it (with trailing '/'). + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, dirname); + archive_entry_set_mode(ae, S_IFDIR | 0755); + failure("Dirname %d/%d", dlen, flen); + assertA(0 == archive_write_header(a, ae)); + + /* Close out the archive. */ + assertA(0 == archive_write_close(a)); +#if ARCHIVE_API_VERSION > 1 + assertA(0 == archive_write_finish(a)); +#else + archive_write_finish(a); +#endif + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_support_compression_all(a)); + assertA(0 == archive_read_open_memory(a, buff, used)); + + /* Read the file and check the filename. */ + assertA(0 == archive_read_next_header(a, &ae)); + failure("Pathname %d/%d: %s", dlen, flen, archive_entry_pathname(ae)); + assert(0 == strcmp(filename, archive_entry_pathname(ae))); + assert((S_IFREG | 0755) == archive_entry_mode(ae)); + + /* + * Read the two dirs and check the names. + * + * Both dirs should read back with the same name, since + * tar should add a trailing '/' to any dir that doesn't + * already have one. + */ + assertA(0 == archive_read_next_header(a, &ae)); + failure("Pathname %d/%d: %s", dlen, flen, archive_entry_pathname(ae)); + assert(0 == strcmp(dirname, archive_entry_pathname(ae))); + assert((S_IFDIR | 0755) == archive_entry_mode(ae)); + + assertA(0 == archive_read_next_header(a, &ae)); + failure("Pathname %d/%d: %s", dlen, flen, archive_entry_pathname(ae)); + assert(0 == strcmp(dirname, archive_entry_pathname(ae))); + assert((S_IFDIR | 0755) == archive_entry_mode(ae)); + + /* Verify the end of the archive. */ + assert(1 == archive_read_next_header(a, &ae)); + assert(0 == archive_read_close(a)); +#if ARCHIVE_API_VERSION > 1 + assert(0 == archive_read_finish(a)); +#else + archive_read_finish(a); +#endif +} + +DEFINE_TEST(test_tar_filenames) +{ + int dlen, flen; + + /* 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); + } + } + + for (dlen = 140; dlen < 160; dlen++) { + for (flen = 90; flen < 110; flen++) { + test_filename(dlen, flen); + } + } +} |