* TODO: Move this into a separate configuration header, have all test
* suites share one copy of this file.
*/
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kientzle Exp $");
+#define KNOWNREF "test_option_f.cpio.uu"
+#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */
#define PROGRAM "bsdcpio" /* Name of program being tested. */
#undef LIBRARY /* Not testing a library. */
-#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */
#undef EXTRA_DUMP /* How to dump extra data */
/* How to generate extra version info. */
#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
-#define KNOWNREF "test_option_f.cpio.uu"
-__FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kientzle Exp $");
/*
*
return (value);
}
+/*
+ * Can this platform run the gzip program?
+ */
+/* Platform-dependent options for hiding the output of a subcommand. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
+#else
+static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
+#endif
+int
+canGzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the gunzip program?
+ */
+int
+canGunzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gunzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
/*
* Sleep as needed; useful for verifying disk timestamp changes by
* ensuring that the wall-clock time has actually changed before we
/* Return true if this platform can create symlinks. */
int canSymlink(void);
+/* Return true if this platform can run the "gzip" program. */
+int canGzip(void);
+
+/* Return true if this platform can run the "gunzip" program. */
+int canGunzip(void);
+
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
* TODO: Move this into a separate configuration header, have all test
* suites share one copy of this file.
*/
+__FBSDID("$FreeBSD: src/lib/libarchive/test/main.c,v 1.17 2008/12/21 00:13:50 kientzle Exp $");
+#define KNOWNREF "test_compat_gtar_1.tar.uu"
+#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */
#undef PROGRAM /* Testing a library, not a program. */
#define LIBRARY "libarchive"
-#define ENVBASE "LIBARCHIVE" /* Prefix for environment variables. */
#define EXTRA_DUMP(x) archive_error_string((struct archive *)(x))
#define EXTRA_VERSION archive_version()
-#define KNOWNREF "test_compat_gtar_1.tar.uu"
-__FBSDID("$FreeBSD: src/lib/libarchive/test/main.c,v 1.17 2008/12/21 00:13:50 kientzle Exp $");
/*
*
}
return f == NULL ? 0 : (*f)(linkname, target, NULL);
}
+
+int
+my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
+{
+ HANDLE h;
+ int r;
+
+ h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return (0);
+ r = GetFileInformationByHandle(h, bhfi);
+ CloseHandle(h);
+ return (r);
+}
#endif
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
return (0);
}
-/* Verify that two paths point to the same file. */
-int
-assertion_file_hardlinks(const char *file, int line,
+/* Test that two paths point to the same file. */
+/* As a side-effect, asserts that both files exist. */
+static int
+is_hardlink(const char *file, int line,
const char *path1, const char *path2)
{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
+ int r;
+
+ assertion_count(file, line);
+ r = my_GetFileInformationByName(path1, &bhfi1);
+ if (r == 0) {
+ failure_start(file, line, "File %s can't be inspected?", path1);
+ failure_finish(NULL);
+ return (0);
+ }
+ r = my_GetFileInformationByName(path2, &bhfi2);
+ if (r == 0) {
+ failure_start(file, line, "File %s can't be inspected?", path2);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
+ && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
+#else
struct stat st1, st2;
int r;
failure_finish(NULL);
return (0);
}
- if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
- failure_start(file, line,
- "Files %s and %s are not hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
- }
- return (1);
+ return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
+#endif
+}
+
+int
+assertion_is_hardlink(const char *file, int line,
+ const char *path1, const char *path2)
+{
+ if (is_hardlink(file, line, path1, path2))
+ return (1);
+ failure_start(file, line,
+ "Files %s and %s are not hardlinked", path1, path2);
+ failure_finish(NULL);
+ return (0);
+}
+
+int
+assertion_is_not_hardlink(const char *file, int line,
+ const char *path1, const char *path2)
+{
+ if (!is_hardlink(file, line, path1, path2))
+ return (1);
+ failure_start(file, line,
+ "Files %s and %s should not be hardlinked", path1, path2);
+ failure_finish(NULL);
+ return (0);
}
/* Verify a/b/mtime of 'pathname'. */
const char *pathname, int nlinks)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- HANDLE h;
BY_HANDLE_FILE_INFORMATION bhfi;
int r;
assertion_count(file, line);
- h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = GetFileInformationByHandle(h, &bhfi);
+ r = my_GetFileInformationByName(pathname, &bhfi);
if (r != 0 && bhfi.nNumberOfLinks == nlinks)
return (1);
failure_start(file, line, "File %s has %d links, expected %d",
return (1);
}
-/* Verify that 'pathname' is a symbolic link. If 'contents' is
+/* Check whether 'pathname' is a symbolic link. If 'contents' is
* non-NULL, verify that the symlink has those contents. */
-int
-assertion_is_symlink(const char *file, int line,
+static int
+is_symlink(const char *file, int line,
const char *pathname, const char *contents)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
assertion_count(file, line);
- /* TODO: Vista supports symlinks */
- failure_start(file, line, "Symlink %s not supported", pathname);
- failure_finish(NULL);
return (0);
#else
char buff[300];
failure_finish(NULL);
return (0);
}
- if (!S_ISLNK(st.st_mode)) {
- failure_start(file, line, "%s should be a symlink", pathname);
- failure_finish(NULL);
+ if (!S_ISLNK(st.st_mode))
return (0);
- }
if (contents == NULL)
return (1);
linklen = readlink(pathname, buff, sizeof(buff));
return (0);
}
buff[linklen] = '\0';
- if (strcmp(buff, contents) != 0) {
- failure_start(file, line, "Wrong symlink %s", pathname);
- logprintf(" Expected: %s\n", contents);
- logprintf(" Found: %s\n", buff);
- failure_finish(NULL);
+ if (strcmp(buff, contents) != 0)
return (0);
- }
return (1);
#endif
}
+/* Assert that path is a symlink that (optionally) contains contents. */
+int
+assertion_is_symlink(const char *file, int line,
+ const char *path, const char *contents)
+{
+ if (is_symlink(file, line, path, contents))
+ return (1);
+ if (contents)
+ failure_start(file, line, "File %s is not a symlink to %s",
+ path, contents);
+ else
+ failure_start(file, line, "File %s is not a symlink", path);
+ failure_finish(NULL);
+ return (0);
+}
+
+
/* Create a directory and report any errors. */
int
assertion_make_dir(const char *file, int line, const char *dirname, int mode)
*
*/
+/*
+ * Check whether platform supports symlinks. This is intended
+ * for tests to use in deciding whether to bother testing symlink
+ * support; if the platform doesn't support symlinks, there's no point
+ * in checking whether the program being tested can create them.
+ */
+int
+canSymlink(void)
+{
+ /* Remember the test result */
+ static int value = 0, tested = 1;
+ if (tested)
+ return (value);
+
+ ++tested;
+ assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, "a");
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
+#elif HAVE_SYMLINK
+ value = (0 == symlink("canSymlink.0", "canSymlink.1"))
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
+#endif
+ return (value);
+}
+
+/*
+ * Can this platform run the gzip program?
+ */
+/* Platform-dependent options for hiding the output of a subcommand. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
+#else
+static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
+#endif
+int
+canGzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the gunzip program?
+ */
+int
+canGunzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gunzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
/*
* Sleep as needed; useful for verifying disk timestamp changes by
* ensuring that the wall-clock time has actually changed before we
return (tests_failed ? 1 : 0);
}
-
-/*
- *
- * Special support specifically for libarchive.
- *
- */
-
-/* Since gzip is by far the most popular external compression program
- * available, we try to use it in the read_program and write_program
- * tests. But if it's not available, then we can't use it. This
- * function just tries to run gzip/gunzip to see if they're available.
- * If not, some of the external compression program tests will be
- * skipped. */
-const char *
-external_gzip_program(int un)
-{
- static int tested = 0;
- static const char *compress_prog = NULL;
- static const char *decompress_prog = NULL;
- /* Args vary depending on the command interpreter we're using. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
- static const char *args = "-V >NUL 2>NUL"; /* Win32 cmd.exe */
-#else
- static const char *args = "-V >/dev/null 2>/dev/null"; /* POSIX 'sh' */
-#endif
-
- if (!tested) {
- if (systemf("gunzip %s", args) == 0)
- decompress_prog = "gunzip";
- if (systemf("gzip %s", args) == 0)
- compress_prog = "gzip";
- tested = 1;
- }
- return (un ? decompress_prog : compress_prog);
-}
/* Assert that file contents match a string; supports printf-style arguments. */
#define assertFileContents \
assertion_setup(__FILE__, __LINE__);assertion_file_contents
-#define assertFileHardlinks(path1, path2) \
- assertion_file_hardlinks(__FILE__, __LINE__, path1, path2)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
#define assertIsDir(pathname, mode) \
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
+#define assertIsHardlink(path1, path2) \
+ assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
+#define assertIsNotHardlink(path1, path2) \
+ assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsReg(pathname, mode) \
assertion_is_reg(__FILE__, __LINE__, pathname, mode)
#define assertIsSymlink(pathname, contents) \
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contents(const void *, int, const char *, ...);
int assertion_file_exists(const char *, ...);
-int assertion_file_hardlinks(const char *, int, const char *, const char *);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
int assertion_file_not_exists(const char *, ...);
int assertion_file_size(const char *, int, const char *, long);
int assertion_is_dir(const char *, int, const char *, int);
+int assertion_is_hardlink(const char *, int, const char *, const char *);
+int assertion_is_not_hardlink(const char *, int, const char *, const char *);
int assertion_is_reg(const char *, int, const char *, int);
int assertion_is_symlink(const char *, int, const char *, const char *);
int assertion_make_dir(const char *, int, const char *, int);
int assertion_text_file_contents(const char *buff, const char *f);
int assertion_umask(const char *, int, int);
void assertion_setup(const char *, int);
+
void test_skipping(const char *fmt, ...);
/* Like sprintf, then system() */
/* Delay until time() returns a value after this. */
void sleepUntilAfter(time_t);
+/* Return true if this platform can create symlinks. */
+int canSymlink(void);
+
+/* Return true if this platform can run the "gzip" program. */
+int canGzip(void);
+
+/* Return true if this platform can run the "gunzip" program. */
+int canGunzip(void);
+
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
* Special interfaces for libarchive test harness.
*/
-/* Get external gzip program name */
-const char *external_gzip_program(int un);
-
#include "archive.h"
#include "archive_entry.h"
/* "2" version exercises a slightly different set of libarchive APIs. */
int read_open_memory2(struct archive *, void *, size_t, size_t);
-/*
- * ARCHIVE_VERSION_STAMP first appeared in 1.9 and libarchive 2.2.4.
- * We can approximate it for earlier versions, though.
- * This is used to disable tests of features not present in the current
- * version.
- */
-#ifndef ARCHIVE_VERSION_STAMP
-#define ARCHIVE_VERSION_STAMP \
- (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
-#endif
-
/* Versions of above that accept an archive argument for additional info. */
#define assertA(e) assertion_assert(__FILE__, __LINE__, (e), #e, (a))
#define assertEqualIntA(a,v1,v2) \
int r;
struct archive_entry *ae;
struct archive *a;
- const char *extprog;
/*
* First, test handling when a non-existent compression
/*
* If we have "gzip -d", try using that.
*/
- if ((extprog = external_gzip_program(1)) == NULL) {
- skipping("There is no gzip uncompression "
- "program in this platform");
+ if (!canGunzip()) {
+ skipping("Can't run gunzip program on this platform");
return;
}
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_compression_none(a));
assertEqualIntA(a, ARCHIVE_OK,
- archive_read_support_compression_program(a, extprog));
+ archive_read_support_compression_program(a, "gunzip"));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK,
size_t used;
int blocksize = 1024;
int r;
- const char *compprog, *decompprog;
- decompprog = external_gzip_program(1);
- if ((compprog = external_gzip_program(0)) == NULL) {
- skipping("There is no gzip compression "
- "program in this platform");
+ if (!canGzip()) {
+ skipping("Cannot run 'gzip'");
return;
}
/* Write it through an external "gzip" program. */
assert((a = archive_write_new()) != NULL);
assertA(0 == archive_write_set_format_ustar(a));
- r = archive_write_set_compression_program(a, compprog);
+ r = archive_write_set_compression_program(a, "gzip");
if (r == ARCHIVE_FATAL) {
skipping("Write compression via external "
"program unsupported on this platform");
/* The compression_gzip() handler will fall back to gunzip
* automatically, but if we know gunzip isn't available, then
* skip the rest. */
- if (r != ARCHIVE_OK && decompprog == NULL) {
- skipping("No gzip decompression is available; "
+ if (r != ARCHIVE_OK && !canGunzip()) {
+ skipping("No libz and no gunzip program, "
"unable to verify gzip compression");
assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
return;
assertIsReg("link1a", 0755 & ~UMASK);
assertFileSize("link1a", sizeof(data));
assertFileNLinks("link1a", 2);
- assertFileHardlinks("link1a", "link1b");
+ assertIsHardlink("link1a", "link1b");
/* Test #2: Should produce identical results to test #1 */
/* Note that marking a hardlink with size = 0 is treated the
assertIsReg("link2a", 0755 & ~UMASK);
assertFileSize("link2a", sizeof(data));
assertFileNLinks("link2a", 2);
- assertFileHardlinks("link2a", "link2b");
+ assertIsHardlink("link2a", "link2b");
/* Test #3 */
assertIsReg("link3a", 0755 & ~UMASK);
assertFileSize("link3a", sizeof(data));
assertFileNLinks("link3a", 2);
- assertFileHardlinks("link3a", "link3b");
+ assertIsHardlink("link3a", "link3b");
/* Test #4 */
assertIsReg("link4a", 0755 & ~UMASK);
assertFileNLinks("link4a", 2);
assertFileSize("link4a", sizeof(data));
- assertFileHardlinks("link4a", "link4b");
+ assertIsHardlink("link4a", "link4b");
#endif
}
* TODO: Move this into a separate configuration header, have all test
* suites share one copy of this file.
*/
+__FBSDID("$FreeBSD: src/usr.bin/tar/test/main.c,v 1.6 2008/11/05 06:40:53 kientzle Exp $");
+#define KNOWNREF "test_patterns_2.tar.uu"
+#define ENVBASE "BSDTAR" /* Prefix for environment variables. */
#define PROGRAM "bsdtar" /* Name of program being tested. */
#undef LIBRARY /* Not testing a library. */
-#define ENVBASE "BSDTAR" /* Prefix for environment variables. */
#undef EXTRA_DUMP /* How to dump extra data */
/* How to generate extra version info. */
#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
-#define KNOWNREF "test_patterns_2.tar.uu"
-__FBSDID("$FreeBSD: src/usr.bin/tar/test/main.c,v 1.6 2008/11/05 06:40:53 kientzle Exp $");
/*
*
}
return f == NULL ? 0 : (*f)(linkname, target, NULL);
}
+
+int
+my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
+{
+ HANDLE h;
+ int r;
+
+ h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return (0);
+ r = GetFileInformationByHandle(h, bhfi);
+ CloseHandle(h);
+ return (r);
+}
#endif
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
return (0);
}
-/* Verify that two paths point to the same file. */
-int
-assertion_file_hardlinks(const char *file, int line,
+/* Test that two paths point to the same file. */
+/* As a side-effect, asserts that both files exist. */
+static int
+is_hardlink(const char *file, int line,
const char *path1, const char *path2)
{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
+ int r;
+
+ assertion_count(file, line);
+ r = my_GetFileInformationByName(path1, &bhfi1);
+ if (r == 0) {
+ failure_start(file, line, "File %s can't be inspected?", path1);
+ failure_finish(NULL);
+ return (0);
+ }
+ r = my_GetFileInformationByName(path2, &bhfi2);
+ if (r == 0) {
+ failure_start(file, line, "File %s can't be inspected?", path2);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
+ && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
+#else
struct stat st1, st2;
int r;
failure_finish(NULL);
return (0);
}
- if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
- failure_start(file, line,
- "Files %s and %s are not hardlinked", path1, path2);
- failure_finish(NULL);
- return (0);
- }
- return (1);
+ return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
+#endif
+}
+
+int
+assertion_is_hardlink(const char *file, int line,
+ const char *path1, const char *path2)
+{
+ if (is_hardlink(file, line, path1, path2))
+ return (1);
+ failure_start(file, line,
+ "Files %s and %s are not hardlinked", path1, path2);
+ failure_finish(NULL);
+ return (0);
+}
+
+int
+assertion_is_not_hardlink(const char *file, int line,
+ const char *path1, const char *path2)
+{
+ if (!is_hardlink(file, line, path1, path2))
+ return (1);
+ failure_start(file, line,
+ "Files %s and %s should not be hardlinked", path1, path2);
+ failure_finish(NULL);
+ return (0);
}
/* Verify a/b/mtime of 'pathname'. */
const char *pathname, int nlinks)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- HANDLE h;
BY_HANDLE_FILE_INFORMATION bhfi;
int r;
assertion_count(file, line);
- h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- failure_start(file, line, "Can't access %s", pathname);
- failure_finish(NULL);
- return (0);
- }
- r = GetFileInformationByHandle(h, &bhfi);
+ r = my_GetFileInformationByName(pathname, &bhfi);
if (r != 0 && bhfi.nNumberOfLinks == nlinks)
return (1);
failure_start(file, line, "File %s has %d links, expected %d",
return (1);
}
-/* Verify that 'pathname' is a symbolic link. If 'contents' is
+/* Check whether 'pathname' is a symbolic link. If 'contents' is
* non-NULL, verify that the symlink has those contents. */
-int
-assertion_is_symlink(const char *file, int line,
+static int
+is_symlink(const char *file, int line,
const char *pathname, const char *contents)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
assertion_count(file, line);
- /* TODO: Vista supports symlinks */
- failure_start(file, line, "Symlink %s not supported", pathname);
- failure_finish(NULL);
return (0);
#else
char buff[300];
failure_finish(NULL);
return (0);
}
- if (!S_ISLNK(st.st_mode)) {
- failure_start(file, line, "%s should be a symlink", pathname);
- failure_finish(NULL);
+ if (!S_ISLNK(st.st_mode))
return (0);
- }
if (contents == NULL)
return (1);
linklen = readlink(pathname, buff, sizeof(buff));
return (0);
}
buff[linklen] = '\0';
- if (strcmp(buff, contents) != 0) {
- failure_start(file, line, "Wrong symlink %s", pathname);
- logprintf(" Expected: %s\n", contents);
- logprintf(" Found: %s\n", buff);
- failure_finish(NULL);
+ if (strcmp(buff, contents) != 0)
return (0);
- }
return (1);
#endif
}
+/* Assert that path is a symlink that (optionally) contains contents. */
+int
+assertion_is_symlink(const char *file, int line,
+ const char *path, const char *contents)
+{
+ if (is_symlink(file, line, path, contents))
+ return (1);
+ if (contents)
+ failure_start(file, line, "File %s is not a symlink to %s",
+ path, contents);
+ else
+ failure_start(file, line, "File %s is not a symlink", path);
+ failure_finish(NULL);
+ return (0);
+}
+
+
/* Create a directory and report any errors. */
int
assertion_make_dir(const char *file, int line, const char *dirname, int mode)
*
*/
+/*
+ * Check whether platform supports symlinks. This is intended
+ * for tests to use in deciding whether to bother testing symlink
+ * support; if the platform doesn't support symlinks, there's no point
+ * in checking whether the program being tested can create them.
+ */
+int
+canSymlink(void)
+{
+ /* Remember the test result */
+ static int value = 0, tested = 1;
+ if (tested)
+ return (value);
+
+ ++tested;
+ assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, "a");
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
+#elif HAVE_SYMLINK
+ value = (0 == symlink("canSymlink.0", "canSymlink.1"))
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
+#endif
+ return (value);
+}
+
+/*
+ * Can this platform run the gzip program?
+ */
+/* Platform-dependent options for hiding the output of a subcommand. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
+#else
+static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
+#endif
+int
+canGzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the gunzip program?
+ */
+int
+canGunzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gunzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
/*
* Sleep as needed; useful for verifying disk timestamp changes by
* ensuring that the wall-clock time has actually changed before we
/* Assert that file contents match a string; supports printf-style arguments. */
#define assertFileContents \
assertion_setup(__FILE__, __LINE__);assertion_file_contents
-#define assertFileHardlinks(path1, path2) \
- assertion_file_hardlinks(__FILE__, __LINE__, path1, path2)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
#define assertIsDir(pathname, mode) \
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
+#define assertIsHardlink(path1, path2) \
+ assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
+#define assertIsNotHardlink(path1, path2) \
+ assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsReg(pathname, mode) \
assertion_is_reg(__FILE__, __LINE__, pathname, mode)
#define assertIsSymlink(pathname, contents) \
int assertion_file_birthtime_recent(const char *, int, const char *);
int assertion_file_contents(const void *, int, const char *, ...);
int assertion_file_exists(const char *, ...);
-int assertion_file_hardlinks(const char *, int, const char *, const char *);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
int assertion_file_not_exists(const char *, ...);
int assertion_file_size(const char *, int, const char *, long);
int assertion_is_dir(const char *, int, const char *, int);
+int assertion_is_hardlink(const char *, int, const char *, const char *);
+int assertion_is_not_hardlink(const char *, int, const char *, const char *);
int assertion_is_reg(const char *, int, const char *, int);
int assertion_is_symlink(const char *, int, const char *, const char *);
int assertion_make_dir(const char *, int, const char *, int);
int assertion_text_file_contents(const char *buff, const char *f);
int assertion_umask(const char *, int, int);
void assertion_setup(const char *, int);
+
void test_skipping(const char *fmt, ...);
/* Like sprintf, then system() */
/* Delay until time() returns a value after this. */
void sleepUntilAfter(time_t);
+/* Return true if this platform can create symlinks. */
+int canSymlink(void);
+
+/* Return true if this platform can run the "gzip" program. */
+int canGzip(void);
+
+/* Return true if this platform can run the "gunzip" program. */
+int canGunzip(void);
+
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
assertIsReg("linkfile", -1);
assertFileSize("linkfile", 10);
assertFileNLinks("linkfile", 2);
- assertFileHardlinks("file", "linkfile");
+ assertIsHardlink("file", "linkfile");
-#if !defined(_WIN32) || defined(__CYGWIN__)
/* Symlink */
- assertIsSymlink("symlink", "file");
-#endif
+ if (canSymlink())
+ assertIsSymlink("symlink", "file");
/* dir */
assertIsDir("dir", 0775);
assertMakeHardlink("linkfile", "file");
/* Symlink to above file. */
- assertMakeSymlink("symlink", "file");
+ if (canSymlink())
+ assertMakeSymlink("symlink", "file");
/* Directory. */
assertMakeDir("dir", 0775);
- flist = "file linkfile symlink dir";
+ if (canSymlink())
+ flist = "file linkfile symlink dir";
+ else
+ flist = "file linkfile dir";
/* Archive/dearchive with a variety of options. */
basic_tar("copy", "", "", flist);
/* tar doesn't handle cpio symlinks correctly */
# include <sys/cygwin.h>
#endif
-/* assumes that cwd is the top of the test tree. Furthermore,
- * assumes that this function is first called with the "longest"
- * cwd involved in the tests. That is, from
- * <testdir>/original
- * as opposed to
- * <testdir>/plain or <testdir>/ustar
+/*
+ * Try to figure out how deep we can go in our tests. Assumes that
+ * the first call to this function has the longest starting cwd (which
+ * is currently "<testdir>/original"). This is mostly to work around
+ * limits in our Win32 support.
+ *
+ * Background: On Posix systems, PATH_MAX is merely a limit on the
+ * length of the string passed into a system call. By repeatedly
+ * calling chdir(), you can work with arbitrarily long paths on such
+ * systems. In contrast, Win32 APIs apply PATH_MAX limits to the full
+ * absolute path, so the permissible length of a system call argument
+ * varies with the cwd. Some APIs actually enforce limits
+ * significantly less than PATH_MAX to ensure that you can create
+ * files within the current working directory. The Win32 limits also
+ * apply to Cygwin before 1.7.
+ *
+ * Someday, I want to convert the Win32 support to use newer
+ * wide-character paths with '\\?\' prefix, which has a 32k PATH_MAX
+ * instead of the rather anemic 260 character limit of the older
+ * system calls. Then we can drop this mess (unless we want to
+ * continue to special-case Cygwin 1.5 and earlier).
*/
static int
compute_loop_max(void)
if (LOOP_MAX == 0) {
assert(_getcwd(buf, MAX_PATH) != NULL);
cwdlen = strlen(buf);
- /* on windows, can't create a directory in which there is not
- * enough room left in MAX_PATH to /also/ create an 8.3 file.
- * Thus, max path len for mkdir is MAX_PATH - 12 ("12345678.123")
- * It is possible also that windows counts the length of cwd against
- * the MAX_PATH maximum, so account for that. Next, account also for
- * "/". And lastly, account for the fact that the relative path
- * has 4 characters when the loop count i = 0.
- */
- LOOP_MAX = MAX_PATH - 12 - (int)cwdlen - 1 - 4;
+ /* 12 characters = length of 8.3 filename */
+ /* 4 characters = length of "/../" used in symlink tests */
+ /* 1 character = length of extra "/" separator */
+ LOOP_MAX = MAX_PATH - (int)cwdlen - 12 - 4 - 1;
}
return LOOP_MAX;
#elif defined(__CYGWIN__) && !defined(HAVE_CYGWIN_CONV_PATH)
cygwin_conv_to_full_win32_path(pbuf, wbuf);
wcwdlen = strlen(wbuf);
cwdlen = ((wcwdlen > pcwdlen) ? wcwdlen : pcwdlen);
- /* on windows, can't create a directory in which there is not
- * enough room left in PATH_MAX to /also/ create an 8.3 file.
- * Thus, max path len for mkdir is PATH_MAX - 12 ("12345678.123")
- * Then, because cygwin treats even relative paths as if they were
- * absolute, and cwd counts against the PATH_MAX maximum, we must
- * account for that (using worst case of posix or win32 equivalents).
- * Next, account also for "/../" (as used in symlink creation test).
- * And lastly, account for the fact that the relative path has 4
- * characters when the loop count i = 0. These calculations do not
- * apply to cygwin-1.7, because unlike older cygwin, it uses the "wide"
- * functions of the win32 system for all file and directory access.
- */
- LOOP_MAX = PATH_MAX - 12 - (int)cwdlen - 4 - 4;
+ /* Cygwin helper needs an extra few characters. */
+ LOOP_MAX = PATH_MAX - (int)cwdlen - 12 - 4 - 4;
}
return LOOP_MAX;
#else
buff2[0] = 'm';
assertMakeHardlink(buff2, buff);
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Create a symlink named "s/abcdef..." to the above. */
- strcpy(buff2 + 3, buff);
- buff[0] = 's';
- buff2[0] = '.';
- buff2[1] = '.';
- buff2[2] = '/';
- failure("buff=\"%s\" buff2=\"%s\"", buff, buff2);
- assertMakeSymlink(buff, buff2);
-#else
- skipping("create a symlink to the above");
-#endif
+ if (canSymlink()) {
+ /* Create a symlink named "s/abcdef..." to the above. */
+ strcpy(buff2 + 3, buff);
+ buff[0] = 's';
+ buff2[0] = '.';
+ buff2[1] = '.';
+ buff2[2] = '/';
+ failure("buff=\"%s\" buff2=\"%s\"", buff, buff2);
+ assertMakeSymlink(buff, buff2);
+ } else {
+ skipping("Symlink tests");
+ }
/* Create a dir named "d/abcdef...". */
buff[0] = 'd';
failure("buff=\"%s\"", buff);
strcat(name2, filename);
if (limit != LIMIT_USTAR || strlen(name2) <= 100) {
/* Verify hardlink "l/abcdef..." */
- assertFileHardlinks(name1, name2);
+ assertIsHardlink(name1, name2);
/* Verify hardlink "m/abcdef..." */
name2[0] = 'm';
- assertFileHardlinks(name1, name2);
+ assertIsHardlink(name1, name2);
}
-#if !defined(_WIN32) || defined(__CYGWIN__)
- /* Verify symlink "s/abcdef..." */
- strcpy(name1, "s/");
- strcat(name1, filename);
- strcpy(name2, "../f/");
- strcat(name2, filename);
- if (limit != LIMIT_USTAR || strlen(name2) <= 100)
- assertIsSymlink(name1, name2);
-#else
- skipping("verify symlink");
-#endif
+ if (canSymlink()) {
+ /* Verify symlink "s/abcdef..." */
+ strcpy(name1, "s/");
+ strcat(name1, filename);
+ strcpy(name2, "../f/");
+ strcat(name2, filename);
+ if (limit != LIMIT_USTAR || strlen(name2) <= 100)
+ assertIsSymlink(name1, name2);
+ }
/* Verify dir "d/abcdef...". */
strcpy(name1, "d/");