git-annex/Utility/FileIO.hs
Joey Hess 867110e9ee
add readFileString, writeFileString, appendFileString
Exported by Common, so they will be available everywhere.
These are the same as readFile, writeFile, appendFile.
But have two benefits:

* They take OsPath, so using them avoids converting back and forth
  unncessarily.
* They use the close-on-exec flag so can't leak FDs to child processes.
  Unlike the standard Haskell versions which unfortunately have that
  wart currently. (I do hope the standard versions get fixed
  eventually.)

Sponsored-by: the NIH-funded NICEMAN (ReproNim TR&D3) project
2025-09-05 14:54:36 -04:00

190 lines
5.4 KiB
Haskell

{- This is a subset of the functions provided by file-io, supplimented with
- readFileString, writeFileString, and appendFileString.
-
- When building with file-io, all exported functions set the close-on-exec
- flag.
-
- When not building with file-io, this provides equvilant
- RawFilePath versions. Note that those versions do not currently
- set the close-on-exec flag.
-
- Since Prelude exports many of these as well, this needs to be imported
- qualified.
-
- Copyright 2025 Joey Hess <id@joeyh.name>
-
- License: BSD-2-clause
-}
{-# OPTIONS_GHC -fno-warn-tabs #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Utility.FileIO
(
withFile,
openFile,
withBinaryFile,
openBinaryFile,
readFile,
readFile',
writeFile,
writeFile',
appendFile,
appendFile',
openTempFile,
readFileString,
writeFileString,
appendFileString,
) where
#ifdef WITH_OSPATH
#ifndef mingw32_HOST_OS
import Utility.FileIO.CloseOnExec
import Utility.FileIO.String
#else
-- On Windows, System.File.OsPath does not handle UNC-style conversion itself,
-- so that has to be done when calling it. See
-- https://github.com/haskell/file-io/issues/39
import Utility.Path.Windows
import Utility.OsPath
import System.IO (IO, Handle, IOMode)
import Prelude (String, return)
import qualified Utility.FileIO.CloseOnExec as O
import qualified Utility.FileIO.String as O
import qualified Data.ByteString as B
import Control.Applicative
withFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
withFile f m a = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.withFile f' m a
openFile :: OsPath -> IOMode -> IO Handle
openFile f m = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.openFile f' m
withBinaryFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
withBinaryFile f m a = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.withBinaryFile f' m a
openBinaryFile :: OsPath -> IOMode -> IO Handle
openBinaryFile f m = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.openBinaryFile f' m
readFile :: OsPath -> IO L.ByteString
readFile f = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.readFile f'
readFile' :: OsPath -> IO B.ByteString
readFile' f = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.readFile' f'
writeFile :: OsPath -> L.ByteString -> IO ()
writeFile f b = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.writeFile f' b
writeFile' :: OsPath -> B.ByteString -> IO ()
writeFile' f b = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.writeFile' f' b
appendFile :: OsPath -> L.ByteString -> IO ()
appendFile f b = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.appendFile f' b
appendFile' :: OsPath -> B.ByteString -> IO ()
appendFile' f b = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.appendFile' f' b
openTempFile :: OsPath -> OsPath -> IO (OsPath, Handle)
openTempFile p s = do
p' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath p)
(t, h) <- O.openTempFile p' s
-- Avoid returning mangled path from convertToWindowsNativeNamespace
let t' = p </> takeFileName t
return (t', h)
readFileString :: OsPath -> IO String
readFileString p = do
p' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath p)
I.readFileString p'
writeFileString :: OsPath -> String -> IO ()
writeFileString f txt = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
I.writeFileString f' txt
appendFileString :: OsPath -> String -> IO ()
appendFileString f txt = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
I.appendFileString f' txt
#endif
#else
-- RawFilePath versions
import Utility.OsPath
import Utility.FileSystemEncoding
import System.IO (IO, Handle, IOMode)
import Prelude (String, (.), return)
import qualified Prelude as P
import qualified System.IO
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
withFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
withFile = System.IO.withFile . fromRawFilePath
openFile :: OsPath -> IOMode -> IO Handle
openFile = System.IO.openFile . fromRawFilePath
withBinaryFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
withBinaryFile = System.IO.withBinaryFile . fromRawFilePath
openBinaryFile :: OsPath -> IOMode -> IO Handle
openBinaryFile = System.IO.openBinaryFile . fromRawFilePath
readFile :: OsPath -> IO L.ByteString
readFile = L.readFile . fromRawFilePath
readFile' :: OsPath -> IO B.ByteString
readFile' = B.readFile . fromRawFilePath
writeFile :: OsPath -> L.ByteString -> IO ()
writeFile = L.writeFile . fromRawFilePath
writeFile' :: OsPath -> B.ByteString -> IO ()
writeFile' = B.writeFile . fromRawFilePath
appendFile :: OsPath -> L.ByteString -> IO ()
appendFile = L.appendFile . fromRawFilePath
appendFile' :: OsPath -> B.ByteString -> IO ()
appendFile' = B.appendFile . fromRawFilePath
openTempFile :: OsPath -> OsPath -> IO (OsPath, Handle)
openTempFile p s = do
(t, h) <- System.IO.openTempFile
(fromRawFilePath p)
(fromRawFilePath s)
return (toRawFilePath t, h)
readFileString :: OsPath -> IO String
readFileString = P.readFile . fromRawFilePath
writeFileString :: OsPath -> String -> IO ()
writeFileString = P.writeFile . fromRawFilePath
appendFileString :: OsPath -> String -> IO ()
appendFileString = P.appendFile . fromRawFilePath
#endif