Skip to content

Commit

Permalink
Merge pull request apple#3005 from millenomi/pr/sr-14823
Browse files Browse the repository at this point in the history
  • Loading branch information
millenomi committed Jul 13, 2021
2 parents 08979ae + cbfe077 commit 62c50ad
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 23 deletions.
44 changes: 25 additions & 19 deletions Sources/Foundation/NSPathUtilities.swift
Expand Up @@ -735,7 +735,6 @@ public func NSFullUserName() -> String {
}

internal func _NSCreateTemporaryFile(_ filePath: String) throws -> (Int32, String) {
let template = filePath + ".tmp.XXXXXX"
#if os(Windows)
let maxLength: Int = Int(MAX_PATH + 1)
var buf: [UInt16] = Array<UInt16>(repeating: 0, count: maxLength)
Expand All @@ -760,26 +759,32 @@ internal func _NSCreateTemporaryFile(_ filePath: String) throws -> (Int32, Strin
// Don't close h, fd is transferred ownership
let fd = _open_osfhandle(intptr_t(bitPattern: h), 0)
#else
var filename = template.utf8CString
var template = URL(fileURLWithPath: filePath)

let filename = template.lastPathComponent
let hashed = String(format: "%llx", Int64(filename.hashValue))
template.deleteLastPathComponent()
template.appendPathComponent("SCF.\(hashed).tmp.XXXXXX")

let result = filename.withUnsafeMutableBufferPointer { (ptr: inout UnsafeMutableBufferPointer<CChar>) -> (Int32, String)? in
// filename is updated with the temp file name on success.
let fd = mkstemp(ptr.baseAddress!)
if fd == -1 {
return nil
} else {
guard let fname = String(utf8String: ptr.baseAddress!) else {
// Couldnt convert buffer back to filename.
close(fd)
errno = ENOENT
return nil
}
return (fd, fname)
}

let (fd, errorCode, pathResult) = template.withUnsafeFileSystemRepresentation { ptr -> (Int32, Int32, String) in
let length = strlen(ptr!)

// buffer is updated with the temp file name on success.
let buffer = UnsafeMutableBufferPointer<CChar>.allocate(capacity: length + 1 /* the null character */)
UnsafeRawBufferPointer(start: ptr!, count: length + 1 /* the null character */)
.copyBytes(to: UnsafeMutableRawBufferPointer(buffer))
defer { buffer.deallocate() }

let fd = mkstemp(buffer.baseAddress!)
let errorCode = errno
return (fd,
errorCode,
FileManager.default.string(withFileSystemRepresentation: buffer.baseAddress!, length: strlen(buffer.baseAddress!)))
}

guard let (fd, pathResult) = result else {
throw _NSErrorWithErrno(errno, reading: false, path: template)
if fd == -1 {
throw _NSErrorWithErrno(errorCode, reading: false, path: pathResult)
}

// Set the file mode to match macOS
Expand All @@ -802,8 +807,9 @@ internal func _NSCleanupTemporaryFile(_ auxFilePath: String, _ filePath: String)
}
#else
if rename($0, $1) != 0 {
let errorCode = errno
try? FileManager.default.removeItem(atPath: auxFilePath)
throw _NSErrorWithErrno(errno, reading: false, path: filePath)
throw _NSErrorWithErrno(errorCode, reading: false, path: filePath)
}
#endif
})
Expand Down
12 changes: 8 additions & 4 deletions Tests/Foundation/Tests/TestFileManager.swift
Expand Up @@ -489,11 +489,15 @@ class TestFileManager : XCTestCase {
try fm.createDirectory(atPath: basePath, withIntermediateDirectories: false, attributes: nil)
try fm.createDirectory(atPath: basePath2, withIntermediateDirectories: false, attributes: nil)

let _ = fm.createFile(atPath: itemPath, contents: Data(count: 123), attributes: nil)
let _ = fm.createFile(atPath: itemPath2, contents: Data(count: 456), attributes: nil)

if !fm.createFile(atPath: itemPath, contents: Data(count: 123), attributes: nil) {
throw CocoaError(.fileWriteUnknown)
}
if !fm.createFile(atPath: itemPath2, contents: Data(count: 456), attributes: nil) {
throw CocoaError(.fileWriteUnknown)
}
} catch {
XCTFail()
XCTFail("Failed with error while creating temporary files: \(error)")
return
}

var item1FileAttributes: [FileAttributeKey: Any]!
Expand Down

0 comments on commit 62c50ad

Please sign in to comment.