/* Symlink */
if (canSymlink())
- assertIsSymlink("symlink", "file");
+ assertIsSymlink("symlink", "file", 0);
/* Another file with 1 link and different permissions. */
failure(msg);
/* Symlink */
if (canSymlink())
- assertIsSymlink("symlink", "file");
+ assertIsSymlink("symlink", "file", 0);
/* dir */
assertIsDir("dir", 0775);
assertTextFileContents("1 block\n", "copy.err");
failure("Regular -p without -L should preserve symlinks.");
- assertIsSymlink("copy/symlink", NULL);
+ assertIsSymlink("copy/symlink", NULL, 0);
r = systemf(CAT " filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "unpack.err");
assertChdir("..");
- assertIsSymlink("unpack/symlink", NULL);
+ assertIsSymlink("unpack/symlink", NULL, 0);
r = systemf(CAT " filelist | %s -oL >archive-L.out 2>archive-L.err", testprog);
failure("Error invoking %s -oL", testprog);
set = 1;
f = la_GetFunctionKernel32("CreateHardLinkW");
}
- if (!f)
+ if (!f) {
+ errno = ENOTSUP;
return (0);
+ }
ret = (*f)(linkname, target, NULL);
if (!ret) {
/* Under windows 2000, it is necessary to remove
static BOOLEAN (WINAPI *f)(LPCWSTR, LPCWSTR, DWORD);
static int set;
wchar_t *ttarget, *p;
+ int len;
DWORD attrs = 0;
DWORD flags = 0;
DWORD newflags = 0;
if (!f)
return (0);
+ len = wcslen(target);
+ if (len == 0) {
+ errno = EINVAL;
+ return(0);
+ }
/*
* When writing path targets, we need to translate slashes
* to backslashes
*/
- ttarget = malloc((wcslen(target) + 1) * sizeof(wchar_t));
+ ttarget = malloc((len + 1) * sizeof(wchar_t));
if (ttarget == NULL)
return(0);
*p = L'\0';
/*
- * If the target equals ".", ".." or ends with a backslash, it always
- * points to a directory. In this case we can safely set the directory
- * flag. All other symlinks are created as file symlinks.
+ * If the target equals ".", "..", ends with a backslash or a
+ * backslash followed by "." or ".." it always points to a directory.
+ * In this case we can safely set the directory flag.
+ * All other symlinks are created as file symlinks.
*/
- if (wcscmp(ttarget, L".") == 0 || wcscmp(ttarget, L"..") == 0 ||
- *(p - 1) == L'\\') {
+ if (*(p - 1) == L'\\' || (*(p - 1) == L'.' && (
+ len == 1 || *(p - 2) == L'\\' || ( *(p - 2) == L'.' && (
+ len == 2 || *(p - 3) == L'\\'))))) {
#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY)
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
#else
flags |= 0x1;
#endif
- /* Now we remove trailing backslashes, if any */
- p--;
- while(*p == L'\\') {
- *p = L'\0';
- p--;
- }
}
#if defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
#if HAVE_SYMLINK
return symlink(linkname, a->name) ? errno : 0;
#else
+ errno = 0;
r = la_CreateSymbolicLinkW((const wchar_t *)a->name, linkname);
if (r == 0) {
- la_dosmaperr(GetLastError());
+ if (errno == 0)
+ la_dosmaperr(GetLastError());
r = errno;
} else
r = 0;
assertIsDir("dir4/b", 0755);
assertIsDir("dir4/c", 0711);
if (canSymlink())
- assertIsSymlink("symlink", "file");
+ assertIsSymlink("symlink", "file", 0);
free(buff);
free(file_buff);
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
archive_entry_free(ae);
+ /* Symbolic link: dot -> . */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "dot");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, ".");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: dotdot -> .. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "dotdot");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "..");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: slash -> / */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "slash");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "/");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: sldot -> /. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "sldot");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "/.");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: sldotdot -> /.. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "sldotdot");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "/..");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Dir: d1 */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "d1");
+ archive_entry_set_mode(ae, AE_IFDIR | 0777);
+ archive_entry_unset_size(ae);
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: d1nosl -> d1 */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "d1nosl");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "d1");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: d1slash -> d1/ */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "d1slash");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "d1/");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: d1sldot -> d1/. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "d1sldot");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "d1/.");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+ /* Symbolic link: d1slddot -> d1/.. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "d1slddot");
+ archive_entry_set_mode(ae, AE_IFLNK | 0642);
+ archive_entry_unset_size(ae);
+ archive_entry_copy_symlink(ae, "d1/..");
+ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ if (r >= ARCHIVE_WARN)
+ assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+ archive_entry_free(ae);
+
+
assertEqualInt(ARCHIVE_OK, archive_write_free(ad));
/* Test the entries on disk. */
assertIsReg("link1a", -1);
assertFileSize("link1a", sizeof(data));
assertFileNLinks("link1a", 1);
- assertIsSymlink("link1b", "link1a");
+ assertIsSymlink("link1b", "link1a", 0);
/* Test #2: Should produce identical results to test #1 */
assertIsReg("link2a", -1);
assertFileSize("link2a", sizeof(data));
assertFileNLinks("link2a", 1);
- assertIsSymlink("link2b", "link2a");
+ assertIsSymlink("link2b", "link2a", 0);
+
+ /* Test #3: Special symlinks */
+ assertIsSymlink("dot", ".", 1);
+ assertIsSymlink("dotdot", "..", 1);
+ assertIsSymlink("slash", "/", 1);
+ assertIsSymlink("sldot", "/.", 1);
+ assertIsSymlink("sldotdot", "/..", 1);
+
+ /* Test #4: Directory symlink mixed with . and .. */
+ assertIsDir("d1", -1);
+ /* On Windows, d1nosl should be a file symlink */
+ assertIsSymlink("d1nosl", "d1", 0);
+ assertIsSymlink("d1slash", "d1/", 1);
+ assertIsSymlink("d1sldot", "d1/.", 1);
+ assertIsSymlink("d1slddot", "d1/..", 1);
}
/* Symlink */
if (canSymlink())
- assertIsSymlink("symlink", "file");
+ assertIsSymlink("symlink", "file", 0);
/* dir */
failure("%s", target);
sprintf(name1, "s/%s", filenames[i]);
sprintf(name2, "../f/%s", filenames[i]);
if (strlen(name2) <= limit)
- assertIsSymlink(name1, name2);
+ assertIsSymlink(name1, name2, 0);
}
/* Verify dir "d/abcdef...". */
assertChdir("test1");
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
- assertIsSymlink("ld1", "d1");
- assertIsSymlink("d1/link1", "file1");
- assertIsSymlink("d1/linkX", "fileX");
- assertIsSymlink("link2", "d1/file2");
- assertIsSymlink("linkY", "d1/fileY");
+ assertIsSymlink("ld1", "d1", 1);
+ assertIsSymlink("d1/link1", "file1", 0);
+ assertIsSymlink("d1/linkX", "fileX", 0);
+ assertIsSymlink("link2", "d1/file2", 0);
+ assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 2: With -H, no symlink on command line. */
assertChdir("test2");
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
- assertIsSymlink("ld1", "d1");
- assertIsSymlink("d1/link1", "file1");
- assertIsSymlink("d1/linkX", "fileX");
- assertIsSymlink("link2", "d1/file2");
- assertIsSymlink("linkY", "d1/fileY");
+ assertIsSymlink("ld1", "d1", 1);
+ assertIsSymlink("d1/link1", "file1", 0);
+ assertIsSymlink("d1/linkX", "fileX", 0);
+ assertIsSymlink("link2", "d1/file2", 0);
+ assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 3: With -H, some symlinks on command line. */
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsDir("ld1", umasked(0755));
- assertIsSymlink("d1/linkX", "fileX");
- assertIsSymlink("d1/link1", "file1");
+ assertIsSymlink("d1/linkX", "fileX", 0);
+ assertIsSymlink("d1/link1", "file1", 0);
assertIsReg("link2", umasked(0644));
- assertIsSymlink("linkY", "d1/fileY");
+ assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
}
assertChdir("test1");
assertEqualInt(0,
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
- assertIsSymlink("ld1", "d1");
- assertIsSymlink("d1/link1", "file1");
- assertIsSymlink("d1/linkX", "fileX");
- assertIsSymlink("link2", "d1/file2");
- assertIsSymlink("linkY", "d1/fileY");
+ assertIsSymlink("ld1", "d1", 1);
+ assertIsSymlink("d1/link1", "file1", 0);
+ assertIsSymlink("d1/linkX", "fileX", 0);
+ assertIsSymlink("link2", "d1/file2", 0);
+ assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 2: With -L, no symlink on command line. */
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsDir("ld1", umasked(0755));
assertIsReg("d1/link1", umasked(0644));
- assertIsSymlink("d1/linkX", "fileX");
+ assertIsSymlink("d1/linkX", "fileX", 0);
assertIsReg("link2", umasked(0644));
- assertIsSymlink("linkY", "d1/fileY");
+ assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Test 3: With -L, some symlinks on command line. */
systemf("%s -xf archive.tar >c.out 2>c.err", testprog));
assertIsDir("ld1", umasked(0755));
assertIsReg("d1/link1", umasked(0644));
- assertIsSymlink("d1/linkX", "fileX");
+ assertIsSymlink("d1/linkX", "fileX", 0);
assertIsReg("link2", umasked(0644));
- assertIsSymlink("linkY", "d1/fileY");
+ assertIsSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
}
assertMakeSymlink("d1", "realDir", 1);
r = systemf("%s -xf ../archive.tar d1/file1 >test.out 2>test.err", testprog);
assert(r != 0);
- assertIsSymlink("d1", "realDir");
+ assertIsSymlink("d1", "realDir", 1);
assertFileNotExists("d1/file1");
assertEmptyFile("test.out");
assertNonEmptyFile("test.err");
assertMakeSymlink("d1", "realDir", 1);
assertEqualInt(0,
systemf("%s -xPf ../archive.tar d1/file1 >test.out 2>test.err", testprog));
- assertIsSymlink("d1", "realDir");
+ assertIsSymlink("d1", "realDir", 1);
assertFileContents("d1/file1", 8, "d1/file1");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
assertMakeSymlink("d1", "realDir", 1);
assertEqualInt(0,
systemf("%s -xPUf ../archive.tar d1/file1 >test.out 2>test.err", testprog));
- assertIsSymlink("d1", "realDir");
+ assertIsSymlink("d1", "realDir", 1);
assertFileContents("d1/file1", 8, "d1/file1");
assertEmptyFile("test.out");
assertEmptyFile("test.err");
testprog, testprog);
assertFileContents("realfile", 8, "test6a/in/d2/realfile");
assertFileContents("realfile", 8, "test6a/in/d2/symlink");
- assertIsSymlink("test6a/in/d2/symlink", "realfile");
+ assertIsSymlink("test6a/in/d2/symlink", "realfile", 0);
/* At creation time. */
assertMakeDir("test6b", 0755);
systemf("%s -cf - -s /d1/d2/ in/d1 | %s -xf - -C test6b",
testprog, testprog);
assertFileContents("realfile", 8, "test6b/in/d2/realfile");
assertFileContents("realfile", 8, "test6b/in/d2/symlink");
- assertIsSymlink("test6b/in/d2/symlink", "realfile");
+ assertIsSymlink("test6b/in/d2/symlink", "realfile", 0);
}
/*
testprog, testprog);
assertFileContents("realfile", 8, "test7a/in/d1/realfile-renamed");
assertFileContents("realfile", 8, "test7a/in/d1/symlink");
- assertIsSymlink("test7a/in/d1/symlink", "realfile-renamed");
+ assertIsSymlink("test7a/in/d1/symlink", "realfile-renamed", 0);
/* At creation. */
assertMakeDir("test7b", 0755);
systemf("%s -cf - -s /realfile/realfile-renamed/ in/d1 | %s -xf - -C test7b",
testprog, testprog);
assertFileContents("realfile", 8, "test7b/in/d1/realfile-renamed");
assertFileContents("realfile", 8, "test7b/in/d1/symlink");
- assertIsSymlink("test7b/in/d1/symlink", "realfile-renamed");
+ assertIsSymlink("test7b/in/d1/symlink", "realfile-renamed", 0);
}
/*
assertFileContents("realfile", 8, "test10a/in/d1/foo");
assertFileContents("foo", 3, "test10a/in/d1/realfile");
assertFileContents("foo", 3, "test10a/in/d1/symlink");
- assertIsSymlink("test10a/in/d1/symlink", "realfile");
+ assertIsSymlink("test10a/in/d1/symlink", "realfile", 0);
/* At creation. */
assertMakeDir("test10b", 0755);
systemf("%s -cf - -s /realfile/foo/S -s /foo/realfile/ in/d1 | %s -xf - -C test10b",
assertFileContents("realfile", 8, "test10b/in/d1/foo");
assertFileContents("foo", 3, "test10b/in/d1/realfile");
assertFileContents("foo", 3, "test10b/in/d1/symlink");
- assertIsSymlink("test10b/in/d1/symlink", "realfile");
+ assertIsSymlink("test10b/in/d1/symlink", "realfile", 0);
}
/*
assertFileContents("foo", 3, "test11a/in/d1/foo");
assertFileContents("realfile", 8, "test11a/in/d1/realfile");
assertFileContents("foo", 3, "test11a/in/d1/symlink");
- assertIsSymlink("test11a/in/d1/symlink", "foo");
+ assertIsSymlink("test11a/in/d1/symlink", "foo", 0);
/* At creation. */
assertMakeDir("test11b", 0755);
systemf("%s -cf - -s /realfile/foo/R in/d1 | %s -xf - -C test11b",
assertFileContents("foo", 3, "test11b/in/d1/foo");
assertFileContents("realfile", 8, "test11b/in/d1/realfile");
assertFileContents("foo", 3, "test11b/in/d1/symlink");
- assertIsSymlink("test11b/in/d1/symlink", "foo");
+ assertIsSymlink("test11b/in/d1/symlink", "foo", 0);
}
/*
/* If platform supports symlinks, target/s2 is a broken symlink. */
/* If platform does not support symlink, target/s2 doesn't exist. */
if (canSymlink())
- assertIsSymlink("target/s2", "d2/f1");
+ assertIsSymlink("target/s2", "d2/f1", 0);
else
assertFileNotExists("target/s2");
failure("d0/d1/d2 should be extracted");
/* If platform supports symlinks, target/s2 is included. */
if (canSymlink()) {
failure("d0/d1/s2 is a symlink to something included in archive");
- assertIsSymlink("target2/s2", "d2/f1");
+ assertIsSymlink("target2/s2", "d2/f1", 0);
}
failure("d0/d1/d2 should be archived");
assertIsDir("target2/d2", -1);
/* dest2/dir and dest2/dir4 symlinks should be followed */
if (canSymlink()) {
- assertIsSymlink("dest2/dir", "real_dir");
- assertIsSymlink("dest2/dir4", "real_dir");
+ assertIsSymlink("dest2/dir", "real_dir", 1);
+ assertIsSymlink("dest2/dir4", "real_dir", 1);
assertIsDir("dest2/real_dir", -1);
}
assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
#define assertIsReg(pathname, mode) \
assertion_is_reg(__FILE__, __LINE__, pathname, mode)
-#define assertIsSymlink(pathname, contents) \
- assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
+#define assertIsSymlink(pathname, contents, isdir) \
+ assertion_is_symlink(__FILE__, __LINE__, pathname, contents, isdir)
/* Create a directory, report error if it fails. */
#define assertMakeDir(dirname, mode) \
assertion_make_dir(__FILE__, __LINE__, dirname, mode)
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_is_symlink(const char *, int, const char *, const char *, int);
int assertion_make_dir(const char *, int, const char *, int);
int assertion_make_file(const char *, int, const char *, int, int, const void *);
int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
DWORD attrs;
static int set;
- int ret, tmpflags;
+ int ret, tmpflags, llen, tlen;
int flags = 0;
char *src, *tgt, *p;
if (!set) {
if (f == NULL)
return (0);
- tgt = malloc(strlen(target) + 1);
+ tlen = strlen(target);
+ llen = strlen(linkname);
+
+ if (tlen == 0 || llen == 0)
+ return (0);
+
+ tgt = malloc((tlen + 1) * sizeof(char));
if (tgt == NULL)
return (0);
- src = malloc(strlen(linkname) + 1);
+ src = malloc((llen + 1) * sizeof(char));
if (src == NULL) {
free(tgt);
return (0);
*p = '\0';
/*
- * If the target equals ".", ".." or ends with a slash, it always
- * points to a directory. In this case we can set the directory flag.
+ * Each test has to specify if a file or a directory symlink
+ * should be created.
*/
if (targetIsDir) {
#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY)
return (1);
}
-/* Check whether 'pathname' is a symbolic link. If 'contents' is
- * non-NULL, verify that the symlink has those contents. */
+/*
+ * Check whether 'pathname' is a symbolic link. If 'contents' is
+ * non-NULL, verify that the symlink has those contents.
+ *
+ * On platforms with directory symlinks, set isdir to 0 to test for a file
+ * symlink and to 1 to test for a directory symlink. On other platforms
+ * the variable is ignored.
+ */
static int
is_symlink(const char *file, int line,
- const char *pathname, const char *contents)
+ const char *pathname, const char *contents, int isdir)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
HANDLE h;
DWORD inbytes;
REPARSE_DATA_BUFFER *buf;
+ BY_HANDLE_FILE_INFORMATION st;
size_t len, len2;
wchar_t *linknamew, *contentsw;
const char *p;
char *s, *pn;
int ret = 0;
BYTE *indata;
- DWORD flag = FILE_FLAG_BACKUP_SEMANTICS |
+ static DWORD flag = FILE_FLAG_BACKUP_SEMANTICS |
FILE_FLAG_OPEN_REPARSE_POINT;
/* Replace slashes with backslashes in pathname */
h = CreateFileA(pn, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
flag, NULL);
free(pn);
- if (h == INVALID_HANDLE_VALUE)
+ if (h == INVALID_HANDLE_VALUE) {
+ failure_start(file, line, "Can't access %s\n", pathname);
+ failure_finish(NULL);
return (0);
+ }
+ ret = GetFileInformationByHandle(h, &st);
+ if (ret == 0) {
+ failure_start(file, line,
+ "Can't stat: %s", pathname);
+ failure_finish(NULL);
+ } else if ((st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
+ failure_start(file, line,
+ "Not a symlink: %s", pathname);
+ failure_finish(NULL);
+ ret = 0;
+ }
+ if (isdir && ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
+ failure_start(file, line,
+ "Not a directory symlink: %s", pathname);
+ failure_finish(NULL);
+ ret = 0;
+ }
+ if (!isdir &&
+ ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
+ failure_start(file, line,
+ "Not a file symlink: %s", pathname);
+ failure_finish(NULL);
+ ret = 0;
+ }
+ if (ret == 0) {
+ CloseHandle(h);
+ return (0);
+ }
indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata,
CloseHandle(h);
if (ret == 0) {
free(indata);
+ failure_start(file, line,
+ "Could not retrieve symlink target: %s", pathname);
+ failure_finish(NULL);
return (0);
}
if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
free(indata);
/* File is not a symbolic link */
- errno = EINVAL;
+ failure_start(file, line,
+ "Not a symlink: %s", pathname);
+ failure_finish(NULL);
return (0);
}
ssize_t linklen;
int r;
+ (void)isdir; /* UNUSED */
assertion_count(file, line);
r = lstat(pathname, &st);
if (r != 0) {
/* 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)
+ const char *path, const char *contents, int isdir)
{
- if (is_symlink(file, line, path, contents))
+ if (is_symlink(file, line, path, contents, isdir))
return (1);
if (contents)
failure_start(file, line, "File %s is not a symlink to %s",
* use the Win32 CreateSymbolicLink() function. */
#if defined(_WIN32) && !defined(__CYGWIN__)
value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
- && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0",
+ 0);
#elif HAVE_SYMLINK
value = (0 == symlink("canSymlink.0", "canSymlink.1"))
- && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0",
+ 0);
#endif
return (value);
}