Skip to content

Commit f80b6f2

Browse files
authored
Merge pull request #2199 from gmittert/TheMessWeCreated
2 parents cef3bbd + cd7dfdb commit f80b6f2

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

Foundation/NSData.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,10 +453,13 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
453453
let permissions = (try? fm._permissionsOfItem(atPath: path)) ?? 0o600
454454

455455
if writeOptionsMask.contains(.atomic) {
456-
let (newFD, auxFilePath) = try _NSCreateTemporaryFile(path)
456+
var (newFD, auxFilePath) = try _NSCreateTemporaryFile(path)
457457
let fh = FileHandle(fileDescriptor: newFD, closeOnDealloc: true)
458458
do {
459459
try doWrite(fh)
460+
// Moving a file on Windows (via _NSCleanupTemporaryFile)
461+
// requires that there be no open handles to the file
462+
fh.closeFile()
460463
try _NSCleanupTemporaryFile(auxFilePath, path)
461464
try fm.setAttributes([.posixPermissions: NSNumber(value: permissions)], ofItemAtPath: path)
462465
} catch {

Foundation/NSPathUtilities.swift

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,11 +659,21 @@ internal func _NSCreateTemporaryFile(_ filePath: String) throws -> (Int32, Strin
659659
guard "SCF".withCString(encodedAs: UTF16.self, {
660660
return GetTempFileNameW(buf, $0, 0, &buf) != 0
661661
}) else {
662-
throw _NSErrorWithErrno(Int32(GetLastError()), reading: false,
663-
path: filePath)
662+
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
664663
}
665664
let pathResult = FileManager.default.string(withFileSystemRepresentation: String(decoding: buf, as: UTF16.self), length: wcslen(buf))
666-
let fd = open(pathResult, _O_CREAT)
665+
guard let h = CreateFileW(buf,
666+
GENERIC_READ | DWORD(GENERIC_WRITE),
667+
DWORD(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
668+
nil,
669+
DWORD(OPEN_EXISTING),
670+
DWORD(FILE_ATTRIBUTE_NORMAL),
671+
nil),
672+
h != INVALID_HANDLE_VALUE else {
673+
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
674+
}
675+
// Don't close h, fd is transferred ownership
676+
let fd = _open_osfhandle(intptr_t(bitPattern: h), 0)
667677
#else
668678
let maxLength = Int(PATH_MAX) + 1
669679
var buf = [Int8](repeating: 0, count: maxLength)
@@ -678,10 +688,22 @@ internal func _NSCreateTemporaryFile(_ filePath: String) throws -> (Int32, Strin
678688
}
679689

680690
internal func _NSCleanupTemporaryFile(_ auxFilePath: String, _ filePath: String) throws {
691+
#if os(Windows)
692+
try auxFilePath.withCString(encodedAs: UTF16.self) { fromPath in
693+
try filePath.withCString(encodedAs: UTF16.self) { toPath in
694+
let res = CopyFileW(fromPath, toPath, /*bFailIfExists=*/false)
695+
try? FileManager.default.removeItem(atPath: auxFilePath)
696+
if !res {
697+
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
698+
}
699+
}
700+
}
701+
#else
681702
try FileManager.default._fileSystemRepresentation(withPath: auxFilePath, andPath: filePath, {
682703
if rename($0, $1) != 0 {
683704
try? FileManager.default.removeItem(atPath: auxFilePath)
684705
throw _NSErrorWithErrno(errno, reading: false, path: filePath)
685706
}
686707
})
708+
#endif
687709
}

0 commit comments

Comments
 (0)