Deleted Added
full compact
test_main.c (344673) test_main.c (348607)
1/*
2 * Copyright (c) 2003-2009 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 154 unchanged lines hidden (view full) ---

163
164#if defined(_WIN32) && !defined(__CYGWIN__)
165static void *GetFunctionKernel32(const char *);
166static int my_CreateSymbolicLinkA(const char *, const char *, int);
167static int my_CreateHardLinkA(const char *, const char *);
168static int my_GetFileInformationByName(const char *,
169 BY_HANDLE_FILE_INFORMATION *);
170
1/*
2 * Copyright (c) 2003-2009 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 154 unchanged lines hidden (view full) ---

163
164#if defined(_WIN32) && !defined(__CYGWIN__)
165static void *GetFunctionKernel32(const char *);
166static int my_CreateSymbolicLinkA(const char *, const char *, int);
167static int my_CreateHardLinkA(const char *, const char *);
168static int my_GetFileInformationByName(const char *,
169 BY_HANDLE_FILE_INFORMATION *);
170
171typedef struct _REPARSE_DATA_BUFFER {
172 ULONG ReparseTag;
173 USHORT ReparseDataLength;
174 USHORT Reserved;
175 union {
176 struct {
177 USHORT SubstituteNameOffset;
178 USHORT SubstituteNameLength;
179 USHORT PrintNameOffset;
180 USHORT PrintNameLength;
181 ULONG Flags;
182 WCHAR PathBuffer[1];
183 } SymbolicLinkReparseBuffer;
184 struct {
185 USHORT SubstituteNameOffset;
186 USHORT SubstituteNameLength;
187 USHORT PrintNameOffset;
188 USHORT PrintNameLength;
189 WCHAR PathBuffer[1];
190 } MountPointReparseBuffer;
191 struct {
192 UCHAR DataBuffer[1];
193 } GenericReparseBuffer;
194 } DUMMYUNIONNAME;
195} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
196
171static void *
172GetFunctionKernel32(const char *name)
173{
174 static HINSTANCE lib;
175 static int set;
176 if (!set) {
177 set = 1;
178 lib = LoadLibrary("kernel32.dll");
179 }
180 if (lib == NULL) {
181 fprintf(stderr, "Can't load kernel32.dll?!\n");
182 exit(1);
183 }
184 return (void *)GetProcAddress(lib, name);
185}
186
187static int
197static void *
198GetFunctionKernel32(const char *name)
199{
200 static HINSTANCE lib;
201 static int set;
202 if (!set) {
203 set = 1;
204 lib = LoadLibrary("kernel32.dll");
205 }
206 if (lib == NULL) {
207 fprintf(stderr, "Can't load kernel32.dll?!\n");
208 exit(1);
209 }
210 return (void *)GetProcAddress(lib, name);
211}
212
213static int
188my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
214my_CreateSymbolicLinkA(const char *linkname, const char *target,
215 int targetIsDir)
189{
190 static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
216{
217 static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
218 DWORD attrs;
191 static int set;
219 static int set;
220 int ret, tmpflags, llen, tlen;
221 int flags = 0;
222 char *src, *tgt, *p;
192 if (!set) {
193 set = 1;
194 f = GetFunctionKernel32("CreateSymbolicLinkA");
195 }
223 if (!set) {
224 set = 1;
225 f = GetFunctionKernel32("CreateSymbolicLinkA");
226 }
196 return f == NULL ? 0 : (*f)(linkname, target, flags);
227 if (f == NULL)
228 return (0);
229
230 tlen = strlen(target);
231 llen = strlen(linkname);
232
233 if (tlen == 0 || llen == 0)
234 return (0);
235
236 tgt = malloc((tlen + 1) * sizeof(char));
237 if (tgt == NULL)
238 return (0);
239 src = malloc((llen + 1) * sizeof(char));
240 if (src == NULL) {
241 free(tgt);
242 return (0);
243 }
244
245 /*
246 * Translate slashes to backslashes
247 */
248 p = src;
249 while(*linkname != '\0') {
250 if (*linkname == '/')
251 *p = '\\';
252 else
253 *p = *linkname;
254 linkname++;
255 p++;
256 }
257 *p = '\0';
258
259 p = tgt;
260 while(*target != '\0') {
261 if (*target == '/')
262 *p = '\\';
263 else
264 *p = *target;
265 target++;
266 p++;
267 }
268 *p = '\0';
269
270 /*
271 * Each test has to specify if a file or a directory symlink
272 * should be created.
273 */
274 if (targetIsDir) {
275#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY)
276 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
277#else
278 flags |= 0x1;
279#endif
280 }
281
282#if defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
283 tmpflags = flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
284#else
285 tmpflags = flags | 0x2;
286#endif
287 /*
288 * Windows won't overwrite existing links
289 */
290 attrs = GetFileAttributesA(linkname);
291 if (attrs != INVALID_FILE_ATTRIBUTES) {
292 if (attrs & FILE_ATTRIBUTE_DIRECTORY)
293 RemoveDirectoryA(linkname);
294 else
295 DeleteFileA(linkname);
296 }
297
298 ret = (*f)(src, tgt, tmpflags);
299 /*
300 * Prior to Windows 10 the SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
301 * is not undestood
302 */
303 if (!ret)
304 ret = (*f)(src, tgt, flags);
305
306 free(src);
307 free(tgt);
308 return (ret);
197}
198
199static int
200my_CreateHardLinkA(const char *linkname, const char *target)
201{
202 static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
203 static int set;
204 if (!set) {

--- 1389 unchanged lines hidden (view full) ---

1594 logprintf(" Found: 0%3o\n", st.st_mode & 07777);
1595 failure_finish(NULL);
1596 return (0);
1597 }
1598#endif
1599 return (1);
1600}
1601
309}
310
311static int
312my_CreateHardLinkA(const char *linkname, const char *target)
313{
314 static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
315 static int set;
316 if (!set) {

--- 1389 unchanged lines hidden (view full) ---

1706 logprintf(" Found: 0%3o\n", st.st_mode & 07777);
1707 failure_finish(NULL);
1708 return (0);
1709 }
1710#endif
1711 return (1);
1712}
1713
1602/* Check whether 'pathname' is a symbolic link. If 'contents' is
1603 * non-NULL, verify that the symlink has those contents. */
1714/*
1715 * Check whether 'pathname' is a symbolic link. If 'contents' is
1716 * non-NULL, verify that the symlink has those contents.
1717 *
1718 * On platforms with directory symlinks, set isdir to 0 to test for a file
1719 * symlink and to 1 to test for a directory symlink. On other platforms
1720 * the variable is ignored.
1721 */
1604static int
1605is_symlink(const char *file, int line,
1722static int
1723is_symlink(const char *file, int line,
1606 const char *pathname, const char *contents)
1724 const char *pathname, const char *contents, int isdir)
1607{
1608#if defined(_WIN32) && !defined(__CYGWIN__)
1725{
1726#if defined(_WIN32) && !defined(__CYGWIN__)
1609 (void)pathname; /* UNUSED */
1610 (void)contents; /* UNUSED */
1611 assertion_count(file, line);
1612 /* Windows sort-of has real symlinks, but they're only usable
1613 * by privileged users and are crippled even then, so there's
1614 * really not much point in bothering with this. */
1615 return (0);
1727 HANDLE h;
1728 DWORD inbytes;
1729 REPARSE_DATA_BUFFER *buf;
1730 BY_HANDLE_FILE_INFORMATION st;
1731 size_t len, len2;
1732 wchar_t *linknamew, *contentsw;
1733 const char *p;
1734 char *s, *pn;
1735 int ret = 0;
1736 BYTE *indata;
1737 const DWORD flag = FILE_FLAG_BACKUP_SEMANTICS |
1738 FILE_FLAG_OPEN_REPARSE_POINT;
1739
1740 /* Replace slashes with backslashes in pathname */
1741 pn = malloc((strlen(pathname) + 1) * sizeof(char));
1742 p = pathname;
1743 s = pn;
1744 while(*p != '\0') {
1745 if(*p == '/')
1746 *s = '\\';
1747 else
1748 *s = *p;
1749 p++;
1750 s++;
1751 }
1752 *s = '\0';
1753
1754 h = CreateFileA(pn, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
1755 flag, NULL);
1756 free(pn);
1757 if (h == INVALID_HANDLE_VALUE) {
1758 failure_start(file, line, "Can't access %s\n", pathname);
1759 failure_finish(NULL);
1760 return (0);
1761 }
1762 ret = GetFileInformationByHandle(h, &st);
1763 if (ret == 0) {
1764 failure_start(file, line,
1765 "Can't stat: %s", pathname);
1766 failure_finish(NULL);
1767 } else if ((st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
1768 failure_start(file, line,
1769 "Not a symlink: %s", pathname);
1770 failure_finish(NULL);
1771 ret = 0;
1772 }
1773 if (isdir && ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
1774 failure_start(file, line,
1775 "Not a directory symlink: %s", pathname);
1776 failure_finish(NULL);
1777 ret = 0;
1778 }
1779 if (!isdir &&
1780 ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
1781 failure_start(file, line,
1782 "Not a file symlink: %s", pathname);
1783 failure_finish(NULL);
1784 ret = 0;
1785 }
1786 if (ret == 0) {
1787 CloseHandle(h);
1788 return (0);
1789 }
1790
1791 indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1792 ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata,
1793 1024, &inbytes, NULL);
1794 CloseHandle(h);
1795 if (ret == 0) {
1796 free(indata);
1797 failure_start(file, line,
1798 "Could not retrieve symlink target: %s", pathname);
1799 failure_finish(NULL);
1800 return (0);
1801 }
1802
1803 buf = (REPARSE_DATA_BUFFER *) indata;
1804 if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
1805 free(indata);
1806 /* File is not a symbolic link */
1807 failure_start(file, line,
1808 "Not a symlink: %s", pathname);
1809 failure_finish(NULL);
1810 return (0);
1811 }
1812
1813 if (contents == NULL) {
1814 free(indata);
1815 return (1);
1816 }
1817
1818 len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength;
1819
1820 linknamew = malloc(len + sizeof(wchar_t));
1821 if (linknamew == NULL) {
1822 free(indata);
1823 return (0);
1824 }
1825
1826 memcpy(linknamew, &((BYTE *)buf->SymbolicLinkReparseBuffer.PathBuffer)
1827 [buf->SymbolicLinkReparseBuffer.SubstituteNameOffset], len);
1828 free(indata);
1829
1830 linknamew[len / sizeof(wchar_t)] = L'\0';
1831
1832 contentsw = malloc(len + sizeof(wchar_t));
1833 if (contentsw == NULL) {
1834 free(linknamew);
1835 return (0);
1836 }
1837
1838 len2 = mbsrtowcs(contentsw, &contents, (len + sizeof(wchar_t)
1839 / sizeof(wchar_t)), NULL);
1840
1841 if (len2 > 0 && wcscmp(linknamew, contentsw) != 0)
1842 ret = 1;
1843
1844 free(linknamew);
1845 free(contentsw);
1846 return (ret);
1616#else
1617 char buff[300];
1618 struct stat st;
1619 ssize_t linklen;
1620 int r;
1621
1847#else
1848 char buff[300];
1849 struct stat st;
1850 ssize_t linklen;
1851 int r;
1852
1853 (void)isdir; /* UNUSED */
1622 assertion_count(file, line);
1623 r = lstat(pathname, &st);
1624 if (r != 0) {
1625 failure_start(file, line,
1626 "Symlink should exist: %s", pathname);
1627 failure_finish(NULL);
1628 return (0);
1629 }

--- 12 unchanged lines hidden (view full) ---

1642 return (0);
1643 return (1);
1644#endif
1645}
1646
1647/* Assert that path is a symlink that (optionally) contains contents. */
1648int
1649assertion_is_symlink(const char *file, int line,
1854 assertion_count(file, line);
1855 r = lstat(pathname, &st);
1856 if (r != 0) {
1857 failure_start(file, line,
1858 "Symlink should exist: %s", pathname);
1859 failure_finish(NULL);
1860 return (0);
1861 }

--- 12 unchanged lines hidden (view full) ---

1874 return (0);
1875 return (1);
1876#endif
1877}
1878
1879/* Assert that path is a symlink that (optionally) contains contents. */
1880int
1881assertion_is_symlink(const char *file, int line,
1650 const char *path, const char *contents)
1882 const char *path, const char *contents, int isdir)
1651{
1883{
1652 if (is_symlink(file, line, path, contents))
1884 if (is_symlink(file, line, path, contents, isdir))
1653 return (1);
1654 if (contents)
1655 failure_start(file, line, "File %s is not a symlink to %s",
1656 path, contents);
1657 else
1658 failure_start(file, line, "File %s is not a symlink", path);
1659 failure_finish(NULL);
1660 return (0);

--- 111 unchanged lines hidden (view full) ---

1772 return (1);
1773 failure_start(file, line, "Could not create hardlink");
1774 logprintf(" New link: %s\n", newpath);
1775 logprintf(" Old name: %s\n", linkto);
1776 failure_finish(NULL);
1777 return(0);
1778}
1779
1885 return (1);
1886 if (contents)
1887 failure_start(file, line, "File %s is not a symlink to %s",
1888 path, contents);
1889 else
1890 failure_start(file, line, "File %s is not a symlink", path);
1891 failure_finish(NULL);
1892 return (0);

--- 111 unchanged lines hidden (view full) ---

2004 return (1);
2005 failure_start(file, line, "Could not create hardlink");
2006 logprintf(" New link: %s\n", newpath);
2007 logprintf(" Old name: %s\n", linkto);
2008 failure_finish(NULL);
2009 return(0);
2010}
2011
1780/* Create a symlink and report any failures. */
2012/*
2013 * Create a symlink and report any failures.
2014 *
2015 * Windows symlinks need to know if the target is a directory.
2016 */
1781int
1782assertion_make_symlink(const char *file, int line,
2017int
2018assertion_make_symlink(const char *file, int line,
1783 const char *newpath, const char *linkto)
2019 const char *newpath, const char *linkto, int targetIsDir)
1784{
1785#if defined(_WIN32) && !defined(__CYGWIN__)
2020{
2021#if defined(_WIN32) && !defined(__CYGWIN__)
1786 int targetIsDir = 0; /* TODO: Fix this */
1787 assertion_count(file, line);
1788 if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
1789 return (1);
1790#elif HAVE_SYMLINK
2022 assertion_count(file, line);
2023 if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
2024 return (1);
2025#elif HAVE_SYMLINK
2026 (void)targetIsDir; /* UNUSED */
1791 assertion_count(file, line);
1792 if (0 == symlink(linkto, newpath))
1793 return (1);
2027 assertion_count(file, line);
2028 if (0 == symlink(linkto, newpath))
2029 return (1);
2030#else
2031 (void)targetIsDir; /* UNUSED */
1794#endif
1795 failure_start(file, line, "Could not create symlink");
1796 logprintf(" New link: %s\n", newpath);
1797 logprintf(" Old name: %s\n", linkto);
1798 failure_finish(NULL);
1799 return(0);
1800}
1801

--- 410 unchanged lines hidden (view full) ---

2212 return (value);
2213
2214 ++tested;
2215 assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a");
2216 /* Note: Cygwin has its own symlink() emulation that does not
2217 * use the Win32 CreateSymbolicLink() function. */
2218#if defined(_WIN32) && !defined(__CYGWIN__)
2219 value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
2032#endif
2033 failure_start(file, line, "Could not create symlink");
2034 logprintf(" New link: %s\n", newpath);
2035 logprintf(" Old name: %s\n", linkto);
2036 failure_finish(NULL);
2037 return(0);
2038}
2039

--- 410 unchanged lines hidden (view full) ---

2450 return (value);
2451
2452 ++tested;
2453 assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a");
2454 /* Note: Cygwin has its own symlink() emulation that does not
2455 * use the Win32 CreateSymbolicLink() function. */
2456#if defined(_WIN32) && !defined(__CYGWIN__)
2457 value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
2220 && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
2458 && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0",
2459 0);
2221#elif HAVE_SYMLINK
2222 value = (0 == symlink("canSymlink.0", "canSymlink.1"))
2460#elif HAVE_SYMLINK
2461 value = (0 == symlink("canSymlink.0", "canSymlink.1"))
2223 && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
2462 && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0",
2463 0);
2224#endif
2225 return (value);
2226}
2227
2228/* Platform-dependent options for hiding the output of a subcommand. */
2229#if defined(_WIN32) && !defined(__CYGWIN__)
2230static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
2231#else

--- 1632 unchanged lines hidden ---
2464#endif
2465 return (value);
2466}
2467
2468/* Platform-dependent options for hiding the output of a subcommand. */
2469#if defined(_WIN32) && !defined(__CYGWIN__)
2470static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
2471#else

--- 1632 unchanged lines hidden ---