From 830ce1e18bd0e056cfbe6beb17e6259bec513136 Mon Sep 17 00:00:00 2001 From: Dave Inglis Date: Tue, 16 Sep 2025 17:03:01 -0400 Subject: [PATCH] Use FileManager API to get current working directory - FileManager handles long file name prefixes on Windows correctly. This keeps any UNC long file prefix (\\?\) out of URL that were relative and then resolved to absolute urls. --- Sources/CoreFoundation/CFPlatform.c | 24 ------------------ .../include/ForFoundationOnly.h | 1 - .../internalInclude/CoreFoundation_Prefix.h | 1 - Sources/Foundation/FileManager.swift | 25 +++++++++++++++++++ 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/Sources/CoreFoundation/CFPlatform.c b/Sources/CoreFoundation/CFPlatform.c index 8112cec632..2cb329a609 100644 --- a/Sources/CoreFoundation/CFPlatform.c +++ b/Sources/CoreFoundation/CFPlatform.c @@ -42,7 +42,6 @@ #define SECURITY_WIN32 #include -#define getcwd _NS_getcwd #define open _NS_open #endif @@ -69,11 +68,6 @@ char **_CFArgv(void) { return *_NSGetArgv(); } int _CFArgc(void) { return *_NSGetArgc(); } #endif - -CF_PRIVATE Boolean _CFGetCurrentDirectory(char *path, int maxlen) { - return getcwd(path, maxlen) != NULL; -} - #if TARGET_OS_WIN32 // Returns the path to the CF DLL, which we can then use to find resources like char sets bool bDllPathCached = false; @@ -1131,24 +1125,6 @@ CF_EXPORT int _NS_unlink(const char *name) { return res; } -// Warning: this doesn't support dstbuf as null even though 'getcwd' does -CF_EXPORT char *_NS_getcwd(char *dstbuf, size_t size) { - if (!dstbuf) { - CFLog(kCFLogLevelWarning, CFSTR("CFPlatform: getcwd called with null buffer")); - return 0; - } - - wchar_t *buf = _wgetcwd(NULL, 0); - if (!buf) { - return NULL; - } - - // Convert result to UTF8 - copyToNarrowFileSystemRepresentation(buf, (CFIndex)size, dstbuf); - free(buf); - return dstbuf; -} - CF_EXPORT char *_NS_getenv(const char *name) { // todo: wide getenv // We have to be careful what happens here, because getenv is called during cf initialization, and things like cfstring may not be working yet diff --git a/Sources/CoreFoundation/include/ForFoundationOnly.h b/Sources/CoreFoundation/include/ForFoundationOnly.h index b524163d4c..2ae44b54c6 100644 --- a/Sources/CoreFoundation/include/ForFoundationOnly.h +++ b/Sources/CoreFoundation/include/ForFoundationOnly.h @@ -527,7 +527,6 @@ CF_EXPORT int _NS_mkdir(const char *name); CF_EXPORT int _NS_rmdir(const char *name); CF_EXPORT int _NS_chmod(const char *name, int mode); CF_EXPORT int _NS_unlink(const char *name); -CF_EXPORT char *_NS_getcwd(char *dstbuf, size_t size); // Warning: this doesn't support dstbuf as null even though 'getcwd' does CF_EXPORT char *_NS_getenv(const char *name); CF_EXPORT int _NS_rename(const char *oldName, const char *newName); CF_EXPORT int _NS_open(const char *name, int oflag, int pmode); diff --git a/Sources/CoreFoundation/internalInclude/CoreFoundation_Prefix.h b/Sources/CoreFoundation/internalInclude/CoreFoundation_Prefix.h index 1cbefad215..40a0d02adb 100644 --- a/Sources/CoreFoundation/internalInclude/CoreFoundation_Prefix.h +++ b/Sources/CoreFoundation/internalInclude/CoreFoundation_Prefix.h @@ -374,7 +374,6 @@ CF_EXPORT int _NS_mkdir(const char *name); CF_EXPORT int _NS_rmdir(const char *name); CF_EXPORT int _NS_chmod(const char *name, int mode); CF_EXPORT int _NS_unlink(const char *name); -CF_EXPORT char *_NS_getcwd(char *dstbuf, size_t size); // Warning: this doesn't support dstbuf as null even though 'getcwd' does CF_EXPORT char *_NS_getenv(const char *name); CF_EXPORT int _NS_rename(const char *oldName, const char *newName); CF_EXPORT int _NS_open(const char *name, int oflag, int pmode); diff --git a/Sources/Foundation/FileManager.swift b/Sources/Foundation/FileManager.swift index f5dd433579..fff9fd906e 100644 --- a/Sources/Foundation/FileManager.swift +++ b/Sources/Foundation/FileManager.swift @@ -681,3 +681,28 @@ extension FileManager { } } } + +// Used in CFURL.c (use FileManager API so that platform specifics like long path prefix strip can be handled in a single place) +@_cdecl("_CFGetCurrentDirectory") +internal func _CFGetCurrentDirectory(_ buffer: UnsafeMutablePointer?, _ size: Int) -> Bool { + guard let buffer = buffer, size > 0 else { + return false // Invalid parameters + } + + let currentPath = FileManager.default.currentDirectoryPath + + // Convert to C string representation + let cString = currentPath.utf8CString + let requiredSize = cString.count // includes null terminator + + if requiredSize > size { + return false // Buffer too small + } + + // Copy the string to the buffer + cString.withUnsafeBufferPointer { sourceBuffer in + buffer.initialize(from: sourceBuffer.baseAddress!, count: requiredSize) + } + + return true // Success +}