Skip to content

Commit 7d0d507

Browse files
committed
Use SHCreateDirectory to create a directory with intermediate directories on Windows
Instead of recursively creating all the parent directories, which is racy if the directory is created between the check if the parent directory exists and the actual directory creation, use `SHCreateDirectoryExW`, which also creates intermediate directories.
1 parent 33a49e5 commit 7d0d507

File tree

1 file changed

+9
-17
lines changed

1 file changed

+9
-17
lines changed

Sources/FoundationEssentials/FileManager/FileManager+Directories.swift

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -258,27 +258,19 @@ extension _FileManagerImpl {
258258
) throws {
259259
#if os(Windows)
260260
try path.withNTPathRepresentation { pwszPath in
261-
if createIntermediates {
262-
var isDirectory: Bool = false
263-
if fileManager.fileExists(atPath: path, isDirectory: &isDirectory) {
264-
guard isDirectory else {
265-
throw CocoaError.errorWithFilePath(path, win32: ERROR_FILE_EXISTS, reading: false)
266-
}
267-
return
268-
}
269-
270-
let parent = path.deletingLastPathComponent()
271-
if !parent.isEmpty {
272-
try createDirectory(atPath: parent, withIntermediateDirectories: true, attributes: attributes)
273-
}
274-
}
275-
276261
var saAttributes: SECURITY_ATTRIBUTES =
277262
SECURITY_ATTRIBUTES(nLength: DWORD(MemoryLayout<SECURITY_ATTRIBUTES>.size),
278263
lpSecurityDescriptor: nil,
279264
bInheritHandle: false)
280-
guard CreateDirectoryW(pwszPath, &saAttributes) else {
281-
throw CocoaError.errorWithFilePath(path, win32: GetLastError(), reading: false)
265+
if createIntermediates {
266+
// `SHCreateDirectoryExW` creates intermediate directories while `CreateDirectoryW` does not
267+
guard SHCreateDirectoryExW(nil, pwszPath, &saAttributes) == ERROR_SUCCESS else {
268+
throw CocoaError.errorWithFilePath(path, win32: GetLastError(), reading: false)
269+
}
270+
} else {
271+
guard CreateDirectoryW(pwszPath, &saAttributes) else {
272+
throw CocoaError.errorWithFilePath(path, win32: GetLastError(), reading: false)
273+
}
282274
}
283275
if let attributes {
284276
try? fileManager.setAttributes(attributes, ofItemAtPath: path)

0 commit comments

Comments
 (0)