{-# LINE 1 "libraries/unix/System/Posix/ByteString/FilePath.hsc" #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeApplications #-}
module System.Posix.ByteString.FilePath (
RawFilePath, withFilePath, peekFilePath, peekFilePathLen,
throwErrnoPathIfMinus1Retry,
throwErrnoPathIfMinus1Retry_,
throwErrnoPathIfNullRetry,
throwErrnoPathIfRetry,
throwErrnoPath,
throwErrnoPathIf,
throwErrnoPathIf_,
throwErrnoPathIfNull,
throwErrnoPathIfMinus1,
throwErrnoPathIfMinus1_,
throwErrnoTwoPathsIfMinus1_
) where
import Foreign hiding ( void )
import Foreign.C hiding (
throwErrnoPath,
throwErrnoPathIf,
throwErrnoPathIf_,
throwErrnoPathIfNull,
throwErrnoPathIfMinus1,
throwErrnoPathIfMinus1_ )
import Control.Monad
import Control.Exception
import Data.ByteString.Internal (c_strlen)
import GHC.Foreign as GHC ( peekCStringLen )
import GHC.IO.Encoding ( getFileSystemEncoding )
import GHC.IO.Exception
import Data.ByteString as B
import Data.ByteString.Char8 as BC
import Prelude hiding (FilePath)
{-# LINE 54 "libraries/unix/System/Posix/ByteString/FilePath.hsc" #-}
type RawFilePath = ByteString
withFilePath :: RawFilePath -> (CString -> IO a) -> IO a
withFilePath :: forall a. RawFilePath -> (CString -> IO a) -> IO a
withFilePath RawFilePath
path = RawFilePath -> (CString -> IO a) -> IO a
forall a. RawFilePath -> (CString -> IO a) -> IO a
useAsCStringSafe RawFilePath
path
peekFilePath :: CString -> IO RawFilePath
peekFilePath :: CString -> IO RawFilePath
peekFilePath = CString -> IO RawFilePath
packCString
peekFilePathLen :: CStringLen -> IO RawFilePath
peekFilePathLen :: CStringLen -> IO RawFilePath
peekFilePathLen = CStringLen -> IO RawFilePath
packCStringLen
throwErrnoPathIfMinus1Retry :: (Eq a, Num a)
=> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfMinus1Retry :: forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfMinus1Retry String
loc RawFilePath
path IO a
f = do
(a -> Bool) -> String -> RawFilePath -> IO a -> IO a
forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfRetry (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== -a
1) String
loc RawFilePath
path IO a
f
throwErrnoPathIfMinus1Retry_ :: (Eq a, Num a)
=> String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1Retry_ :: forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1Retry_ String
loc RawFilePath
path IO a
f =
IO a -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO a -> IO ()) -> IO a -> IO ()
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfRetry (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== -a
1) String
loc RawFilePath
path IO a
f
throwErrnoPathIfNullRetry :: String -> RawFilePath -> IO (Ptr a) -> IO (Ptr a)
throwErrnoPathIfNullRetry :: forall a. String -> RawFilePath -> IO (Ptr a) -> IO (Ptr a)
throwErrnoPathIfNullRetry String
loc RawFilePath
path IO (Ptr a)
f =
(Ptr a -> Bool)
-> String -> RawFilePath -> IO (Ptr a) -> IO (Ptr a)
forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfRetry (Ptr a -> Ptr a -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr a
forall a. Ptr a
nullPtr) String
loc RawFilePath
path IO (Ptr a)
f
throwErrnoPathIfRetry :: (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfRetry :: forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfRetry a -> Bool
pr String
loc RawFilePath
rpath IO a
f =
do
res <- IO a
f
if pr res
then do
err <- getErrno
if err == eINTR
then throwErrnoPathIfRetry pr loc rpath f
else throwErrnoPath loc rpath
else return res
throwErrnoPath :: String -> RawFilePath -> IO a
throwErrnoPath :: forall a. String -> RawFilePath -> IO a
throwErrnoPath String
loc RawFilePath
path =
do
errno <- IO Errno
getErrno
path' <- either (const (BC.unpack path)) id <$> try @IOException (decodeWithBasePosix path)
ioError (errnoToIOError loc errno Nothing (Just path'))
throwErrnoPathIf :: (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIf :: forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIf a -> Bool
cond String
loc RawFilePath
path IO a
f =
do
res <- IO a
f
if cond res then throwErrnoPath loc path else return res
throwErrnoPathIf_ :: (a -> Bool) -> String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIf_ :: forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIf_ a -> Bool
cond String
loc RawFilePath
path IO a
f = IO a -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO a -> IO ()) -> IO a -> IO ()
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIf a -> Bool
cond String
loc RawFilePath
path IO a
f
throwErrnoPathIfNull :: String -> RawFilePath -> IO (Ptr a) -> IO (Ptr a)
throwErrnoPathIfNull :: forall a. String -> RawFilePath -> IO (Ptr a) -> IO (Ptr a)
throwErrnoPathIfNull = (Ptr a -> Bool)
-> String -> RawFilePath -> IO (Ptr a) -> IO (Ptr a)
forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIf (Ptr a -> Ptr a -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr a
forall a. Ptr a
nullPtr)
throwErrnoPathIfMinus1 :: (Eq a, Num a) => String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfMinus1 :: forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO a
throwErrnoPathIfMinus1 = (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO a
throwErrnoPathIf (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== -a
1)
throwErrnoPathIfMinus1_ :: (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1_ :: forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1_ = (a -> Bool) -> String -> RawFilePath -> IO a -> IO ()
forall a. (a -> Bool) -> String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIf_ (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== -a
1)
throwErrnoTwoPathsIfMinus1_ :: (Eq a, Num a) => String -> RawFilePath -> RawFilePath -> IO a -> IO ()
throwErrnoTwoPathsIfMinus1_ :: forall a.
(Eq a, Num a) =>
String -> RawFilePath -> RawFilePath -> IO a -> IO ()
throwErrnoTwoPathsIfMinus1_ String
loc RawFilePath
path1 RawFilePath
path2 IO a
action = do
path1' <- (IOException -> String)
-> (String -> String) -> Either IOException String -> String
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> IOException -> String
forall a b. a -> b -> a
const (RawFilePath -> String
BC.unpack RawFilePath
path1)) String -> String
forall a. a -> a
id (Either IOException String -> String)
-> IO (Either IOException String) -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e a. Exception e => IO a -> IO (Either e a)
try @IOException (RawFilePath -> IO String
decodeWithBasePosix RawFilePath
path1)
path2' <- either (const (BC.unpack path2)) id <$> try @IOException (decodeWithBasePosix path2)
throwErrnoIfMinus1_ (loc <> " '" <> path1' <> "' to '" <> path2' <> "'") action
decodeWithBasePosix :: RawFilePath -> IO String
decodeWithBasePosix :: RawFilePath -> IO String
decodeWithBasePosix RawFilePath
ba = RawFilePath -> (CStringLen -> IO String) -> IO String
forall a. RawFilePath -> (CStringLen -> IO a) -> IO a
B.useAsCStringLen RawFilePath
ba ((CStringLen -> IO String) -> IO String)
-> (CStringLen -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \CStringLen
fp -> CStringLen -> IO String
peekFilePathPosix CStringLen
fp
where
peekFilePathPosix :: CStringLen -> IO String
peekFilePathPosix :: CStringLen -> IO String
peekFilePathPosix CStringLen
fp = IO TextEncoding
getFileSystemEncoding IO TextEncoding -> (TextEncoding -> IO String) -> IO String
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \TextEncoding
enc -> TextEncoding -> CStringLen -> IO String
GHC.peekCStringLen TextEncoding
enc CStringLen
fp
useAsCStringSafe :: RawFilePath -> (CString -> IO a) -> IO a
useAsCStringSafe :: forall a. RawFilePath -> (CString -> IO a) -> IO a
useAsCStringSafe RawFilePath
path CString -> IO a
f = RawFilePath -> (CString -> IO a) -> IO a
forall a. RawFilePath -> (CString -> IO a) -> IO a
useAsCString RawFilePath
path ((CString -> IO a) -> IO a) -> (CString -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \CString
ptr -> do
let len :: Int
len = RawFilePath -> Int
B.length RawFilePath
path
clen <- CString -> IO CSize
c_strlen CString
ptr
if clen == fromIntegral len
then f ptr
else do
path' <- either (const (BC.unpack path)) id <$> try @IOException (decodeWithBasePosix path)
ioError (err path')
where
err :: String -> IOException
err String
path' =
IOError
{ ioe_handle :: Maybe Handle
ioe_handle = Maybe Handle
forall a. Maybe a
Nothing
, ioe_type :: IOErrorType
ioe_type = IOErrorType
InvalidArgument
, ioe_location :: String
ioe_location = String
"checkForInteriorNuls"
, ioe_description :: String
ioe_description = String
"POSIX filepaths must not contain internal NUL octets."
, ioe_errno :: Maybe CInt
ioe_errno = Maybe CInt
forall a. Maybe a
Nothing
, ioe_filename :: Maybe String
ioe_filename = String -> Maybe String
forall a. a -> Maybe a
Just String
path'
}