@@ -43,10 +43,14 @@ import Cardano.Prelude
43
43
import Control.Monad.Trans.Except.Extra (firstExceptT , handleIOExceptT , hoistEither )
44
44
import qualified Data.Aeson as Aeson
45
45
import qualified Data.ByteString as BS
46
+ import qualified Data.ByteString.Lazy as LBS
47
+ import qualified Data.ByteString.Builder as Builder
46
48
import qualified Data.ByteString.Char8 as BSC
47
49
import qualified Data.List.NonEmpty as NE
48
50
import qualified Data.Text as Text
49
51
import qualified Data.Text.Encoding as Text
52
+ import GHC.IO.Handle (hClose )
53
+ import GHC.IO.Handle.FD (openFileBlocking )
50
54
51
55
import Cardano.Api
52
56
@@ -239,6 +243,24 @@ deserialiseInputAnyOf bech32Types textEnvTypes inputBs =
239
243
-- Cryptographic key deserialisation
240
244
------------------------------------------------------------------------------
241
245
246
+ -- It's possible a user might be supplying keys via a pipe that may
247
+ -- not yet have data by the time we want to read, so we need to make
248
+ -- sure we support that.
249
+ readFileBlocking :: FilePath -> IO ByteString
250
+ readFileBlocking path = bracket
251
+ (openFileBlocking path ReadMode )
252
+ hClose
253
+ (\ fp -> do
254
+ -- An arbitrary block size.
255
+ let blockSize = 4096
256
+ let go acc = do
257
+ next <- BS. hGet fp blockSize
258
+ if BS. null next
259
+ then pure acc
260
+ else go (acc <> Builder. byteString next)
261
+ contents <- go mempty
262
+ pure $ LBS. toStrict $ Builder. toLazyByteString contents)
263
+
242
264
-- | Read a cryptographic key from a file.
243
265
--
244
266
-- The contents of the file can either be Bech32-encoded, hex-encoded, or in
@@ -250,7 +272,7 @@ readKeyFile
250
272
-> IO (Either (FileError InputDecodeError ) a )
251
273
readKeyFile asType acceptedFormats path =
252
274
runExceptT $ do
253
- content <- handleIOExceptT (FileIOError path) $ BS. readFile path
275
+ content <- handleIOExceptT (FileIOError path) $ readFileBlocking path
254
276
firstExceptT (FileError path) $ hoistEither $
255
277
deserialiseInput asType acceptedFormats content
256
278
@@ -289,7 +311,7 @@ readKeyFileAnyOf
289
311
-> IO (Either (FileError InputDecodeError ) b )
290
312
readKeyFileAnyOf bech32Types textEnvTypes path =
291
313
runExceptT $ do
292
- content <- handleIOExceptT (FileIOError path) $ BS. readFile path
314
+ content <- handleIOExceptT (FileIOError path) $ readFileBlocking path
293
315
firstExceptT (FileError path) $ hoistEither $
294
316
deserialiseInputAnyOf bech32Types textEnvTypes content
295
317
0 commit comments