{-# LANGUAGE DeriveDataTypeable        #-}
{-# LANGUAGE DeriveGeneric             #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings         #-}
{-# LANGUAGE Rank2Types                #-}

--
-- This is the main interface. APIs should be quite self-explainatory.
--

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