{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Rank2Types #-}
module Data.CPIO
( readCPIO
, writeCPIO
, Entry(..)
, FormatError(..)
, isEntryDirectory
) where
import Control.Applicative ((<$>))
import qualified Control.Exception as E
import Control.Monad (forM_, when)
import Data.Binary.Get (getWord32be, runGet)
import Data.Binary.Put (putWord32be, runPut)
import Data.Bits ((.&.))
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base16 as B16
import qualified Data.ByteString.Lazy as BL
import Data.Conduit
import qualified Data.Conduit.Binary as CB
import Data.Int (Int64)
import Data.Typeable (Typeable)
import Data.Word (Word32)
data Entry = Entry
{ Entry -> Word32
cpioInode :: !Word32
, Entry -> Word32
cpioMode :: !Word32
, Entry -> Word32
cpioUid :: !Word32
, Entry -> Word32
cpioGid :: !Word32
, Entry -> Word32
cpioNLink :: !Word32
, Entry -> Word32
cpioMTime :: !Word32
, Entry -> Word32
cpioFileSize :: !Word32
, Entry -> Word32
cpioDevMaj :: !Word32
, Entry -> Word32
cpioDevMin :: !Word32
, Entry -> Word32
cpioRDevMaj :: !Word32
, Entry -> Word32
cpioRDevMin :: !Word32
, Entry -> Maybe Word32
cpioCRC32 :: Maybe Word32
, Entry -> ByteString
cpioFileName :: ByteString
, Entry -> ByteString
cpioFileData :: BL.ByteString
} deriving (Int -> Entry -> ShowS
[Entry] -> ShowS
Entry -> String
(Int -> Entry -> ShowS)
-> (Entry -> String) -> ([Entry] -> ShowS) -> Show Entry
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Entry] -> ShowS
$cshowList :: [Entry] -> ShowS
show :: Entry -> String
$cshow :: Entry -> String
showsPrec :: Int -> Entry -> ShowS
$cshowsPrec :: Int -> Entry -> ShowS
Show, ReadPrec [Entry]
ReadPrec Entry
Int -> ReadS Entry
ReadS [Entry]
(Int -> ReadS Entry)
-> ReadS [Entry]
-> ReadPrec Entry
-> ReadPrec [Entry]
-> Read Entry
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Entry]
$creadListPrec :: ReadPrec [Entry]
readPrec :: ReadPrec Entry
$creadPrec :: ReadPrec Entry
readList :: ReadS [Entry]
$creadList :: ReadS [Entry]
readsPrec :: Int -> ReadS Entry
$creadsPrec :: Int -> ReadS Entry
Read, Entry -> Entry -> Bool
(Entry -> Entry -> Bool) -> (Entry -> Entry -> Bool) -> Eq Entry
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Entry -> Entry -> Bool
$c/= :: Entry -> Entry -> Bool
== :: Entry -> Entry -> Bool
$c== :: Entry -> Entry -> Bool
Eq)
data FormatError
= TruncatedArchive
| InvalidMagic ByteString
| InvalidHex ByteString
deriving (Typeable)
instance E.Exception FormatError
isEntryDirectory :: Entry -> Bool
isEntryDirectory :: Entry -> Bool
isEntryDirectory entry :: Entry
entry = (Entry -> Word32
cpioMode Entry
entry) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. 0o040000 Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
instance Show FormatError where
show :: FormatError -> String
show TruncatedArchive = "truncated cpio archive"
show (InvalidMagic s :: ByteString
s) = "invalid magic: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ (ByteString -> String
forall a. Show a => a -> String
show ByteString
s)
show (InvalidHex s :: ByteString
s) = "invalid hex: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ (ByteString -> String
forall a. Show a => a -> String
show ByteString
s)
takeExactlyLazy :: Monad m => Int64 -> Consumer ByteString m BL.ByteString
takeExactlyLazy :: Int64 -> Consumer ByteString m ByteString
takeExactlyLazy len :: Int64
len = do
ByteString
x <- Int -> ConduitT ByteString o m ByteString
forall (m :: * -> *) o.
Monad m =>
Int -> ConduitT ByteString o m ByteString
CB.take (Int -> ConduitT ByteString o m ByteString)
-> Int -> ConduitT ByteString o m ByteString
forall a b. (a -> b) -> a -> b
$ Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
len
if ByteString -> Int64
BL.length ByteString
x Int64 -> Int64 -> Bool
forall a. Eq a => a -> a -> Bool
== Int64
len
then ByteString -> ConduitT ByteString o m ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
x
else FormatError -> ConduitT ByteString o m ByteString
forall a e. Exception e => e -> a
E.throw FormatError
TruncatedArchive
takeExactly :: Monad m => Int64 -> Consumer ByteString m ByteString
takeExactly :: Int64 -> Consumer ByteString m ByteString
takeExactly len :: Int64
len = (ByteString -> ByteString)
-> ConduitT ByteString o m ByteString
-> ConduitT ByteString o m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([ByteString] -> ByteString
BS.concat ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
BL.toChunks) (ConduitT ByteString o m ByteString
-> ConduitT ByteString o m ByteString)
-> ConduitT ByteString o m ByteString
-> ConduitT ByteString o m ByteString
forall a b. (a -> b) -> a -> b
$ Int64 -> Consumer ByteString m ByteString
forall (m :: * -> *).
Monad m =>
Int64 -> Consumer ByteString m ByteString
takeExactlyLazy Int64
len
trailerText :: ByteString
trailerText :: ByteString
trailerText = "TRAILER!!!"
alignTo4 :: Integral a => a -> a
alignTo4 :: a -> a
alignTo4 0 = 0
alignTo4 n :: a
n = 3 a -> a -> a
forall a. Num a => a -> a -> a
- ((a
n a -> a -> a
forall a. Num a => a -> a -> a
- 1) a -> a -> a
forall a. Integral a => a -> a -> a
`mod` 4)
readCPIO :: Monad m => Conduit ByteString m Entry
readCPIO :: Conduit ByteString m Entry
readCPIO = do
ByteString
magic <- (ByteString -> ByteString)
-> ConduitT ByteString Entry m ByteString
-> ConduitT ByteString Entry m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([ByteString] -> ByteString
BS.concat ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
BL.toChunks) (ConduitT ByteString Entry m ByteString
-> ConduitT ByteString Entry m ByteString)
-> ConduitT ByteString Entry m ByteString
-> ConduitT ByteString Entry m ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ConduitT ByteString Entry m ByteString
forall (m :: * -> *) o.
Monad m =>
Int -> ConduitT ByteString o m ByteString
CB.take 6
Bool
has_crc <-
case ByteString
magic of
"070701" -> Bool -> ConduitT ByteString Entry m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
"070702" -> Bool -> ConduitT ByteString Entry m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
_ -> FormatError -> ConduitT ByteString Entry m Bool
forall a e. Exception e => e -> a
E.throw (ByteString -> FormatError
InvalidMagic ByteString
magic)
Word32
inode <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
mode <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
uid <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
gid <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
nlink <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
mtime <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
filesize <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
devmaj <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
devmin <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
rdevmaj <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
rdevmin <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
filenamesize <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
Word32
crc32 <- ConduitT ByteString Entry m Word32
forall (m :: * -> *) o. Monad m => ConduitT ByteString o m Word32
decodeR32
let filenamesize_ :: a
filenamesize_ = Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a) -> Integer -> a
forall a b. (a -> b) -> a -> b
$ Word32 -> Integer
forall a. Integral a => a -> Integer
toInteger Word32
filenamesize
ByteString
filename <- ((Word8 -> Bool) -> ByteString -> ByteString
BS.takeWhile (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= 0)) (ByteString -> ByteString)
-> ConduitT ByteString Entry m ByteString
-> ConduitT ByteString Entry m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int64 -> Consumer ByteString m ByteString
forall (m :: * -> *).
Monad m =>
Int64 -> Consumer ByteString m ByteString
takeExactly
Int64
forall a. Num a => a
filenamesize_
ByteString
_ <- Int64 -> ConduitT ByteString Entry m ByteString
forall (m :: * -> *).
Monad m =>
Int64 -> Consumer ByteString m ByteString
takeExactly (Int64 -> ConduitT ByteString Entry m ByteString)
-> Int64 -> ConduitT ByteString Entry m ByteString
forall a b. (a -> b) -> a -> b
$ Int64 -> Int64
forall a. Integral a => a -> a
alignTo4 (Int64 -> Int64) -> Int64 -> Int64
forall a b. (a -> b) -> a -> b
$ 110 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int64
forall a. Num a => a
filenamesize_
let filesize_ :: a
filesize_ = (Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a) -> Integer -> a
forall a b. (a -> b) -> a -> b
$ Word32 -> Integer
forall a. Integral a => a -> Integer
toInteger Word32
filesize)
ByteString
filedata <- Int64 -> Consumer ByteString m ByteString
forall (m :: * -> *).
Monad m =>
Int64 -> Consumer ByteString m ByteString
takeExactlyLazy Int64
forall a. Num a => a
filesize_
let entry :: Entry
entry =
Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Maybe Word32
-> ByteString
-> ByteString
-> Entry
Entry Word32
inode Word32
mode Word32
uid Word32
gid Word32
nlink Word32
mtime Word32
filesize Word32
devmaj
Word32
devmin Word32
rdevmaj Word32
rdevmin
(if Bool
has_crc then Maybe Word32
forall a. Maybe a
Nothing else Word32 -> Maybe Word32
forall a. a -> Maybe a
Just Word32
crc32) ByteString
filename ByteString
filedata
Bool -> Conduit ByteString m Entry -> Conduit ByteString m Entry
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ByteString
filename ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
/= ByteString
trailerText) (Conduit ByteString m Entry -> Conduit ByteString m Entry)
-> Conduit ByteString m Entry -> Conduit ByteString m Entry
forall a b. (a -> b) -> a -> b
$ do
Entry -> Conduit ByteString m Entry
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield Entry
entry
ByteString
_ <- Int64 -> ConduitT ByteString Entry m ByteString
forall (m :: * -> *).
Monad m =>
Int64 -> Consumer ByteString m ByteString
takeExactly (Int64 -> ConduitT ByteString Entry m ByteString)
-> Int64 -> ConduitT ByteString Entry m ByteString
forall a b. (a -> b) -> a -> b
$ Int64 -> Int64
forall a. Integral a => a -> a
alignTo4 Int64
forall a. Num a => a
filesize_
Conduit ByteString m Entry
forall (m :: * -> *). Monad m => Conduit ByteString m Entry
readCPIO
where
decodeR32 :: ConduitT ByteString o m Word32
decodeR32 = do
ByteString
v <- Int64 -> Consumer ByteString m ByteString
forall (m :: * -> *).
Monad m =>
Int64 -> Consumer ByteString m ByteString
takeExactly 8
case ByteString -> (ByteString, ByteString)
B16.decode ByteString
v of
(decoded :: ByteString
decoded, "") ->
Word32 -> ConduitT ByteString o m Word32
forall (m :: * -> *) a. Monad m => a -> m a
return (Word32 -> ConduitT ByteString o m Word32)
-> Word32 -> ConduitT ByteString o m Word32
forall a b. (a -> b) -> a -> b
$ Get Word32 -> ByteString -> Word32
forall a. Get a -> ByteString -> a
runGet Get Word32
getWord32be (ByteString -> Word32) -> ByteString -> Word32
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
BL.fromChunks [ ByteString
decoded ]
(_, _) ->
FormatError -> ConduitT ByteString o m Word32
forall a e. Exception e => e -> a
E.throw (ByteString -> FormatError
InvalidHex ByteString
v)
writeCPIO :: Monad m => Conduit Entry m ByteString
writeCPIO :: Conduit Entry m ByteString
writeCPIO = do
Maybe Entry
entry_ <- ConduitT Entry ByteString m (Maybe Entry)
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
await
case Maybe Entry
entry_ of
Nothing ->
Entry -> Conduit Entry m ByteString
forall (m :: * -> *) i.
Monad m =>
Entry -> ConduitT i ByteString m ()
write_entry (Entry -> Conduit Entry m ByteString)
-> Entry -> Conduit Entry m ByteString
forall a b. (a -> b) -> a -> b
$ Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Maybe Word32
-> ByteString
-> ByteString
-> Entry
Entry 0 0 0 0 0 0 0 0 0 0 0 (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just 0) ByteString
trailerText ""
Just entry :: Entry
entry -> do
Entry -> Conduit Entry m ByteString
forall (m :: * -> *) i.
Monad m =>
Entry -> ConduitT i ByteString m ()
write_entry Entry
entry
Conduit Entry m ByteString
forall (m :: * -> *). Monad m => Conduit Entry m ByteString
writeCPIO
where
encodeR32 :: Word32 -> ConduitT i ByteString m ()
encodeR32 x :: Word32
x = ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ByteString -> ConduitT i ByteString m ())
-> ByteString -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
B16.encode (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
BS.concat ([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
BL.toChunks (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPut (Word32 -> Put
putWord32be Word32
x)
write_entry :: Entry -> ConduitT i ByteString m ()
write_entry entry :: Entry
entry = do
case Entry -> Maybe Word32
cpioCRC32 Entry
entry of
Nothing -> ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield "070701"
Just _ -> ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield "070702"
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioInode Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioMode Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioUid Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioGid Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioNLink Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioMTime Entry
entry
let file_size :: Word32
file_size = Entry -> Word32
cpioFileSize Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Word32
file_size
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioDevMaj Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioDevMin Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioRDevMaj Entry
entry
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> Word32
cpioRDevMin Entry
entry
let filename_length :: a
filename_length =
1 a -> a -> a
forall a. Num a => a -> a -> a
+ (Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a) -> Integer -> a
forall a b. (a -> b) -> a -> b
$ Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Int -> Integer) -> Int -> Integer
forall a b. (a -> b) -> a -> b
$ ByteString -> Int
BS.length (ByteString -> Int) -> ByteString -> Int
forall a b. (a -> b) -> a -> b
$ Entry -> ByteString
cpioFileName Entry
entry)
Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 (Word32 -> ConduitT i ByteString m ())
-> Word32 -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ (Word32
forall a. Num a => a
filename_length :: Word32)
case Entry -> Maybe Word32
cpioCRC32 Entry
entry of
Nothing -> Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 0
Just x :: Word32
x -> Word32 -> ConduitT i ByteString m ()
forall (m :: * -> *) i.
Monad m =>
Word32 -> ConduitT i ByteString m ()
encodeR32 Word32
x
ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ByteString -> ConduitT i ByteString m ())
-> ByteString -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Entry -> ByteString
cpioFileName Entry
entry
ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ByteString -> ConduitT i ByteString m ())
-> ByteString -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ "\NUL"
ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ByteString -> ConduitT i ByteString m ())
-> ByteString -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word8 -> ByteString
BS.replicate (Int -> Int
forall a. Integral a => a -> a
alignTo4 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ 110 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
forall a. Num a => a
filename_length) 0
[ByteString]
-> (ByteString -> ConduitT i ByteString m ())
-> ConduitT i ByteString m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (ByteString -> [ByteString]
BL.toChunks (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall a b. (a -> b) -> a -> b
$ Entry -> ByteString
cpioFileData Entry
entry) ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield
ByteString -> ConduitT i ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ByteString -> ConduitT i ByteString m ())
-> ByteString -> ConduitT i ByteString m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word8 -> ByteString
BS.replicate (Int -> Int
forall a. Integral a => a -> a
alignTo4 (Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Word32 -> Integer
forall a. Integral a => a -> Integer
toInteger Word32
file_size)) 0