Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions main/System/IO/Atomic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Control.Monad (when)
import System.Directory (doesFileExist, removeFile, renameFile)
import System.FilePath (takeDirectory, takeFileName)
import System.IO (Handle, hClose, openTempFileWithDefaultPermissions)
import System.Posix.Files (fileMode, getFileStatus, setFileMode)
import System.Posix.Files (fileGroup, fileMode, fileOwner, getFileStatus, setFileMode, setOwnerAndGroup)

-- | Like @withFile@ but replaces the contents atomically.
--
Expand Down Expand Up @@ -50,7 +50,14 @@ withOutputFile path act = transact begin commit rollback $ \(tpath, th) -> do
copyAttributes (tpath, _th) = do
exists <- doesFileExist path
when exists $ do
getFileStatus path >>= setFileMode tpath . fileMode
status <- getFileStatus path
setFileMode tpath (fileMode status)
-- Set the temporary files owner to the same as the original file.
-- This only succeeds if either:
-- - The owner matches already, no change necessary
-- - The current user has the CAP_CHOWN permission
-- See also https://stackoverflow.com/a/49079630 for more context
setOwnerAndGroup tpath (fileOwner status) (fileGroup status)

commit :: (FilePath, Handle) -> IO ()
commit (tpath, th) = hClose th *> renameFile tpath path
Expand Down