Skip to content

Commit 1ddee88

Browse files
hasufellBodigrim
authored andcommitted
Use decodeFS for ioe_filename
1 parent b104a7f commit 1ddee88

File tree

2 files changed

+31
-13
lines changed

2 files changed

+31
-13
lines changed

System/Posix/ByteString/FilePath.hsc

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE Safe #-}
2+
{-# LANGUAGE TypeApplications #-}
23

34
-----------------------------------------------------------------------------
45
-- |
@@ -39,7 +40,10 @@ import Foreign.C hiding (
3940
throwErrnoPathIfMinus1_ )
4041

4142
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
4347
import Data.ByteString.Char8 as BC
4448
import Prelude hiding (FilePath)
4549
#if !MIN_VERSION_base(4, 11, 0)
@@ -91,7 +95,8 @@ throwErrnoPath :: String -> RawFilePath -> IO a
9195
throwErrnoPath loc path =
9296
do
9397
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'))
95100

96101
-- | as 'throwErrnoIf', but exceptions include the given path when
97102
-- appropriate.
@@ -129,5 +134,16 @@ throwErrnoPathIfMinus1_ = throwErrnoPathIf_ (== -1)
129134
-- | as 'throwErrnoTwoPathsIfMinus1_', but exceptions include two paths when appropriate.
130135
--
131136
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

System/Posix/PosixPath/FilePath.hsc

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE CPP #-}
2+
{-# LANGUAGE TypeApplications #-}
23

34
-----------------------------------------------------------------------------
45
-- |
@@ -40,12 +41,12 @@ import Foreign.C hiding (
4041

4142
import System.OsPath.Types
4243
import Control.Monad
43-
import GHC.IO.Encoding.UTF8 ( mkUTF8 )
44-
import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
45-
import System.OsPath.Posix
44+
import Control.Exception
45+
import System.OsPath.Posix as PS
4646
import System.OsPath.Data.ByteString.Short
4747
import Prelude hiding (FilePath)
4848
import System.OsString.Internal.Types (PosixString(..))
49+
4950
#if !MIN_VERSION_base(4, 11, 0)
5051
import Data.Monoid ((<>))
5152
#endif
@@ -93,7 +94,8 @@ throwErrnoPath :: String -> PosixPath -> IO a
9394
throwErrnoPath loc path =
9495
do
9596
errno <- getErrno
96-
ioError (errnoToIOError loc errno Nothing (Just (_toStr path)))
97+
path' <- either (const (_toStr path)) id <$> try @IOException (PS.decodeFS path)
98+
ioError (errnoToIOError loc errno Nothing (Just path'))
9799

98100
-- | as 'throwErrnoIf', but exceptions include the given path when
99101
-- appropriate.
@@ -131,10 +133,10 @@ throwErrnoPathIfMinus1_ = throwErrnoPathIf_ (== -1)
131133
-- | as 'throwErrnoTwoPathsIfMinus1_', but exceptions include two paths when appropriate.
132134
--
133135
throwErrnoTwoPathsIfMinus1_ :: (Eq a, Num a) => String -> PosixPath -> PosixPath -> IO a -> IO ()
134-
throwErrnoTwoPathsIfMinus1_ loc path1 path2 =
135-
throwErrnoIfMinus1_ (loc <> " '" <> _toStr path1 <> "' to '" <> _toStr path2 <> "'")
136-
136+
throwErrnoTwoPathsIfMinus1_ loc path1 path2 action = do
137+
path1' <- either (const (_toStr path1)) id <$> try @IOException (PS.decodeFS path1)
138+
path2' <- either (const (_toStr path2)) id <$> try @IOException (PS.decodeFS path2)
139+
throwErrnoIfMinus1_ (loc <> " '" <> path1' <> "' to '" <> path2' <> "'") action
137140

138141
_toStr :: PosixPath -> String
139-
_toStr fp = either (error . show) id $ decodeWith (mkUTF8 TransliterateCodingFailure) fp
140-
142+
_toStr = fmap PS.toChar . PS.unpack

0 commit comments

Comments
 (0)