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 --- |