|
1 | 1 | {-# LANGUAGE Safe #-}
|
| 2 | +{-# LANGUAGE TypeApplications #-} |
2 | 3 |
|
3 | 4 | -----------------------------------------------------------------------------
|
4 | 5 | -- |
|
@@ -39,7 +40,10 @@ import Foreign.C hiding (
|
39 | 40 | throwErrnoPathIfMinus1_ )
|
40 | 41 |
|
41 | 42 | import Control.Monad
|
42 |
| -import Data.ByteString |
| 43 | +import Control.Exception |
| 44 | +import GHC.Foreign as GHC ( peekCStringLen ) |
| 45 | +import GHC.IO.Encoding ( getFileSystemEncoding ) |
| 46 | +import Data.ByteString as B |
43 | 47 | import Data.ByteString.Char8 as BC
|
44 | 48 | import Prelude hiding (FilePath)
|
45 | 49 | #if !MIN_VERSION_base(4, 11, 0)
|
@@ -91,7 +95,8 @@ throwErrnoPath :: String -> RawFilePath -> IO a
|
91 | 95 | throwErrnoPath loc path =
|
92 | 96 | do
|
93 | 97 | errno <- getErrno
|
94 |
| - ioError (errnoToIOError loc errno Nothing (Just (BC.unpack path))) |
| 98 | + path' <- either (const (BC.unpack path)) id <$> try @IOException (decodeWithBasePosix path) |
| 99 | + ioError (errnoToIOError loc errno Nothing (Just path')) |
95 | 100 |
|
96 | 101 | -- | as 'throwErrnoIf', but exceptions include the given path when
|
97 | 102 | -- appropriate.
|
@@ -129,5 +134,16 @@ throwErrnoPathIfMinus1_ = throwErrnoPathIf_ (== -1)
|
129 | 134 | -- | as 'throwErrnoTwoPathsIfMinus1_', but exceptions include two paths when appropriate.
|
130 | 135 | --
|
131 | 136 | throwErrnoTwoPathsIfMinus1_ :: (Eq a, Num a) => String -> RawFilePath -> RawFilePath -> IO a -> IO ()
|
132 |
| -throwErrnoTwoPathsIfMinus1_ loc path1 path2 = |
133 |
| - throwErrnoIfMinus1_ (loc <> " '" <> BC.unpack path1 <> "' to '" <> BC.unpack path2 <> "'") |
| 137 | +throwErrnoTwoPathsIfMinus1_ loc path1 path2 action = do |
| 138 | + path1' <- either (const (BC.unpack path1)) id <$> try @IOException (decodeWithBasePosix path1) |
| 139 | + path2' <- either (const (BC.unpack path2)) id <$> try @IOException (decodeWithBasePosix path2) |
| 140 | + throwErrnoIfMinus1_ (loc <> " '" <> path1' <> "' to '" <> path2' <> "'") action |
| 141 | + |
| 142 | +-- | This mimics the filepath decoder base uses on unix, |
| 143 | +-- with the small distinction that we're not truncating at NUL bytes (because we're not at |
| 144 | +-- the outer FFI layer). |
| 145 | +decodeWithBasePosix :: RawFilePath -> IO String |
| 146 | +decodeWithBasePosix ba = B.useAsCStringLen ba $ \fp -> peekFilePathPosix fp |
| 147 | + where |
| 148 | + peekFilePathPosix :: CStringLen -> IO String |
| 149 | + peekFilePathPosix fp = getFileSystemEncoding >>= \enc -> GHC.peekCStringLen enc fp |
0 commit comments