Repository: apple/swift-nio
File: Sources/_NIOFileSystem/FileSystem.swift (Swift)

Code before:
    ///
    /// - Returns: The path to the current working directory.
    public var currentWorkingDirectory: FilePath {
        get async throws {
            let result = try await self.threadPool.runIfActive {
                try Libc.getcwd().mapError { errno in
                    FileSystemError.getcwd(errno: errno, location: .here())
                }.get()
            }
            return result
        }
    }

    /// Returns the path of the current user's home directory.
    ///
    /// #### Implementation details
    ///
    /// This function first checks the `HOME` environment variable. If not set:
    /// - On Darwin/Linux/Android, uses `getpwuid_r(3)` to query the password database.
    /// - On Windows, checks the `USERPROFILE` environment variable.
    ///
    /// - Returns: The path to the current user's home directory.
    public var homeDirectory: FilePath {
        get async throws {
            try await self.threadPool.runIfActive {
                try Libc.homeDirectoryForCurrentUser().mapError { errno in
                    FileSystemError.getpwuid_r(errno: errno, location: .here())
                }.get()
            }
        }
    }

    /// Returns a path to a temporary directory.
    ///
    /// #### Implementation details
    ///
    /// On all platforms, this function first attempts to read the `TMPDIR` environment variable and returns that path, omitting trailing slashes.
    /// If that fails:
    /// - On Darwin this function uses `confstr(3)` and gets the value of `_CS_DARWIN_USER_TEMP_DIR`;
    ///   the users temporary directory. Typically items are removed after three days if they are not
    ///   accessed.
    /// - On Android this returns "/data/local/tmp".
    /// - On other platforms this returns "/tmp".
    ///
    /// - Returns: The path to a temporary directory.
    public var temporaryDirectory: FilePath {
        get async throws {
            if let tmpdir = getenv("TMPDIR") {
                return FilePath(String(cString: tmpdir))
            }


Review comment (suggestion):
It might be nice to have the environment-variable-based lookups in a separate function. That would allow us to skip the hop to the thread pool if we can get the answer without needing the passwd database.

Code after:
    ///
    /// - Returns: The path to the current working directory.
    public var currentWorkingDirectory: FilePath {
        get async throws {
            let result = try await self.threadPool.runIfActive {
                try Libc.getcwd().mapError { errno in
                    FileSystemError.getcwd(errno: errno, location: .here())
                }.get()
            }
            return result
        }
    }

    /// Returns the path of the current user's home directory.
    ///
    /// #### Implementation details
    ///
    /// This function first checks the `HOME` environment variable (and `USERPROFILE` on Windows).
    /// If not set, on Darwin/Linux/Android it uses `getpwuid_r(3)` to query the password database.
    ///
    /// Note: `getpwuid_r` can potentially block on I/O (e.g., when using NIS or LDAP),
    /// which is why this property is async when falling back to the password database.
    ///
    /// - Returns: The path to the current user's home directory.
    public var homeDirectory: FilePath {
        get async throws {
            if let path = Libc.homeDirectoryFromEnvironment() {
                return path
            }

            #if canImport(Darwin) || canImport(Glibc) || canImport(Musl) || canImport(Android)
            return try await self.threadPool.runIfActive {
                try Libc.homeDirectoryFromPasswd().mapError { errno in
                    FileSystemError.getpwuid_r(errno: errno, location: .here())
                }.get()
            }
            #else
            throw FileSystemError.getpwuid_r(errno: .noSuchFileOrDirectory, location: .here())
            #endif
        }
    }

    /// Returns a path to a temporary directory.
    ///
    /// #### Implementation details
    ///
    /// On all platforms, this function first attempts to read the `TMPDIR` environment variable and returns that path, omitting trailing slashes.
    /// If that fails:
    /// - On Darwin this function uses `confstr(3)` and gets the value of `_CS_DARWIN_USER_TEMP_DIR`;
    ///   the users temporary directory. Typically items are removed after three days if they are not
    ///   accessed.