libarchive-1.0.3.0: src/Codec/Archive.hs
-- | This module contains higher-level functions for working with archives in
-- Haskell. See "Codec.Archive.Foreign" for direct bindings to
-- libarchive.
module Codec.Archive
( -- * High-level functionality
unpackToDir
, unpackArchive
, entriesToFile
, entriesToFileZip
, entriesToFile7Zip
, entriesToBS
, entriesToBS7zip
, entriesToBSzip
, readArchiveFile
, readArchiveBS
-- * Concrete (Haskell) types
, Entry (..)
, EntryContent (..)
, Ownership (..)
, Permissions
, ModTime
, Id
-- * Permissions helpers
, standardPermissions
, executablePermissions
) where
import Codec.Archive.Foreign
import Codec.Archive.Pack
import Codec.Archive.Types
import Codec.Archive.Unpack
import Control.Monad (void, (<=<))
import Data.ByteString (useAsCStringLen)
import qualified Data.ByteString as BS
import Foreign.C.String
import Foreign.Ptr (Ptr)
import System.IO.Unsafe (unsafePerformIO)
-- | Read from an 'Archive' and then free it
actFree :: (Ptr Archive -> IO a) -> Ptr Archive -> IO a
actFree fact a = fact a <* archive_read_free a
-- | Read an archive from a file. The format of the archive is automatically
-- detected.
readArchiveFile :: FilePath -> IO [Entry]
readArchiveFile = actFree hsEntries <=< archiveFile
-- | Read an archive contained in a 'BS.ByteString'. The format of the archive is
-- automatically detected.
readArchiveBS :: BS.ByteString -> [Entry]
readArchiveBS = unsafePerformIO . (actFree hsEntries <=< bsToArchive)
{-# NOINLINE readArchiveBS #-}
archiveFile :: FilePath -> IO (Ptr Archive)
archiveFile fp = withCString fp $ \cpath -> do
a <- archive_read_new
void $ archive_read_support_format_all a
void $ archive_read_open_filename a cpath 10240
pure a
-- | This is more efficient than
--
-- @
-- unpackToDir "llvm" =<< BS.readFile "llvm.tar"
-- @
unpackArchive :: FilePath -- ^ Filepath pointing to archive
-> FilePath -- ^ Dirctory to unpack in
-> IO ()
unpackArchive tarFp dirFp = do
a <- archiveFile tarFp
unpackEntriesFp a dirFp
void $ archive_read_free a
bsToArchive :: BS.ByteString -> IO (Ptr Archive)
bsToArchive bs = do
a <- archive_read_new
void $ archive_read_support_format_all a
useAsCStringLen bs $
\(charPtr, sz) ->
void $ archive_read_open_memory a charPtr (fromIntegral sz)
pure a
unpackToDir :: FilePath -- ^ Directory to unpack in
-> BS.ByteString -- ^ 'BS.ByteString' containing archive
-> IO ()
unpackToDir fp bs = do
a <- bsToArchive bs
unpackEntriesFp a fp
void $ archive_read_free a