Skip to content

Commit 1e900b4

Browse files
natikgadzhiLukasaglbrntt
authored
NIOFileSystem: Try ${TMPDIR} first for temporary directory (#3067)
### Motivation: This PR aligns what temp directory NIOFileSystem will return first: - First try `${TMPDIR}` as it's an expressed user preference - On Darwin, try `_CS_DARWIN_USER_TMP_DIR` next. If it's set, return that. - Finally, fall back on `/tmp` on Darwin and Linux, and `/data/local/tmp` on Android. Closes #2861. ### Modifications: - Reworks `NIOFileSystem.temporaryDirectory`. ### Result: - NIOFileSystem will now try `${TMPDIR}` first for the temporary directory. ### Caveats: - We might want to align how Swift-NIO and FoundationEssentials resolve temp directory, and [FoundationEssentials have a different approach](https://github.com/swiftlang/swift-foundation/blob/9d57f36de757b3d5e3a2f7ffcf27aaec3033509f/Sources/FoundationEssentials/String/String%2BPath.swift#L484-L533). But, I agree with [this comment](#2861 (comment)), it feels like TMPDIR is an expected default. --------- Co-authored-by: Cory Benfield <[email protected]> Co-authored-by: George Barnett <[email protected]>
1 parent 26d3fb9 commit 1e900b4

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

Sources/NIOFileSystem/FileSystem.swift

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -636,31 +636,35 @@ public struct FileSystem: Sendable, FileSystemProtocol {
636636
///
637637
/// #### Implementation details
638638
///
639-
/// On Darwin this function uses `confstr(3)` and gets the value of `_CS_DARWIN_USER_TEMP_DIR`;
640-
/// the users temporary directory. Typically items are removed after three days if they are not
641-
/// accessed.
642-
///
643-
/// On Linux this returns "/tmp".
639+
/// On all platforms, this function first attempts to read the `TMPDIR` environment variable and returns that path, omitting trailing slashes.
640+
/// If that fails:
641+
/// - On Darwin this function uses `confstr(3)` and gets the value of `_CS_DARWIN_USER_TEMP_DIR`;
642+
/// the users temporary directory. Typically items are removed after three days if they are not
643+
/// accessed.
644+
/// - On Android this returns "/data/local/tmp".
645+
/// - On other platforms this returns "/tmp".
644646
///
645647
/// - Returns: The path to a temporary directory.
646648
public var temporaryDirectory: FilePath {
647649
get async throws {
650+
if let tmpdir = getenv("TMPDIR") {
651+
return FilePath(String(cString: tmpdir))
652+
}
653+
648654
#if canImport(Darwin)
649655
return try await self.threadPool.runIfActive {
650-
try Libc.constr(_CS_DARWIN_USER_TEMP_DIR).map { path in
651-
FilePath(path)
652-
}.mapError { errno in
653-
FileSystemError.confstr(
654-
name: "_CS_DARWIN_USER_TEMP_DIR",
655-
errno: errno,
656-
location: .here()
657-
)
658-
}.get()
656+
let result = Libc.constr(_CS_DARWIN_USER_TEMP_DIR)
657+
switch result {
658+
case .success(let path):
659+
return FilePath(path)
660+
case .failure(_):
661+
return FilePath("/tmp")
662+
}
659663
}
660664
#elseif os(Android)
661-
return "/data/local/tmp"
665+
return FilePath("/data/local/tmp")
662666
#else
663-
return "/tmp"
667+
return FilePath("/tmp")
664668
#endif
665669
}
666670
}

Tests/NIOFileSystemIntegrationTests/FileSystemTests.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,14 @@ extension FileSystemTests {
16811681
XCTAssertGreaterThan(info.size, 0)
16821682
}
16831683

1684+
func testTemporaryDirectoryRespectsEnvironment() async throws {
1685+
if let envTmpDir = getenv("TMPDIR") {
1686+
let envTmpDirString = String(cString: envTmpDir)
1687+
let fsTempDirectory = try await fs.temporaryDirectory
1688+
XCTAssertEqual(fsTempDirectory, FilePath(envTmpDirString))
1689+
}
1690+
}
1691+
16841692
func testReadChunksRange() async throws {
16851693
try await self.fs.withFileHandle(forReadingAt: FilePath(#filePath)) { handle in
16861694
let info = try await handle.info()

0 commit comments

Comments
 (0)