@@ -15,7 +15,7 @@ import Control.Monad (when)
1515import System.Directory (doesFileExist , removeFile , renameFile )
1616import System.FilePath (takeDirectory , takeFileName )
1717import System.IO (Handle , hClose , openTempFileWithDefaultPermissions )
18- import System.Posix.Files (fileMode , getFileStatus , setFileMode )
18+ import System.Posix.Files (fileGroup , fileMode , fileOwner , getFileStatus , setFileMode , setOwnerAndGroup )
1919
2020-- | Like @withFile@ but replaces the contents atomically.
2121--
@@ -50,7 +50,14 @@ withOutputFile path act = transact begin commit rollback $ \(tpath, th) -> do
5050 copyAttributes (tpath, _th) = do
5151 exists <- doesFileExist path
5252 when exists $ do
53- getFileStatus path >>= setFileMode tpath . fileMode
53+ status <- getFileStatus path
54+ setFileMode tpath (fileMode status)
55+ -- Set the temporary files owner to the same as the original file.
56+ -- This only succeeds if either:
57+ -- - The owner matches already, no change necessary
58+ -- - The current user has the CAP_CHOWN permission
59+ -- See also https://stackoverflow.com/a/49079630 for more context
60+ setOwnerAndGroup tpath (fileOwner status) (fileGroup status)
5461
5562 commit :: (FilePath , Handle ) -> IO ()
5663 commit (tpath, th) = hClose th *> renameFile tpath path
0 commit comments