Skip to content

Commit 9bd4a49

Browse files
authored
Merge pull request #3077 from compnerd/readlink
2 parents fda7e71 + 81fcbe5 commit 9bd4a49

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

CoreFoundation/PlugIn.subproj/CFBundle_Resources.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <fcntl.h>
4545
#include <sys/stat.h>
4646
#include <errno.h>
47+
#include <winioctl.h>
4748

4849
#define close _close
4950
#define write _write
@@ -191,6 +192,57 @@ CF_INLINE Boolean _CFBundleURLHasSubDir(CFURLRef url, CFStringRef subDirName) {
191192
return result;
192193
}
193194

195+
#if TARGET_OS_WIN32
196+
typedef signed long long ssize_t;
197+
static ssize_t readlink(const char * restrict pathname,
198+
char * restrict buffer, size_t bufsiz) {
199+
ssize_t result = -1;
200+
201+
WIN32_FILE_ATTRIBUTE_DATA fsa;
202+
HANDLE hFile = INVALID_HANDLE_VALUE;
203+
REPARSE_DATA_BUFFER *pBuffer;
204+
CHAR bBuffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
205+
DWORD dwCount;
206+
size_t length;
207+
208+
if (!GetFileAttributesExA(pathname, GetFileExInfoStandard, &fsa))
209+
goto out;
210+
211+
if (~fsa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
212+
result = strncpy(buffer, pathname, bufsiz);
213+
goto out;
214+
}
215+
216+
hFile = CreateFileA(pathname, GENERIC_READ,
217+
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
218+
NULL, OPEN_EXISTING,
219+
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
220+
NULL);
221+
if (hFile == INVALID_HANDLE_VALUE)
222+
goto out;
223+
224+
if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, bBuffer,
225+
sizeof(bBuffer), &dwCount, NULL))
226+
goto out;
227+
228+
if (dwCount >= sizeof(bBuffer))
229+
goto out;
230+
231+
pBuffer = (REPARSE_DATA_BUFFER *)bBuffer;
232+
switch (pBuffer->ReparseTag) {
233+
case IO_REPARSE_TAG_SYMLINK:
234+
result = strncpy(buffer, pBuffer->GenericReparseBuffer.DataBuffer, bufsiz);
235+
buffer[min(pBuffer->ReparseDataLength, result)] = '\0';
236+
default:
237+
break;
238+
}
239+
240+
out:
241+
CloseHandle(hFile);
242+
return result;
243+
}
244+
#endif
245+
194246
CF_PRIVATE _CFBundleVersion _CFBundleGetBundleVersionForURL(CFURLRef url) {
195247
// check for existence of "Resources" or "Contents" or "Support Files"
196248
// but check for the most likely one first
@@ -345,8 +397,13 @@ CF_PRIVATE _CFBundleVersion _CFBundleGetBundleVersionForURL(CFURLRef url) {
345397

346398
// 2. pointed-to must not traverse outside bundle
347399
// We check this by making sure that the path of the wrapper bundle is found at the start of the resolved symlink of the wrapped bundle. Also check for links to the same directory.
400+
#if TARGET_OS_WIN32
401+
int resolvedWrappedBundleFd = _open(linkPathCString, O_RDONLY);
402+
int resolvedBundlePathFd = _open(bundlePathCString, O_RDONLY);
403+
#else
348404
int resolvedWrappedBundleFd = open(linkPathCString, O_RDONLY);
349405
int resolvedBundlePathFd = open(bundlePathCString, O_RDONLY);
406+
#endif
350407

351408
if (resolvedWrappedBundleFd > 0 && resolvedBundlePathFd > 0) {
352409
char resolvedWrappedBundlePath[PATH_MAX];

0 commit comments

Comments
 (0)