mirror of
https://github.com/idolpx/libMeatloaf.git
synced 2025-12-06 04:38:49 -05:00
1876 lines
65 KiB
C
1876 lines
65 KiB
C
/*-
|
|
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
|
|
* 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"
|
|
|
|
#include <limits.h>
|
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
# if !defined(__BORLANDC__)
|
|
# define getcwd _getcwd
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
* Test if the current filesystem is mounted with noatime option.
|
|
*/
|
|
static int
|
|
atimeIsUpdated(void)
|
|
{
|
|
const char *fn = "fs_noatime";
|
|
struct stat st;
|
|
#if defined(_WIN32) && !defined(CYGWIN)
|
|
char *buff = NULL;
|
|
char *ptr;
|
|
int r;
|
|
|
|
r = systemf("fsutil behavior query disableLastAccess > query_atime");
|
|
if (r == 0) {
|
|
buff = slurpfile(NULL, "query_atime");
|
|
if (buff != NULL) {
|
|
ptr = buff;
|
|
while(*ptr != '\0' && !isdigit(*ptr)) {
|
|
ptr++;
|
|
}
|
|
if (*ptr == '0') {
|
|
free(buff);
|
|
return(1);
|
|
} else if (*ptr == '1' || *ptr == '2') {
|
|
free(buff);
|
|
return(0);
|
|
}
|
|
free(buff);
|
|
}
|
|
}
|
|
#endif
|
|
if (!assertMakeFile(fn, 0666, "a"))
|
|
return (0);
|
|
if (!assertUtimes(fn, 1, 0, 1, 0))
|
|
return (0);
|
|
/* Test the file contents in order to update its atime. */
|
|
if (!assertTextFileContents("a", fn))
|
|
return (0);
|
|
if (stat(fn, &st) != 0)
|
|
return (0);
|
|
/* Is atime updated? */
|
|
if (st.st_atime > 1)
|
|
return (1);
|
|
return (0);
|
|
}
|
|
|
|
static void
|
|
test_basic(void)
|
|
{
|
|
struct archive *a;
|
|
struct archive_entry *ae;
|
|
const void *p;
|
|
char *initial_cwd, *cwd;
|
|
size_t size;
|
|
int64_t offset;
|
|
int file_count;
|
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
wchar_t *wcwd, *wp, *fullpath;
|
|
#endif
|
|
|
|
assertMakeDir("dir1", 0755);
|
|
assertMakeFile("dir1/file1", 0644, "0123456789");
|
|
assertMakeFile("dir1/file2", 0644, "hello world");
|
|
assertMakeDir("dir1/sub1", 0755);
|
|
assertMakeFile("dir1/sub1/file1", 0644, "0123456789");
|
|
assertMakeDir("dir1/sub2", 0755);
|
|
assertMakeFile("dir1/sub2/file1", 0644, "0123456789");
|
|
assertMakeFile("dir1/sub2/file2", 0644, "0123456789");
|
|
assertMakeDir("dir1/sub2/sub1", 0755);
|
|
assertMakeDir("dir1/sub2/sub2", 0755);
|
|
assertMakeDir("dir1/sub2/sub3", 0755);
|
|
assertMakeFile("dir1/sub2/sub3/file", 0644, "xyz");
|
|
file_count = 12;
|
|
|
|
assert((ae = archive_entry_new()) != NULL);
|
|
assert((a = archive_read_disk_new()) != NULL);
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
|
|
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "dir1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/file1") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/file2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 11);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 11);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "hello world", 11);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 11);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub1/file1") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub2/file1") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub2/file2") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub2/sub1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub2/sub2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub2/sub3") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub2/sub3/file") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 3);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 3);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "xyz", 3);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 3);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Test that call archive_read_disk_open_w, wchar_t version.
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, L"dir1"));
|
|
|
|
file_count = 12;
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (wcscmp(archive_entry_pathname_w(ae), L"dir1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/file1") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/file2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 11);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 11);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "hello world", 11);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 11);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub1/file1") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub2/file1") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub2/file2") == 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);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub2/sub1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub2/sub2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub2/sub3") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
} else if (wcscmp(archive_entry_pathname_w(ae),
|
|
L"dir1/sub2/sub3/file") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 3);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 3);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "xyz", 3);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 3);
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Test that call archive_read_disk_open with a regular file.
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/file1"));
|
|
|
|
/* dir1/file1 */
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
assertEqualString(archive_entry_pathname(ae), "dir1/file1");
|
|
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);
|
|
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
|
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
/*
|
|
* Test for wildcard '*' or '?'
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/*1"));
|
|
|
|
/* dir1/file1 */
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
assertEqualString(archive_entry_pathname(ae), "dir1/file1");
|
|
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);
|
|
|
|
/* dir1/sub1 */
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
assertEqualString(archive_entry_pathname(ae), "dir1/sub1");
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
|
|
|
|
/* dir1/sub1/file1 */
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
assertEqualString(archive_entry_pathname(ae), "dir1/sub1/file1");
|
|
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);
|
|
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Test for a full-path beginning with "//?/"
|
|
*/
|
|
wcwd = _wgetcwd(NULL, 0);
|
|
fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
|
|
wcscpy(fullpath, L"//?/");
|
|
wcscat(fullpath, wcwd);
|
|
wcscat(fullpath, L"/dir1/file1");
|
|
free(wcwd);
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
|
|
while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
|
|
*wcwd = L'/';
|
|
|
|
/* dir1/file1 */
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
assertEqualWString(archive_entry_pathname_w(ae), fullpath);
|
|
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);
|
|
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
free(fullpath);
|
|
|
|
/*
|
|
* Test for wild card '*' or '?' with "//?/" prefix.
|
|
*/
|
|
wcwd = _wgetcwd(NULL, 0);
|
|
fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
|
|
wcscpy(fullpath, L"//?/");
|
|
wcscat(fullpath, wcwd);
|
|
wcscat(fullpath, L"/dir1/*1");
|
|
free(wcwd);
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
|
|
while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
|
|
*wcwd = L'/';
|
|
|
|
/* dir1/file1 */
|
|
wp = wcsrchr(fullpath, L'/');
|
|
wcscpy(wp+1, L"file1");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
assertEqualWString(archive_entry_pathname_w(ae), fullpath);
|
|
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);
|
|
|
|
/* dir1/sub1 */
|
|
wcscpy(wp+1, L"sub1");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(1, archive_read_disk_can_descend(a));
|
|
assertEqualWString(archive_entry_pathname_w(ae), fullpath);
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
|
|
|
|
/* dir1/sub1/file1 */
|
|
wcscpy(wp+1, L"sub1/file1");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
assertEqualInt(0, archive_read_disk_can_descend(a));
|
|
assertEqualWString(archive_entry_pathname_w(ae), fullpath);
|
|
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);
|
|
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
free(fullpath);
|
|
|
|
#endif
|
|
|
|
/*
|
|
* We should be on the initial directory where we performed
|
|
* archive_read_disk_new() after we perform archive_read_free()
|
|
* even if we broke off the directory traversals.
|
|
*/
|
|
|
|
/* Save current working directory. */
|
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
|
initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
|
#else
|
|
initial_cwd = getcwd(NULL, 0);
|
|
#endif
|
|
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
|
|
|
|
/* Step in a deep directory. */
|
|
file_count = 12;
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae),
|
|
"dir1/sub1/file1") == 0)
|
|
/*
|
|
* We are on an another directory at this time.
|
|
*/
|
|
break;
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
|
|
/* We should be on the initial working directory. */
|
|
failure(
|
|
"Current working directory does not return to the initial"
|
|
"directory");
|
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
|
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
|
#else
|
|
cwd = getcwd(NULL, 0);
|
|
#endif
|
|
assertEqualString(initial_cwd, cwd);
|
|
free(initial_cwd);
|
|
free(cwd);
|
|
|
|
archive_entry_free(ae);
|
|
}
|
|
|
|
static void
|
|
test_symlink_hybrid(void)
|
|
{
|
|
struct archive *a;
|
|
struct archive_entry *ae;
|
|
const void *p;
|
|
size_t size;
|
|
int64_t offset;
|
|
int file_count;
|
|
|
|
if (!canSymlink()) {
|
|
skipping("Can't test symlinks on this filesystem");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Create a sample archive.
|
|
*/
|
|
assertMakeDir("h", 0755);
|
|
assertChdir("h");
|
|
assertMakeDir("d1", 0755);
|
|
assertMakeSymlink("ld1", "d1", 1);
|
|
assertMakeFile("d1/file1", 0644, "d1/file1");
|
|
assertMakeFile("d1/file2", 0644, "d1/file2");
|
|
assertMakeSymlink("d1/link1", "file1", 0);
|
|
assertMakeSymlink("d1/linkX", "fileX", 0);
|
|
assertMakeSymlink("link2", "d1/file2", 0);
|
|
assertMakeSymlink("linkY", "d1/fileY", 0);
|
|
assertChdir("..");
|
|
|
|
assert((ae = archive_entry_new()) != NULL);
|
|
assert((a = archive_read_disk_new()) != NULL);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_set_symlink_hybrid(a));
|
|
|
|
/*
|
|
* Specified file is a symbolic link file.
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h/ld1"));
|
|
file_count = 5;
|
|
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/ld1/file1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/ld1/file2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file2", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/ld1/link1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/ld1/linkX") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Specified file is a directory and it has symbolic files.
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h"));
|
|
file_count = 9;
|
|
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "h") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "h/d1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/d1/file1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/d1/file2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file2", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/d1/link1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/d1/linkX") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/link2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"h/linkY") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
archive_entry_free(ae);
|
|
}
|
|
|
|
static void
|
|
test_symlink_logical(void)
|
|
{
|
|
struct archive *a;
|
|
struct archive_entry *ae;
|
|
const void *p;
|
|
size_t size;
|
|
int64_t offset;
|
|
int file_count;
|
|
|
|
if (!canSymlink()) {
|
|
skipping("Can't test symlinks on this filesystem");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Create a sample archive.
|
|
*/
|
|
assertMakeDir("l", 0755);
|
|
assertChdir("l");
|
|
assertMakeDir("d1", 0755);
|
|
assertMakeSymlink("ld1", "d1", 1);
|
|
assertMakeFile("d1/file1", 0644, "d1/file1");
|
|
assertMakeFile("d1/file2", 0644, "d1/file2");
|
|
assertMakeSymlink("d1/link1", "file1", 0);
|
|
assertMakeSymlink("d1/linkX", "fileX", 0);
|
|
assertMakeSymlink("link2", "d1/file2", 0);
|
|
assertMakeSymlink("linkY", "d1/fileY", 0);
|
|
assertChdir("..");
|
|
|
|
/* Note: this test uses archive_read_next_header()
|
|
instead of archive_read_next_header2() */
|
|
assert((a = archive_read_disk_new()) != NULL);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_set_symlink_logical(a));
|
|
|
|
/*
|
|
* Specified file is a symbolic link file.
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l/ld1"));
|
|
file_count = 5;
|
|
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
|
if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/file1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/file2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file2", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/link1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/linkX") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Specified file is a directory and it has symbolic files.
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l"));
|
|
file_count = 13;
|
|
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
|
if (strcmp(archive_entry_pathname(ae), "l") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "l/d1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/d1/file1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/d1/file2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file2", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/d1/link1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/d1/linkX") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/file1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/file2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file2", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/link1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/ld1/linkX") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/link2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d1/file2", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l/linkY") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
}
|
|
|
|
static void
|
|
test_symlink_logical_loop(void)
|
|
{
|
|
struct archive *a;
|
|
struct archive_entry *ae;
|
|
const void *p;
|
|
size_t size;
|
|
int64_t offset;
|
|
int file_count;
|
|
|
|
if (!canSymlink()) {
|
|
skipping("Can't test symlinks on this filesystem");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Create a sample archive.
|
|
*/
|
|
assertMakeDir("l2", 0755);
|
|
assertChdir("l2");
|
|
assertMakeDir("d1", 0755);
|
|
assertMakeDir("d1/d2", 0755);
|
|
assertMakeDir("d1/d2/d3", 0755);
|
|
assertMakeDir("d2", 0755);
|
|
assertMakeFile("d2/file1", 0644, "d2/file1");
|
|
assertMakeSymlink("d1/d2/ld1", "../../d1", 1);
|
|
assertMakeSymlink("d1/d2/ld2", "../../d2", 1);
|
|
assertChdir("..");
|
|
|
|
assert((ae = archive_entry_new()) != NULL);
|
|
assert((a = archive_read_disk_new()) != NULL);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_set_symlink_logical(a));
|
|
|
|
/*
|
|
* Specified file is a symbolic link file.
|
|
*/
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l2/d1"));
|
|
file_count = 6;
|
|
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "l2/d1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/d3") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
|
|
} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae),
|
|
"l2/d1/d2/ld2/file1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 8);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 8);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "d2/file1", 8);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 8);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
archive_entry_free(ae);
|
|
}
|
|
|
|
static void
|
|
test_restore_atime(void)
|
|
{
|
|
struct archive *a;
|
|
struct archive_entry *ae;
|
|
const void *p;
|
|
size_t size;
|
|
int64_t offset;
|
|
int file_count;
|
|
const char *skip_test_restore_atime;
|
|
|
|
skip_test_restore_atime = getenv("SKIP_TEST_RESTORE_ATIME");
|
|
if (skip_test_restore_atime != NULL) {
|
|
skipping("Skipping restore atime tests due to "
|
|
"SKIP_TEST_RESTORE_ATIME environment variable");
|
|
return;
|
|
}
|
|
if (!atimeIsUpdated()) {
|
|
skipping("Can't test restoring atime on this filesystem");
|
|
return;
|
|
}
|
|
|
|
assertMakeDir("at", 0755);
|
|
assertMakeFile("at/f1", 0644, "0123456789");
|
|
assertMakeFile("at/f2", 0644, "hello world");
|
|
assertMakeFile("at/fe", 0644, NULL);
|
|
assertUtimes("at/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("at/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("at/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("at", 886622, 0, 886622, 0);
|
|
file_count = 4;
|
|
|
|
assert((ae = archive_entry_new()) != NULL);
|
|
assert((a = archive_read_disk_new()) != NULL);
|
|
|
|
/*
|
|
* Test1: Traversals without archive_read_disk_set_atime_restored().
|
|
*/
|
|
failure("Directory traversals should work as well");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "at") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/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);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 11);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 11);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "hello world", 11);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 11);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There must be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* On FreeBSD (and likely other systems), atime on
|
|
dirs does not change when it is read. */
|
|
/* failure("Atime should be restored"); */
|
|
/* assertFileAtimeRecent("at"); */
|
|
failure("Atime should be restored");
|
|
assertFileAtimeRecent("at/f1");
|
|
failure("Atime should be restored");
|
|
assertFileAtimeRecent("at/f2");
|
|
failure("The atime of a empty file should not be changed");
|
|
assertFileAtime("at/fe", 886611, 0);
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Test2: Traversals with archive_read_disk_set_atime_restored().
|
|
*/
|
|
assertUtimes("at/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("at/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("at/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("at", 886622, 0, 886622, 0);
|
|
file_count = 4;
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
|
|
|
|
failure("Directory traversals should work as well");
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "at") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/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);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 11);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 11);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "hello world", 11);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 11);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There must be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at", 886622, 0);
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at/f1", 886600, 0);
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at/f2", 886611, 0);
|
|
failure("The atime of a empty file should not be changed");
|
|
assertFileAtime("at/fe", 886611, 0);
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Test3: Traversals with archive_read_disk_set_atime_restored() but
|
|
* no data read as a listing.
|
|
*/
|
|
assertUtimes("at/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("at/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("at/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("at", 886622, 0, 886622, 0);
|
|
file_count = 4;
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
|
|
|
|
failure("Directory traversals should work as well");
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "at") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 10);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 11);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There must be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at", 886622, 0);
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at/f1", 886600, 0);
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at/f2", 886611, 0);
|
|
failure("The atime of a empty file should not be changed");
|
|
assertFileAtime("at/fe", 886611, 0);
|
|
|
|
if (!canNodump()) {
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
archive_entry_free(ae);
|
|
skipping("Can't test atime with nodump on this filesystem");
|
|
return;
|
|
}
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and
|
|
* ARCHIVE_READDISK_HONOR_NODUMP
|
|
*/
|
|
assertSetNodump("at/f1");
|
|
assertSetNodump("at/f2");
|
|
assertUtimes("at/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("at/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("at/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("at", 886622, 0, 886622, 0);
|
|
file_count = 2;
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
|
|
ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
|
|
|
|
failure("Directory traversals should work as well");
|
|
while (file_count--) {
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "at") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
if (archive_entry_filetype(ae) == AE_IFDIR) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There must be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at", 886622, 0);
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at/f1", 886600, 0);
|
|
failure("Atime should be restored");
|
|
assertFileAtime("at/f2", 886611, 0);
|
|
failure("The atime of a empty file should not be changed");
|
|
assertFileAtime("at/fe", 886611, 0);
|
|
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
archive_entry_free(ae);
|
|
}
|
|
|
|
static int
|
|
metadata_filter(struct archive *a, void *data, struct archive_entry *ae)
|
|
{
|
|
(void)data; /* UNUSED */
|
|
|
|
failure("CTime should be set");
|
|
assertEqualInt(8, archive_entry_ctime_is_set(ae));
|
|
failure("MTime should be set");
|
|
assertEqualInt(16, archive_entry_mtime_is_set(ae));
|
|
|
|
if (archive_entry_mtime(ae) < 886611)
|
|
return (0);
|
|
if (archive_read_disk_can_descend(a)) {
|
|
/* Descend into the current object */
|
|
failure("archive_read_disk_can_descend should work"
|
|
" in metadata filter");
|
|
assertEqualIntA(a, 1, archive_read_disk_can_descend(a));
|
|
failure("archive_read_disk_descend should work"
|
|
" in metadata filter");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
static void
|
|
test_callbacks(void)
|
|
{
|
|
struct archive *a;
|
|
struct archive *m;
|
|
struct archive_entry *ae;
|
|
const void *p;
|
|
size_t size;
|
|
int64_t offset;
|
|
int file_count;
|
|
|
|
assertMakeDir("cb", 0755);
|
|
assertMakeFile("cb/f1", 0644, "0123456789");
|
|
assertMakeFile("cb/f2", 0644, "hello world");
|
|
assertMakeFile("cb/fe", 0644, NULL);
|
|
assertUtimes("cb/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("cb/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("cb/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("cb", 886622, 0, 886622, 0);
|
|
|
|
assert((ae = archive_entry_new()) != NULL);
|
|
assert((a = archive_read_disk_new()) != NULL);
|
|
if (a == NULL) {
|
|
archive_entry_free(ae);
|
|
return;
|
|
}
|
|
assert((m = archive_match_new()) != NULL);
|
|
if (m == NULL) {
|
|
archive_entry_free(ae);
|
|
archive_read_free(a);
|
|
archive_match_free(m);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Test1: Traversals with a name filter.
|
|
*/
|
|
file_count = 3;
|
|
assertEqualIntA(m, ARCHIVE_OK,
|
|
archive_match_exclude_pattern(m, "cb/f2"));
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_set_matching(a, m, NULL, NULL));
|
|
failure("Directory traversals should work as well");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
|
|
while (file_count--) {
|
|
archive_entry_clear(ae);
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
failure("File 'cb/f2' should be exclueded");
|
|
assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
|
|
if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "cb/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);
|
|
} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
if (archive_read_disk_can_descend(a)) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There should be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/* Reset name filter */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_set_matching(a, NULL, NULL, NULL));
|
|
|
|
/*
|
|
* Test2: Traversals with a metadata filter.
|
|
*/
|
|
assertUtimes("cb/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("cb/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("cb/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("cb", 886622, 0, 886622, 0);
|
|
file_count = 3;
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
|
|
NULL));
|
|
failure("Directory traversals should work as well");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
|
|
|
|
while (file_count--) {
|
|
archive_entry_clear(ae);
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
failure("File 'cb/f1' should be excluded");
|
|
assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
|
|
if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 11);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 11);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "hello world", 11);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 11);
|
|
} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There should be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
assertEqualInt(ARCHIVE_OK, archive_match_free(m));
|
|
archive_entry_free(ae);
|
|
}
|
|
|
|
static void
|
|
test_nodump(void)
|
|
{
|
|
struct archive *a;
|
|
struct archive_entry *ae;
|
|
const void *p;
|
|
size_t size;
|
|
int64_t offset;
|
|
int file_count;
|
|
|
|
if (!canNodump()) {
|
|
skipping("Can't test nodump on this filesystem");
|
|
return;
|
|
}
|
|
|
|
assertMakeDir("nd", 0755);
|
|
assertMakeFile("nd/f1", 0644, "0123456789");
|
|
assertMakeFile("nd/f2", 0644, "hello world");
|
|
assertMakeFile("nd/fe", 0644, NULL);
|
|
assertSetNodump("nd/f2");
|
|
assertUtimes("nd/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("nd/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("nd/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("nd", 886622, 0, 886622, 0);
|
|
|
|
assert((ae = archive_entry_new()) != NULL);
|
|
assert((a = archive_read_disk_new()) != NULL);
|
|
|
|
/*
|
|
* Test1: Traversals without ARCHIVE_READDISK_HONOR_NODUMP
|
|
*/
|
|
failure("Directory traversals should work as well");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
|
|
|
|
file_count = 4;
|
|
while (file_count--) {
|
|
archive_entry_clear(ae);
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "nd/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);
|
|
} else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 11);
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 11);
|
|
assertEqualInt((int)offset, 0);
|
|
assertEqualMem(p, "hello world", 11);
|
|
assertEqualInt(ARCHIVE_EOF,
|
|
archive_read_data_block(a, &p, &size, &offset));
|
|
assertEqualInt((int)size, 0);
|
|
assertEqualInt((int)offset, 11);
|
|
} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
if (archive_read_disk_can_descend(a)) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There should be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
/* Close the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
|
|
|
|
/*
|
|
* Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP
|
|
*/
|
|
assertUtimes("nd/f1", 886600, 0, 886600, 0);
|
|
assertUtimes("nd/f2", 886611, 0, 886611, 0);
|
|
assertUtimes("nd/fe", 886611, 0, 886611, 0);
|
|
assertUtimes("nd", 886622, 0, 886622, 0);
|
|
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
|
|
ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
|
|
failure("Directory traversals should work as well");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
|
|
|
|
file_count = 3;
|
|
while (file_count--) {
|
|
archive_entry_clear(ae);
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
|
|
failure("File 'nd/f2' should be exclueded");
|
|
assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
|
|
if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
|
|
} else if (strcmp(archive_entry_pathname(ae), "nd/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);
|
|
} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
|
|
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
|
|
assertEqualInt(archive_entry_size(ae), 0);
|
|
}
|
|
if (archive_read_disk_can_descend(a)) {
|
|
/* Descend into the current object */
|
|
assertEqualIntA(a, ARCHIVE_OK,
|
|
archive_read_disk_descend(a));
|
|
}
|
|
}
|
|
/* There is no entry. */
|
|
failure("There should be no entry");
|
|
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
|
|
|
|
failure("Atime should be restored");
|
|
assertFileAtime("nd/f2", 886611, 0);
|
|
|
|
/* Destroy the disk object. */
|
|
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
|
|
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;
|
|
int r;
|
|
#if defined(O_PATH) || defined(O_SEARCH) || \
|
|
(defined(__FreeBSD__) && defined(O_EXEC))
|
|
const char *ignore_traversals_test4;
|
|
|
|
ignore_traversals_test4 = getenv("IGNORE_TRAVERSALS_TEST4");
|
|
#endif
|
|
|
|
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.
|
|
*
|
|
* This test is expected to fail on platforms with no O_EXEC or
|
|
* equivalent (e.g. O_PATH on Linux or O_SEARCH on SunOS), because
|
|
* the current traversal code can't handle the case where it can't
|
|
* obtain an open fd for the initial current directory. We need to
|
|
* check that condition here, because if O_EXEC _does_ exist, we don't
|
|
* want to overlook any failure.
|
|
*/
|
|
assertChdir("lock");
|
|
|
|
failure("Directory traversals should work as well");
|
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1"));
|
|
|
|
archive_entry_clear(ae);
|
|
r = archive_read_next_header2(a, ae);
|
|
if (r == ARCHIVE_FAILED) {
|
|
#if defined(O_PATH) || defined(O_SEARCH) || \
|
|
(defined(__FreeBSD__) && defined(O_EXEC))
|
|
if (ignore_traversals_test4 == NULL)
|
|
assertEqualIntA(a, ARCHIVE_OK, r);
|
|
#endif
|
|
/* Close the disk object. */
|
|
archive_read_close(a);
|
|
} else {
|
|
file_count = 2;
|
|
match_count = 0;
|
|
while (file_count--) {
|
|
if (file_count == 0)
|
|
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("..");
|
|
assertChmod("lock", 0755);
|
|
assertChmod("lock/lock2", 0755);
|
|
|
|
/* 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_basic();
|
|
/* Test hybrid mode; follow symlink initially, then not. */
|
|
test_symlink_hybrid();
|
|
/* Test logical mode; follow all symlinks. */
|
|
test_symlink_logical();
|
|
/* Test logical mode; prevent loop in symlinks. */
|
|
test_symlink_logical_loop();
|
|
/* Test to restore atime. */
|
|
test_restore_atime();
|
|
/* Test callbacks. */
|
|
test_callbacks();
|
|
/* Test nodump. */
|
|
test_nodump();
|
|
/* Test parent overshoot. */
|
|
test_parent();
|
|
}
|