archive_entry_free(ae);
}
+static void
+test_parent(void)
+{
+ struct archive *a;
+ struct archive_entry *ae;
+ const void *p;
+ size_t size;
+ int64_t offset;
+ int file_count;
+ int match_count;
+
+ assertMakeDir("lock", 0311);
+ assertMakeDir("lock/dir1", 0755);
+ assertMakeFile("lock/dir1/f1", 0644, "0123456789");
+ assertMakeDir("lock/lock2", 0311);
+ assertMakeDir("lock/lock2/dir1", 0755);
+ assertMakeFile("lock/lock2/dir1/f1", 0644, "0123456789");
+
+ assert((ae = archive_entry_new()) != NULL);
+ assert((a = archive_read_disk_new()) != NULL);
+
+ /*
+ * Test1: Traverse lock/dir1 as .
+ */
+ assertChdir("lock/dir1");
+
+ failure("Directory traversals should work as well");
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
+
+ file_count = 2;
+ match_count = 0;
+ while (file_count--) {
+ archive_entry_clear(ae);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
+ if (strcmp(archive_entry_pathname(ae), ".") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
+ ++match_count;
+ } else if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
+ assertEqualInt(archive_entry_size(ae), 10);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 10);
+ assertEqualInt((int)offset, 0);
+ assertEqualMem(p, "0123456789", 10);
+ assertEqualInt(ARCHIVE_EOF,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 0);
+ assertEqualInt((int)offset, 10);
+ ++match_count;
+ }
+ if (archive_read_disk_can_descend(a)) {
+ /* Descend into the current object */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_disk_descend(a));
+ }
+ }
+ failure("Did not match expected filenames");
+ assertEqualInt(match_count, 2);
+ /*
+ * There is no entry. This will however fail if the directory traverse
+ * tries to ascend past the initial directory, since it lacks permission
+ * to do so.
+ */
+ failure("There should be no entry and no error");
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
+
+ /* Close the disk object. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+
+ assertChdir("../..");
+
+ /*
+ * Test2: Traverse lock/dir1 directly
+ */
+ failure("Directory traversals should work as well");
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1"));
+
+ file_count = 2;
+ match_count = 0;
+ while (file_count--) {
+ archive_entry_clear(ae);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
+ if (strcmp(archive_entry_pathname(ae), "lock/dir1") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
+ ++match_count;
+ } else if (strcmp(archive_entry_pathname(ae), "lock/dir1/f1") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
+ assertEqualInt(archive_entry_size(ae), 10);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 10);
+ assertEqualInt((int)offset, 0);
+ assertEqualMem(p, "0123456789", 10);
+ assertEqualInt(ARCHIVE_EOF,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 0);
+ assertEqualInt((int)offset, 10);
+ ++match_count;
+ }
+ if (archive_read_disk_can_descend(a)) {
+ /* Descend into the current object */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_disk_descend(a));
+ }
+ }
+ failure("Did not match expected filenames");
+ assertEqualInt(match_count, 2);
+ /*
+ * There is no entry. This will however fail if the directory traverse
+ * tries to ascend past the initial directory, since it lacks permission
+ * to do so.
+ */
+ failure("There should be no entry and no error");
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
+
+ /* Close the disk object. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+
+ /*
+ * Test3: Traverse lock/dir1/.
+ */
+ failure("Directory traversals should work as well");
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1/."));
+
+ file_count = 2;
+ match_count = 0;
+ while (file_count--) {
+ archive_entry_clear(ae);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
+ if (strcmp(archive_entry_pathname(ae), "lock/dir1/.") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
+ ++match_count;
+ } else if (strcmp(archive_entry_pathname(ae), "lock/dir1/./f1") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
+ assertEqualInt(archive_entry_size(ae), 10);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 10);
+ assertEqualInt((int)offset, 0);
+ assertEqualMem(p, "0123456789", 10);
+ assertEqualInt(ARCHIVE_EOF,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 0);
+ assertEqualInt((int)offset, 10);
+ ++match_count;
+ }
+ if (archive_read_disk_can_descend(a)) {
+ /* Descend into the current object */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_disk_descend(a));
+ }
+ }
+ failure("Did not match expected filenames");
+ assertEqualInt(match_count, 2);
+ /*
+ * There is no entry. This will however fail if the directory traverse
+ * tries to ascend past the initial directory, since it lacks permission
+ * to do so.
+ */
+ failure("There should be no entry and no error");
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
+
+ /* Close the disk object. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+
+ /*
+ * Test4: Traverse lock/lock2/dir1 from inside lock.
+ */
+ assertChdir("lock");
+
+ failure("Directory traversals should work as well");
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1"));
+
+ file_count = 2;
+ match_count = 0;
+ while (file_count--) {
+ archive_entry_clear(ae);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
+ if (strcmp(archive_entry_pathname(ae), "lock2/dir1") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
+ ++match_count;
+ } else if (strcmp(archive_entry_pathname(ae), "lock2/dir1/f1") == 0) {
+ assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
+ assertEqualInt(archive_entry_size(ae), 10);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 10);
+ assertEqualInt((int)offset, 0);
+ assertEqualMem(p, "0123456789", 10);
+ assertEqualInt(ARCHIVE_EOF,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 0);
+ assertEqualInt((int)offset, 10);
+ ++match_count;
+ }
+ if (archive_read_disk_can_descend(a)) {
+ /* Descend into the current object */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_disk_descend(a));
+ }
+ }
+ failure("Did not match expected filenames");
+ assertEqualInt(match_count, 2);
+ /*
+ * There is no entry. This will however fail if the directory traverse
+ * tries to ascend past the initial directory, since it lacks permission
+ * to do so.
+ */
+ failure("There should be no entry and no error");
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
+
+ /* Close the disk object. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+
+ assertChdir("..");
+
+ /* Destroy the disk object. */
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ archive_entry_free(ae);
+}
+
DEFINE_TEST(test_read_disk_directory_traversals)
{
/* Basic test. */
test_callbacks();
/* Test nodump. */
test_nodump();
+ /* Test parent overshoot. */
+ test_parent();
}