diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # libarchive
 
+## 1.0.0.0
+
+  * Get rid of `cbits`
+  * Add low-level FFI bindings
+  * Add high-level functions for unpacking archives
+
 ## 0.2.1.2
 
   * Stream from a file when using `unpackArchive`
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,9 +4,10 @@
 [![Hackage](https://img.shields.io/hackage/v/libarchive.svg)](http://hackage.haskell.org/package/libarchive)
 [![Dependencies of latest version on Hackage](https://img.shields.io/hackage-deps/v/libarchive.svg)](https://hackage.haskell.org/package/libarchive)
 
-This contains partial Haskell bindings around
+This contains Haskell bindings to
 [libarchive](http://libarchive.org/). It was created as an alternative to
 [tar](http://hackage.haskell.org/package/tar), but it supports more archive
 formats.
 
-Right now it only has support for decompressing archives.
+It has a high-level Haskell API for creating and unpacking archives in addition
+to the C API.
diff --git a/cabal.project.local b/cabal.project.local
--- a/cabal.project.local
+++ b/cabal.project.local
@@ -1,2 +1,2 @@
-constraints: libarchive +development
 documentation: true
+max-backjumps: 40000
diff --git a/cbits/unpack.c b/cbits/unpack.c
deleted file mode 100644
--- a/cbits/unpack.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <archive.h>
-#include <archive_entry.h>
-
-void unpack_common(char* dirname, struct archive *a, struct archive_entry *entry) {
-
-    while (archive_read_next_header(a, &entry) == ARCHIVE_OK || archive_read_next_header(a, &entry) == ARCHIVE_RETRY) {
-        const char* pre_path_name = archive_entry_pathname(entry);
-        size_t fp_length = strlen(dirname) + strlen(pre_path_name);
-        char* fp = malloc(fp_length + 1);
-        strcpy(fp, dirname);
-        strcat(fp, pre_path_name);
-        archive_entry_set_pathname(entry, fp);
-        archive_read_extract(a, entry, ARCHIVE_EXTRACT_TIME);
-        archive_entry_set_pathname(entry, pre_path_name);
-        free(fp);
-        archive_read_data_skip(a);
-    }
-    free(dirname);
-
-    archive_read_free(a);
-
-}
-
-void unpack_from_file(char* dirname, char* filepath) {
-
-    // allocate/initialize archive struct
-    struct archive *a;
-    struct archive_entry *entry;
-    a = archive_read_new();
-
-    // autodetect archive format/compression
-    archive_read_support_format_all(a);
-
-    // open from file
-    archive_read_open_filename(a, filepath, 10240);
-
-    unpack_common(dirname, a, entry);
-
-}
-
-
-// Unpack a tar archive (stored in a bytestring) into a particular directory
-void unpack_in_dir(char* dirname, void *buff, size_t size) {
-
-    // step 1: allocate/initialize archive struct
-    struct archive *a;
-    struct archive_entry *entry;
-    a = archive_read_new();
-
-    // autodetect archive format/compression
-    archive_read_support_format_all(a);
-
-    // open from memory (bytestring)
-    archive_read_open_memory(a, buff, size);
-
-    unpack_common(dirname, a, entry);
-
-}
diff --git a/libarchive.cabal b/libarchive.cabal
--- a/libarchive.cabal
+++ b/libarchive.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.18
 name: libarchive
-version: 0.2.1.2
+version: 1.0.0.0
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2018-2019 Vanessa McHale
@@ -9,12 +9,11 @@
 bug-reports: https://github.com/vmchale/libarchive/issues
 synopsis: Haskell interface to libarchive
 description:
-    Partial Haskell bindings for [libarchive](https://www.libarchive.org/). Provides the ability to unpack archives.
+    Haskell bindings for [libarchive](https://www.libarchive.org/). Provides the ability to unpack archives.
 category: Codec
 build-type: Simple
 extra-source-files:
     cabal.project.local
-    cbits/*.c
 extra-doc-files: README.md
                  CHANGELOG.md
 
@@ -22,30 +21,27 @@
     type: git
     location: https://github.com/vmchale/libarchive
 
-flag development
-    description:
-        Enable `-Werror`
-    default: False
-    manual: True
-
 library
     exposed-modules:
         Codec.Archive
+        Codec.Archive.Foreign
+        Codec.Archive.Foreign.Archive
+        Codec.Archive.Foreign.ArchiveEntry
+    build-tools: c2hs >=0.19.1
     pkgconfig-depends: libarchive -any
-    c-sources:
-        cbits/unpack.c
     hs-source-dirs: src
     other-modules:
-        Codec.Archive.Foreign
+        Codec.Archive.Pack
+        Codec.Archive.Unpack
+        Codec.Archive.Foreign.Common
+        Codec.Archive.Types
     default-language: Haskell2010
     ghc-options: -Wall
     build-depends:
-        base >=4.3 && <5,
+        base >=4.9 && <5,
         bytestring -any,
-        filepath -any
-
-    if (flag(development) && impl(ghc >=8.0))
-        ghc-options: -Werror
+        filepath -any,
+        composition-prelude -any
 
     if impl(ghc >=8.0)
         ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates
diff --git a/src/Codec/Archive.hs b/src/Codec/Archive.hs
--- a/src/Codec/Archive.hs
+++ b/src/Codec/Archive.hs
@@ -1,27 +1,92 @@
+-- | This module contains higher-level functions for working with archives in
+-- Haskell. See "Codec.Archive.Foreign" for direct bindings to
+-- libarchive.
 module Codec.Archive
-    ( unpackToDir
+    ( -- * High-level functionality
+      unpackToDir
     , unpackArchive
+    , entriesToFile
+    , entriesToFileZip
+    , entriesToFile7Zip
+    , entriesToBS
+    , entriesToBS7zip
+    , entriesToBSzip
+    , readArchiveFile
+    , readArchiveBS
+    -- * Concrete (Haskell) types
+    , Entry (..)
+    , EntryContent (..)
+    , Ownership (..)
+    , Permissions
+    , ModTime
+    , Id
+    , 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           System.FilePath       (pathSeparator)
+import           Foreign.Ptr           (Ptr)
+import           System.IO.Unsafe      (unsafePerformIO)
 
+withArchiveRead :: (Ptr Archive -> IO a) -> Ptr Archive -> IO a
+withArchiveRead fact a = do
+    res <- fact a
+    void $ archive_read_free a
+    pure res
+
+-- | Read an archive from a file. The format of the archive is automatically
+-- detected.
+readArchiveFile :: FilePath -> IO [Entry]
+readArchiveFile fp =
+    archiveFile fp >>= withArchiveRead hsEntries
+
+-- | Read an archive contained in a 'BS.ByteString'. The format of the archive is
+-- automatically detected.
+readArchiveBS :: BS.ByteString -> [Entry]
+readArchiveBS bs = unsafePerformIO $
+    bsToArchive bs >>= withArchiveRead hsEntries
+{-# 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 -- ^ Filepath to unpack to
+              -> FilePath -- ^ Dirctory to unpack in
               -> IO ()
 unpackArchive tarFp dirFp = do
-    fp' <- newCString tarFp
-    dir' <- newCString (dirFp ++ [pathSeparator])
-    unpack_from_file dir' fp'
+    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 -- ^ 'ByteString' containing archive
+            -> BS.ByteString -- ^ 'BS.ByteString' containing archive
             -> IO ()
 unpackToDir fp bs = do
-    fp' <- newCString (fp ++ [pathSeparator])
-    useAsCStringLen bs $
-        \(charPtr, sz) ->
-            unpack_in_dir fp' charPtr (fromIntegral sz)
+    a <- bsToArchive bs
+    unpackEntriesFp a fp
+    void $ archive_read_free a
diff --git a/src/Codec/Archive/Foreign.hs b/src/Codec/Archive/Foreign.hs
--- a/src/Codec/Archive/Foreign.hs
+++ b/src/Codec/Archive/Foreign.hs
@@ -1,11 +1,9 @@
-module Codec.Archive.Foreign ( unpack_in_dir
-                             , unpack_from_file
+-- | Everything here is stateful and hence takes place in the 'IO' monad.
+--
+-- Consult @archive.h@ or @archive_entry.h@ for documentation.
+module Codec.Archive.Foreign ( module Codec.Archive.Foreign.ArchiveEntry
+                             , module Codec.Archive.Foreign.Archive
                              ) where
 
-import           Data.Word        (Word)
-import           Foreign.C.String
-import           Foreign.C.Types
-import           Foreign.Ptr
-
-foreign import ccall unsafe unpack_in_dir :: CString -> Ptr CChar -> Word -> IO ()
-foreign import ccall unsafe unpack_from_file :: CString -> CString -> IO ()
+import Codec.Archive.Foreign.ArchiveEntry
+import Codec.Archive.Foreign.Archive
diff --git a/src/Codec/Archive/Foreign/Archive.chs b/src/Codec/Archive/Foreign/Archive.chs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Archive/Foreign/Archive.chs
@@ -0,0 +1,898 @@
+-- | This module corresponds to @archive.h@
+module Codec.Archive.Foreign.Archive ( -- * Direct bindings (read)
+                                       archive_read_new
+                                     , archive_read_data_skip
+                                     , archive_read_data
+                                     , archive_read_data_block
+                                     , archive_read_free
+                                     , archive_read_extract
+                                     , archive_read_open_filename
+                                     , archive_read_open_filename_w
+                                     , archive_read_support_filter_all
+                                     , archive_read_support_filter_bzip2
+                                     , archive_read_support_filter_compress
+                                     , archive_read_support_filter_gzip
+                                     , archive_read_support_filter_grzip
+                                     , archive_read_support_filter_lrzip
+                                     , archive_read_support_filter_lz4
+                                     , archive_read_support_filter_lzip
+                                     , archive_read_support_filter_lzma
+                                     , archive_read_support_filter_lzop
+                                     , archive_read_support_filter_none
+                                     , archive_read_support_filter_program
+                                     , archive_read_support_filter_program_signature
+                                     , archive_read_support_filter_rpm
+                                     , archive_read_support_filter_uu
+                                     , archive_read_support_filter_xz
+                                     , archive_read_support_format_7zip
+                                     , archive_read_support_format_all
+                                     , archive_read_support_format_ar
+                                     , archive_read_add_passphrase
+                                     , archive_read_set_passphrase_callback
+                                     , archive_read_extract2
+                                     , archive_read_extract_set_progress_callback
+                                     , archive_read_extract_set_skip_file
+                                     , archive_read_close
+                                     , archive_read_support_format_by_code
+                                     , archive_read_support_format_cab
+                                     , archive_read_support_format_cpio
+                                     , archive_read_support_format_empty
+                                     , archive_read_support_format_gnutar
+                                     , archive_read_support_format_iso9660
+                                     , archive_read_support_format_lha
+                                     , archive_read_support_format_mtree
+                                     , archive_read_support_format_rar
+                                     , archive_read_support_format_raw
+                                     , archive_read_support_format_tar
+                                     , archive_read_support_format_warc
+                                     , archive_read_support_format_xar
+                                     , archive_read_support_format_zip
+                                     , archive_read_support_format_zip_streamable
+                                     , archive_read_support_format_zip_seekable
+                                     , archive_read_set_format
+                                     , archive_read_append_filter
+                                     , archive_read_append_filter_program
+                                     , archive_read_append_filter_program_signature
+                                     , archive_read_set_open_callback
+                                     , archive_read_set_read_callback
+                                     , archive_read_set_seek_callback
+                                     , archive_read_set_skip_callback
+                                     , archive_read_set_close_callback
+                                     , archive_read_set_switch_callback
+                                     , archive_read_set_callback_data
+                                     , archive_read_set_callback_data2
+                                     , archive_read_add_callback_data
+                                     , archive_read_append_callback_data
+                                     , archive_read_prepend_callback_data
+                                     , archive_read_open1
+                                     , archive_read_open
+                                     , archive_read_open2
+                                     , archive_read_open_filenames
+                                     , archive_read_open_memory
+                                     , archive_read_open_memory2
+                                     , archive_read_open_fd
+                                     , archive_read_next_header
+                                     , archive_read_next_header2
+                                     , archive_read_header_position
+                                     , archiveReadHasEncryptedEntries
+                                     , archive_read_format_capabilities
+                                     , archive_seek_data
+                                     , archive_read_data_into_fd
+                                     , archive_read_set_format_option
+                                     , archive_read_set_filter_option
+                                     , archive_read_set_option
+                                     , archive_read_set_options
+                                     , archive_read_disk_new
+                                     , archive_read_disk_set_symlink_logical
+                                     , archive_read_disk_set_symlink_physical
+                                     , archive_read_disk_set_symlink_hybrid
+                                     , archive_read_disk_entry_from_file
+                                     , archive_read_disk_gname
+                                     , archive_read_disk_uname
+                                     , archive_read_disk_set_standard_lookup
+                                     , archive_read_disk_set_gname_lookup
+                                     , archive_read_disk_set_uname_lookup
+                                     , archive_read_disk_open
+                                     , archive_read_disk_open_w
+                                     , archive_read_disk_descend
+                                     , archiveReadDiskCanDescend
+                                     , archive_read_disk_current_filesystem
+                                     , archiveReadDiskCurrentFilesystemIsSynthetic
+                                     , archiveReadDiskCurrentFilesystemIsRemote
+                                     , archive_read_disk_set_atime_restored
+                                     , archive_read_disk_set_behavior
+                                     , archive_read_disk_set_matching
+                                     , archive_read_disk_set_metadata_filter_callback
+                                     -- * Direct bindings (write)
+                                     , archive_write_set_bytes_per_block
+                                     , archive_write_get_bytes_per_block
+                                     , archive_write_set_bytes_in_last_block
+                                     , archive_write_get_bytes_in_last_block
+                                     , archive_write_set_skip_file
+                                     , archive_write_add_filter
+                                     , archive_write_add_filter_by_name
+                                     , archive_write_add_filter_b64encode
+                                     , archive_write_add_filter_bzip2
+                                     , archive_write_add_filter_compress
+                                     , archive_write_add_filter_grzip
+                                     , archive_write_add_filter_gzip
+                                     , archive_write_add_filter_lrzip
+                                     , archive_write_add_filter_lz4
+                                     , archive_write_add_filter_lzip
+                                     , archive_write_add_filter_lzma
+                                     , archive_write_add_filter_lzop
+                                     , archive_write_add_filter_none
+                                     , archive_write_add_filter_program
+                                     , archive_write_add_filter_uuencode
+                                     , archive_write_add_filter_xz
+                                     , archive_write_data
+                                     , archive_write_new
+                                     , archive_write_free
+                                     , archive_write_set_format_pax_restricted
+                                     , archive_write_header
+                                     , archive_write_set_format
+                                     , archive_write_set_format_by_name
+                                     , archive_write_set_format_7zip
+                                     , archive_write_set_format_ar_bsd
+                                     , archive_write_set_format_ar_svr4
+                                     , archive_write_set_format_cpio
+                                     , archive_write_set_format_cpio_newc
+                                     , archive_write_set_format_gnutar
+                                     , archive_write_set_format_iso9660
+                                     , archive_write_set_format_mtree
+                                     , archive_write_set_format_mtree_classic
+                                     , archive_write_set_format_pax
+                                     , archive_write_set_format_raw
+                                     , archive_write_set_format_shar
+                                     , archive_write_set_format_shar_dump
+                                     , archive_write_set_format_ustar
+                                     , archive_write_set_format_v7tar
+                                     , archive_write_set_format_warc
+                                     , archive_write_set_format_xar
+                                     , archive_write_set_format_zip
+                                     , archive_write_set_format_filter_by_ext
+                                     , archive_write_set_format_filter_by_ext_def
+                                     , archive_write_zip_set_compression_deflate
+                                     , archive_write_zip_set_compression_store
+                                     , archive_write_open
+                                     , archive_write_open_fd
+                                     , archive_write_open_filename
+                                     , archive_write_open_filename_w
+                                     , archive_write_open_memory
+                                     , archive_write_data_block
+                                     , archive_write_finish_entry
+                                     , archive_write_close
+                                     , archive_write_fail
+                                     , archive_write_set_format_option
+                                     , archive_write_set_filter_option
+                                     , archive_write_set_option
+                                     , archive_write_set_options
+                                     , archive_write_set_passphrase
+                                     , archive_write_set_passphrase_callback
+                                     , archive_write_disk_new
+                                     , archive_write_disk_set_skip_file
+                                     , archive_write_disk_set_options
+                                     , archive_write_disk_set_standard_lookup
+                                     , archive_write_disk_set_group_lookup
+                                     , archive_write_disk_set_user_lookup
+                                     , archive_write_disk_gid
+                                     , archive_write_disk_uid
+                                     -- * Direct bindings (archive error)
+                                     , archive_errno
+                                     , archive_error_string
+                                     , archive_format_name
+                                     , archive_format
+                                     , archive_clear_error
+                                     , archive_set_error
+                                     , archive_copy_error
+                                     , archive_file_count
+                                     -- * Direct bindings (archive match)
+                                     , archive_match_new
+                                     , archive_match_free
+                                     , archiveMatchExcluded
+                                     , archiveMatchPathExcluded
+                                     , archive_match_exclude_pattern
+                                     , archive_match_exclude_pattern_w
+                                     , archiveMatchExcludePatternFromFile
+                                     , archiveMatchExcludePatternFromFileW
+                                     , archive_match_include_pattern
+                                     , archive_match_include_pattern_w
+                                     , archiveMatchIncludePatternFromFile
+                                     , archiveMatchIncludePatternFromFileW
+                                     , archive_match_path_unmatched_inclusions
+                                     , archive_match_path_unmatched_inclusions_next
+                                     , archive_match_path_unmatched_inclusions_next_w
+                                     , archiveMatchTimeExcluded
+                                     , archive_match_include_time
+                                     , archive_match_include_date
+                                     , archive_match_include_date_w
+                                     , archive_match_include_file_time
+                                     , archive_match_include_file_time_w
+                                     , archive_match_exclude_entry
+                                     , archiveMatchOwnerExcluded
+                                     , archive_match_include_uid
+                                     , archive_match_include_gid
+                                     , archive_match_include_uname
+                                     , archive_match_include_uname_w
+                                     , archive_match_include_gname
+                                     , archive_match_include_gname_w
+                                     -- * Direct bindings (version\/filter\/miscellaneous)
+                                     , archive_version_number
+                                     , archive_version_string
+                                     , archive_version_details
+                                     , archive_free
+                                     , archive_filter_count
+                                     , archive_filter_bytes
+                                     , archive_filter_code
+                                     , archive_filter_name
+                                     -- * Version macros
+                                     , archiveVersionNumber
+                                     , archiveVersionOnlyString
+                                     , archiveVersionString
+                                     -- * Capability macros
+                                     , archiveReadFormatCapsNone
+                                     , archiveReadFormatCapsEncryptData
+                                     , archiveReadFormatCapsEncryptMetadata
+                                     -- * Header read macros
+                                     , archiveOk
+                                     , archiveEOF
+                                     , archiveRetry
+                                     , archiveWarn
+                                     , archiveFailed
+                                     , archiveFatal
+                                     -- * Time matching macros
+                                     , archiveMatchMTime
+                                     , archiveMatchCTime
+                                     , archiveMatchNewer
+                                     , archiveMatchOlder
+                                     , archiveMatchEqual
+                                     -- * Entry flags
+                                     , archiveExtractOwner
+                                     , archiveExtractPerm
+                                     , archiveExtractTime
+                                     , archiveExtractNoOverwrite
+                                     , archiveExtractUnlink
+                                     , archiveExtractACL
+                                     , archiveExtractFFlags
+                                     , archiveExtractXattr
+                                     , archiveExtractSecureSymlinks
+                                     , archiveExtractSecureNoDotDot
+                                     , archiveExtractNoAutodir
+                                     , archiveExtractSparse
+                                     , archiveExtractMacMetadata
+                                     , archiveExtractNoHfsCompression
+                                     , archiveExtractHfsCompressionForced
+                                     , archiveExtractSecureNoAbsolutePaths
+                                     , archiveExtractClearNoChangeFFlags
+                                     -- * Filters
+                                     , archiveFilterNone
+                                     , archiveFilterGzip
+                                     , archiveFilterBzip2
+                                     , archiveFilterCompress
+                                     , archiveFilterProgram
+                                     , archiveFilterLzma
+                                     , archiveFilterXz
+                                     , archiveFilterUu
+                                     , archiveFilterRpm
+                                     , archiveFilterLzip
+                                     , archiveFilterLrzip
+                                     , archiveFilterLzop
+                                     , archiveFilterGrzip
+                                     , archiveFilterLz4
+                                     -- * Formats
+                                     , archiveFormatCpio
+                                     , archiveFormatShar
+                                     , archiveFormatTar
+                                     , archiveFormatIso9660
+                                     , archiveFormatZip
+                                     , archiveFormatEmpty
+                                     , archiveFormatAr
+                                     , archiveFormatMtree
+                                     , archiveFormatRaw
+                                     , archiveFormatXar
+                                     , archiveFormatLha
+                                     , archiveFormatCab
+                                     , archiveFormatRar
+                                     , archiveFormat7zip
+                                     , archiveFormatWarc
+                                     -- * Read disk flags
+                                     , archiveReadDiskRestoreATime
+                                     , archiveReadDiskHonorNoDump
+                                     , archiveReadDiskMacCopyFile
+                                     , archiveReadDiskNoTraverseMounts
+                                     , archiveReadDiskNoXattr
+                                     -- * Abstract types
+                                     , Archive
+                                     -- * Haskell types
+                                     , ArchiveEncryption (..)
+                                     -- * Lower-level API types
+                                     , ArchiveError
+                                     , Flags
+                                     , ArchiveFilter
+                                     , ArchiveFormat
+                                     , ArchiveCapabilities
+                                     , ReadDiskFlags
+                                     , TimeFlag
+                                     -- * Callback types
+                                     , ArchiveReadCallback
+                                     , ArchiveSkipCallback
+                                     , ArchiveSeekCallback
+                                     , ArchiveWriteCallback
+                                     , ArchiveOpenCallback
+                                     , ArchiveCloseCallback
+                                     , ArchiveSwitchCallback
+                                     , ArchivePassphraseCallback
+                                     -- * Callback constructors
+                                     , mkReadCallback
+                                     , mkSkipCallback
+                                     , mkSeekCallback
+                                     , mkWriteCallback
+                                     , mkOpenCallback
+                                     , mkCloseCallback
+                                     , mkSwitchCallback
+                                     , mkPassphraseCallback
+                                     , mkWriteLookup
+                                     , mkReadLookup
+                                     , mkCleanup
+                                     , mkMatch
+                                     , mkFilter
+                                     ) where
+
+import Codec.Archive.Foreign.Common
+import Control.Composition ((.*), (.**))
+import Data.Bits (Bits (..))
+import Data.Int (Int64)
+import Codec.Archive.Types
+import Foreign.C.String
+import Foreign.C.Types
+import Foreign.Ptr (FunPtr, Ptr)
+import System.Posix.Types (Fd (..))
+
+-- Miscellaneous
+foreign import ccall archive_version_number :: CInt
+foreign import ccall archive_version_string :: CString
+foreign import ccall archive_version_details :: CString
+
+-- destructors: use "dynamic" instead of "wrapper" (but we don't want that)
+-- callbacks
+foreign import ccall "wrapper" mkReadCallback :: ArchiveReadCallback a b -> IO (FunPtr (ArchiveReadCallback a b))
+foreign import ccall "wrapper" mkSkipCallback :: ArchiveSkipCallback a -> IO (FunPtr (ArchiveSkipCallback a))
+foreign import ccall "wrapper" mkSeekCallback :: ArchiveSeekCallback a -> IO (FunPtr (ArchiveSeekCallback a))
+foreign import ccall "wrapper" mkWriteCallback :: ArchiveWriteCallback a b -> IO (FunPtr (ArchiveWriteCallback a b))
+foreign import ccall "wrapper" mkOpenCallback :: ArchiveOpenCallback a -> IO (FunPtr (ArchiveOpenCallback a))
+foreign import ccall "wrapper" mkCloseCallback :: ArchiveCloseCallback a -> IO (FunPtr (ArchiveCloseCallback a))
+foreign import ccall "wrapper" mkSwitchCallback :: ArchiveSwitchCallback a b -> IO (FunPtr (ArchiveSwitchCallback a b))
+foreign import ccall "wrapper" mkPassphraseCallback :: ArchivePassphraseCallback a -> IO (FunPtr (ArchivePassphraseCallback a))
+
+foreign import ccall "wrapper" mkWriteLookup :: (Ptr a -> CString -> Int64 -> IO Int64) -> IO (FunPtr (Ptr a -> CString -> Int64 -> IO Int64))
+foreign import ccall "wrapper" mkReadLookup :: (Ptr a -> Int64 -> IO CString) -> IO (FunPtr (Ptr a -> Int64 -> IO CString))
+foreign import ccall "wrapper" mkCleanup :: (Ptr a -> IO ()) -> IO (FunPtr (Ptr a -> IO ()))
+
+foreign import ccall "wrapper" mkMatch :: (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO ()) -> IO (FunPtr (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO ()))
+foreign import ccall "wrapper" preMkFilter :: (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO CInt) -> IO (FunPtr (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO CInt))
+
+mkFilter :: (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO Bool) -> IO (FunPtr (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO CInt))
+mkFilter f = let f' = fmap boolToInt .** f in preMkFilter f'
+
+boolToInt :: Integral a => Bool -> a
+boolToInt False = 0
+boolToInt True = 1
+
+type ArchiveReadCallback a b = Ptr Archive -> Ptr a -> Ptr (Ptr b) -> IO CSize
+type ArchiveSkipCallback a = Ptr Archive -> Ptr a -> Int64 -> IO Int64
+type ArchiveSeekCallback a = Ptr Archive -> Ptr a -> Int64 -> CInt -> IO Int64
+type ArchiveWriteCallback a b = Ptr Archive -> Ptr a -> Ptr b -> CSize -> IO CSize
+type ArchiveOpenCallback a = Ptr Archive -> Ptr a -> IO ArchiveError
+type ArchiveCloseCallback a = Ptr Archive -> Ptr a -> IO ArchiveError
+type ArchiveSwitchCallback a b = Ptr Archive -> Ptr a -> Ptr b -> IO ArchiveError
+type ArchivePassphraseCallback a = Ptr Archive -> Ptr a -> IO CString
+
+-- Archive read
+foreign import ccall unsafe archive_read_new :: IO (Ptr Archive)
+foreign import ccall unsafe archive_read_support_filter_all :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_bzip2 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_compress :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_gzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_grzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_lrzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_lz4 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_lzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_lzma :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_lzop :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_none :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_program :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_program_signature :: Ptr Archive -> CString -> CString -> CSize -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_rpm :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_uu :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_filter_xz :: Ptr Archive -> IO ArchiveError
+-- foreign import ccall unsafe archive_read_support_filter_zstd :: Ptr Archive -> IO ArchiveError
+
+foreign import ccall unsafe archive_read_support_format_7zip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_all :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_ar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_by_code :: Ptr Archive -> CInt -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_cab :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_cpio :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_empty :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_gnutar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_iso9660 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_lha :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_mtree :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_rar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_raw :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_tar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_warc :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_xar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_zip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_zip_streamable :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_support_format_zip_seekable :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_format :: Ptr Archive -> ArchiveFormat -> IO ArchiveError
+foreign import ccall unsafe archive_read_append_filter :: Ptr Archive -> ArchiveFilter -> IO ArchiveError
+foreign import ccall unsafe archive_read_append_filter_program :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_read_append_filter_program_signature :: Ptr Archive -> CString -> Ptr a -> CSize -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_open_callback :: Ptr Archive -> FunPtr (ArchiveOpenCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_read_callback :: Ptr Archive -> FunPtr (ArchiveOpenCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_seek_callback :: Ptr Archive -> FunPtr (ArchiveOpenCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_skip_callback :: Ptr Archive -> FunPtr (ArchiveSkipCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_close_callback :: Ptr Archive -> FunPtr (ArchiveCloseCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_switch_callback :: Ptr Archive -> FunPtr (ArchiveSwitchCallback a b) -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_callback_data :: Ptr Archive -> Ptr a -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_callback_data2 :: Ptr Archive -> Ptr a -> CUInt -> IO ArchiveError
+foreign import ccall unsafe archive_read_add_callback_data :: Ptr Archive -> Ptr a -> CUInt -> IO ArchiveError
+foreign import ccall unsafe archive_read_append_callback_data :: Ptr Archive -> Ptr a -> IO ArchiveError
+foreign import ccall unsafe archive_read_prepend_callback_data :: Ptr Archive -> Ptr a -> IO ArchiveError
+foreign import ccall unsafe archive_read_open1 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_open :: Ptr Archive -> Ptr a -> FunPtr (ArchiveOpenCallback a) -> FunPtr (ArchiveReadCallback a b) -> FunPtr (ArchiveCloseCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_read_open2 :: Ptr Archive -> Ptr a -> FunPtr (ArchiveOpenCallback a) -> FunPtr (ArchiveReadCallback a b) -> FunPtr (ArchiveSkipCallback a) -> FunPtr (ArchiveCloseCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_read_open_filename :: Ptr Archive -> CString -> CSize -> IO ArchiveError
+foreign import ccall unsafe archive_read_open_filenames :: Ptr Archive -> Ptr CString -> CSize -> IO ArchiveError
+foreign import ccall unsafe archive_read_open_filename_w :: Ptr Archive -> CWString -> CSize -> IO ArchiveError
+foreign import ccall unsafe archive_read_open_memory :: Ptr Archive -> Ptr CChar -> CSize -> IO ArchiveError
+foreign import ccall unsafe archive_read_open_memory2 :: Ptr Archive -> Ptr a -> CSize -> CSize -> IO ArchiveError
+foreign import ccall unsafe archive_read_open_fd :: Ptr Archive -> Fd -> CSize -> IO ArchiveError
+-- foreign import ccall unsafe archive_read_open_FILE 
+foreign import ccall unsafe archive_read_next_header :: Ptr Archive -> Ptr (Ptr ArchiveEntry) -> IO ArchiveError
+foreign import ccall unsafe archive_read_next_header2 :: Ptr Archive -> Ptr ArchiveEntry -> IO ArchiveError
+foreign import ccall unsafe archive_read_header_position :: Ptr Archive -> IO Int64
+foreign import ccall unsafe archive_read_has_encrypted_entries :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_read_format_capabilities :: Ptr Archive -> IO ArchiveCapabilities
+
+foreign import ccall unsafe archive_read_data :: Ptr Archive -> Ptr a -> CSize -> IO CSize
+foreign import ccall unsafe archive_seek_data :: Ptr Archive -> Int64 -> CInt -> IO Int64
+foreign import ccall unsafe archive_read_data_block :: Ptr Archive -> Ptr (Ptr a) -> Ptr CSize -> Ptr Int64 -> IO ArchiveError
+foreign import ccall unsafe archive_read_data_skip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_data_into_fd :: Ptr Archive -> Fd -> IO ArchiveError
+
+foreign import ccall unsafe archive_read_set_format_option :: Ptr Archive -> CString -> CString -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_filter_option :: Ptr Archive -> CString -> CString -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_option :: Ptr Archive -> CString -> CString -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_options :: Ptr Archive -> CString -> IO ArchiveError
+
+foreign import ccall unsafe archive_read_add_passphrase :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_read_set_passphrase_callback :: Ptr Archive -> Ptr a -> FunPtr (ArchivePassphraseCallback a) -> IO ArchiveError
+
+foreign import ccall unsafe archive_read_extract :: Ptr Archive -> Ptr ArchiveEntry -> Flags -> IO ArchiveError
+foreign import ccall unsafe archive_read_extract2 :: Ptr Archive -> Ptr ArchiveEntry -> Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_extract_set_progress_callback :: Ptr Archive -> (FunPtr (Ptr a -> IO ())) -> Ptr a -> IO ()
+foreign import ccall unsafe archive_read_extract_set_skip_file :: Ptr Archive -> Int64 -> Int64 -> IO ()
+
+foreign import ccall unsafe archive_read_close :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_free :: Ptr Archive -> IO ArchiveError
+
+-- Archive write
+foreign import ccall unsafe archive_write_new :: IO (Ptr Archive)
+foreign import ccall unsafe archive_write_set_bytes_per_block :: Ptr Archive -> CInt -> IO ArchiveError
+foreign import ccall unsafe archive_write_get_bytes_per_block :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_write_set_bytes_in_last_block :: Ptr Archive -> CInt -> IO ArchiveError
+foreign import ccall unsafe archive_write_get_bytes_in_last_block :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_write_set_skip_file :: Ptr Archive -> Int64 -> Int64 -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter :: Ptr Archive -> ArchiveFilter -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_by_name :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_b64encode :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_bzip2 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_compress :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_grzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_gzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_lrzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_lz4 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_lzip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_lzma :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_lzop :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_none :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_program :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_uuencode :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_add_filter_xz :: Ptr Archive -> IO ArchiveError
+-- foreign import ccall unsafe archive_write_add_filter_zstd :: Ptr Archive -> IO ArchiveError
+
+foreign import ccall unsafe archive_write_set_format :: Ptr Archive -> ArchiveFormat -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_by_name :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_7zip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_ar_bsd :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_ar_svr4 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_cpio :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_cpio_newc :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_gnutar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_iso9660 :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_mtree :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_mtree_classic :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_pax :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_pax_restricted :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_raw :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_shar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_shar_dump :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_ustar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_v7tar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_warc :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_xar :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_zip :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_filter_by_ext :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_format_filter_by_ext_def :: Ptr Archive -> CString -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_zip_set_compression_deflate :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_zip_set_compression_store :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_open :: Ptr Archive -> Ptr a -> FunPtr (ArchiveOpenCallback a) -> FunPtr (ArchiveWriteCallback a b) -> FunPtr (ArchiveCloseCallback a) -> IO ArchiveError
+foreign import ccall unsafe archive_write_open_fd :: Ptr Archive -> Fd -> IO ArchiveError
+foreign import ccall unsafe archive_write_open_filename :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_open_filename_w :: Ptr Archive -> CWString -> IO ArchiveError
+-- foreign import ccall unsafe archive_write_open_FILE
+foreign import ccall unsafe archive_write_open_memory :: Ptr Archive -> Ptr a -> CSize -> Ptr CSize -> IO ArchiveError
+
+foreign import ccall unsafe archive_write_header :: Ptr Archive -> Ptr ArchiveEntry -> IO ArchiveError
+foreign import ccall unsafe archive_write_data :: Ptr Archive -> Ptr a -> CSize -> IO CSize
+
+foreign import ccall unsafe archive_write_data_block :: Ptr Archive -> Ptr a -> CSize -> Int64 -> IO ArchiveError
+
+foreign import ccall unsafe archive_write_finish_entry :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_close :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_fail :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_free :: Ptr Archive -> IO ArchiveError
+
+foreign import ccall unsafe archive_write_set_format_option :: Ptr Archive -> CString -> CString -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_filter_option :: Ptr Archive -> CString -> CString -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_option :: Ptr Archive -> CString -> CString -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_options :: Ptr Archive -> CString -> IO ArchiveError
+
+foreign import ccall unsafe archive_write_set_passphrase :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_write_set_passphrase_callback :: Ptr Archive -> Ptr a -> FunPtr (ArchivePassphraseCallback a) -> IO ArchiveError
+
+foreign import ccall unsafe archive_write_disk_new :: IO (Ptr Archive)
+foreign import ccall unsafe archive_write_disk_set_skip_file :: Ptr Archive -> Int64 -> Int64 -> IO ArchiveError
+foreign import ccall unsafe archive_write_disk_set_options :: Ptr Archive -> Flags -> IO ArchiveError
+
+foreign import ccall unsafe archive_write_disk_set_standard_lookup :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_write_disk_set_group_lookup :: Ptr Archive -> Ptr a -> FunPtr (Ptr a -> CString -> Int64 -> IO Int64) -> FunPtr (Ptr a -> IO ()) -> IO ArchiveError
+foreign import ccall unsafe archive_write_disk_set_user_lookup :: Ptr Archive -> Ptr a -> FunPtr (Ptr a -> CString -> Int64 -> IO Int64) -> FunPtr (Ptr a -> IO ()) -> IO ArchiveError
+foreign import ccall unsafe archive_write_disk_gid :: Ptr Archive -> CString -> Int64 -> IO Int64
+foreign import ccall unsafe archive_write_disk_uid :: Ptr Archive -> CString -> Int64 -> IO Int64
+
+foreign import ccall unsafe archive_read_disk_new :: IO (Ptr Archive)
+foreign import ccall unsafe archive_read_disk_set_symlink_logical :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_set_symlink_physical :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_set_symlink_hybrid :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_entry_from_file :: Ptr Archive -> Ptr ArchiveEntry -> Fd -> Ptr Stat -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_gname :: Ptr Archive -> Int64 -> IO CString
+foreign import ccall unsafe archive_read_disk_uname :: Ptr Archive -> Int64 -> IO CString
+foreign import ccall unsafe archive_read_disk_set_standard_lookup :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_set_gname_lookup :: Ptr Archive -> Ptr a -> FunPtr (Ptr a -> Int64 -> IO CString) -> FunPtr (Ptr a -> IO ()) -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_set_uname_lookup :: Ptr Archive -> Ptr a -> FunPtr (Ptr a -> Int64 -> IO CString) -> FunPtr (Ptr a -> IO ()) -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_open :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_open_w :: Ptr Archive -> CWString -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_descend :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_can_descend :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_read_disk_current_filesystem :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_read_disk_current_filesystem_is_synthetic :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_read_disk_current_filesystem_is_remote :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_read_disk_set_atime_restored :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_set_behavior :: Ptr Archive -> ReadDiskFlags -> IO ArchiveError
+
+foreign import ccall unsafe archive_read_disk_set_matching :: Ptr Archive -> Ptr Archive -> FunPtr (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO ()) -> Ptr a -> IO ArchiveError
+foreign import ccall unsafe archive_read_disk_set_metadata_filter_callback :: Ptr Archive -> FunPtr (Ptr Archive -> Ptr a -> Ptr ArchiveEntry -> IO CInt) -> Ptr a -> IO ArchiveError
+
+foreign import ccall unsafe archive_free :: Ptr Archive -> IO ArchiveError
+
+foreign import ccall unsafe archive_filter_count :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_filter_bytes :: Ptr Archive -> CInt -> Int64
+foreign import ccall unsafe archive_filter_code :: Ptr Archive -> CInt -> IO Int
+foreign import ccall unsafe archive_filter_name :: Ptr Archive -> CInt -> IO CString
+
+foreign import ccall unsafe archive_errno :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_error_string :: Ptr Archive -> IO CString
+foreign import ccall unsafe archive_format_name :: Ptr Archive -> IO CString
+foreign import ccall unsafe archive_format :: Ptr Archive -> IO ArchiveFormat
+foreign import ccall unsafe archive_clear_error :: Ptr Archive -> IO ()
+foreign import ccall unsafe archive_set_error :: Ptr Archive -> CInt -> CString -> IO () -- TODO: variadic lol
+foreign import ccall unsafe archive_copy_error :: Ptr Archive -> Ptr Archive -> IO ()
+foreign import ccall unsafe archive_file_count :: Ptr Archive -> IO CInt
+
+foreign import ccall unsafe archive_match_new :: Ptr Archive
+foreign import ccall unsafe archive_match_free :: Ptr Archive -> IO ArchiveError
+foreign import ccall unsafe archive_match_excluded :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_match_path_excluded :: Ptr Archive -> Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_match_exclude_pattern :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_match_exclude_pattern_w :: Ptr Archive -> CWString -> IO ArchiveError
+foreign import ccall unsafe archive_match_exclude_pattern_from_file :: Ptr Archive -> CString -> CInt -> IO ArchiveError
+foreign import ccall unsafe archive_match_exclude_pattern_from_file_w :: Ptr Archive -> CWString -> CInt -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_pattern :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_pattern_w :: Ptr Archive -> CWString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_pattern_from_file :: Ptr Archive -> CString -> CInt -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_pattern_from_file_w :: Ptr Archive -> CString -> CInt -> IO ArchiveError
+foreign import ccall unsafe archive_match_path_unmatched_inclusions :: Ptr Archive -> IO CInt
+foreign import ccall unsafe archive_match_path_unmatched_inclusions_next :: Ptr Archive -> Ptr CString -> IO ArchiveError
+foreign import ccall unsafe archive_match_path_unmatched_inclusions_next_w :: Ptr Archive -> Ptr CWString -> IO ArchiveError
+foreign import ccall unsafe archive_match_time_excluded :: Ptr Archive -> Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_match_include_time :: Ptr Archive -> TimeFlag -> CTime -> CLong -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_date :: Ptr Archive -> TimeFlag -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_date_w :: Ptr Archive -> TimeFlag -> CWString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_file_time :: Ptr Archive -> TimeFlag -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_file_time_w :: Ptr Archive -> TimeFlag -> CWString -> IO ArchiveError
+foreign import ccall unsafe archive_match_exclude_entry :: Ptr Archive -> TimeFlag -> Ptr ArchiveEntry -> IO ArchiveError
+foreign import ccall unsafe archive_match_owner_excluded :: Ptr Archive -> Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_match_include_gid :: Ptr Archive -> Id -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_uid :: Ptr Archive -> Id -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_uname :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_uname_w :: Ptr Archive -> CWString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_gname :: Ptr Archive -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_match_include_gname_w :: Ptr Archive -> CWString -> IO ArchiveError
+
+#include <archive.h>
+
+archiveVersionNumber :: Int
+archiveVersionNumber = {# const ARCHIVE_VERSION_NUMBER #}
+
+archiveVersionOnlyString :: String
+archiveVersionOnlyString = {# const ARCHIVE_VERSION_ONLY_STRING #}
+
+archiveVersionString :: String
+archiveVersionString = {# const ARCHIVE_VERSION_STRING #}
+
+-- TODO: make ArchiveError a sum type
+archiveOk :: ArchiveError
+archiveOk = ArchiveError {# const ARCHIVE_OK #}
+
+archiveEOF :: ArchiveError
+archiveEOF = ArchiveError {# const ARCHIVE_EOF #}
+
+archiveRetry :: ArchiveError
+archiveRetry = ArchiveError ({# const ARCHIVE_RETRY #})
+
+archiveWarn :: ArchiveError
+archiveWarn = ArchiveError ({# const ARCHIVE_WARN #})
+
+archiveFailed :: ArchiveError
+archiveFailed = ArchiveError ({# const ARCHIVE_FAILED #})
+
+archiveFatal :: ArchiveError
+archiveFatal = ArchiveError ({# const ARCHIVE_FATAL #})
+
+-- Archive filter
+archiveFilterNone :: ArchiveFilter
+archiveFilterNone = ArchiveFilter {# const ARCHIVE_FILTER_NONE #}
+
+archiveFilterGzip :: ArchiveFilter
+archiveFilterGzip = ArchiveFilter {# const ARCHIVE_FILTER_GZIP #}
+
+archiveFilterBzip2 :: ArchiveFilter
+archiveFilterBzip2 = ArchiveFilter {# const ARCHIVE_FILTER_BZIP2 #}
+
+archiveFilterCompress :: ArchiveFilter
+archiveFilterCompress = ArchiveFilter {# const ARCHIVE_FILTER_COMPRESS #}
+
+archiveFilterProgram :: ArchiveFilter
+archiveFilterProgram = ArchiveFilter {# const ARCHIVE_FILTER_PROGRAM #}
+
+archiveFilterLzma :: ArchiveFilter
+archiveFilterLzma = ArchiveFilter {# const ARCHIVE_FILTER_LZMA #}
+
+archiveFilterXz :: ArchiveFilter
+archiveFilterXz = ArchiveFilter {# const ARCHIVE_FILTER_XZ #}
+
+archiveFilterUu :: ArchiveFilter
+archiveFilterUu = ArchiveFilter {# const ARCHIVE_FILTER_UU #}
+
+archiveFilterRpm :: ArchiveFilter
+archiveFilterRpm = ArchiveFilter {# const ARCHIVE_FILTER_RPM #}
+
+archiveFilterLzip :: ArchiveFilter
+archiveFilterLzip = ArchiveFilter {# const ARCHIVE_FILTER_LZIP #}
+
+archiveFilterLrzip :: ArchiveFilter
+archiveFilterLrzip = ArchiveFilter {# const ARCHIVE_FILTER_LRZIP #}
+
+archiveFilterLzop :: ArchiveFilter
+archiveFilterLzop = ArchiveFilter {# const ARCHIVE_FILTER_LZOP #}
+
+archiveFilterGrzip :: ArchiveFilter
+archiveFilterGrzip = ArchiveFilter {# const ARCHIVE_FILTER_GRZIP #}
+
+archiveFilterLz4 :: ArchiveFilter
+archiveFilterLz4 = ArchiveFilter {# const ARCHIVE_FILTER_LZ4 #}
+
+-- Extraction flags
+archiveExtractOwner :: Flags
+archiveExtractOwner = Flags {# const ARCHIVE_EXTRACT_OWNER #}
+
+archiveExtractPerm :: Flags
+archiveExtractPerm = Flags {# const ARCHIVE_EXTRACT_PERM #}
+
+archiveExtractTime :: Flags
+archiveExtractTime = Flags {# const ARCHIVE_EXTRACT_TIME #}
+
+archiveExtractNoOverwrite :: Flags
+archiveExtractNoOverwrite = Flags {# const ARCHIVE_EXTRACT_NO_OVERWRITE #}
+
+archiveExtractUnlink :: Flags
+archiveExtractUnlink = Flags {# const ARCHIVE_EXTRACT_UNLINK #}
+
+archiveExtractACL :: Flags
+archiveExtractACL = Flags {# const ARCHIVE_EXTRACT_ACL #}
+
+archiveExtractFFlags :: Flags
+archiveExtractFFlags = Flags {# const ARCHIVE_EXTRACT_FFLAGS #}
+
+archiveExtractXattr :: Flags
+archiveExtractXattr = Flags {# const ARCHIVE_EXTRACT_XATTR #}
+
+archiveExtractSecureSymlinks :: Flags
+archiveExtractSecureSymlinks = Flags {# const ARCHIVE_EXTRACT_SECURE_SYMLINKS #}
+
+archiveExtractSecureNoDotDot :: Flags
+archiveExtractSecureNoDotDot = Flags {# const ARCHIVE_EXTRACT_SECURE_NODOTDOT #}
+
+archiveExtractNoAutodir :: Flags
+archiveExtractNoAutodir = Flags {# const ARCHIVE_EXTRACT_NO_AUTODIR #}
+
+-- archiveExtractNoOverwriteNewer :: Flags
+-- archiveExtractNoOverwriteNewer = Flags {# const ARCHIVE_NO_OVERWRITE_NEWER #}
+
+archiveExtractSparse :: Flags
+archiveExtractSparse = Flags {# const ARCHIVE_EXTRACT_SPARSE #}
+
+archiveExtractMacMetadata :: Flags
+archiveExtractMacMetadata = Flags {# const ARCHIVE_EXTRACT_MAC_METADATA #}
+
+archiveExtractNoHfsCompression :: Flags
+archiveExtractNoHfsCompression = Flags {# const ARCHIVE_EXTRACT_NO_HFS_COMPRESSION #}
+
+archiveExtractHfsCompressionForced :: Flags
+archiveExtractHfsCompressionForced = Flags {# const ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED #}
+
+archiveExtractSecureNoAbsolutePaths :: Flags
+archiveExtractSecureNoAbsolutePaths = Flags {# const ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS #}
+
+archiveExtractClearNoChangeFFlags :: Flags
+archiveExtractClearNoChangeFFlags = Flags {# const ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS #}
+
+archiveFormatCpio :: ArchiveFormat
+archiveFormatCpio = ArchiveFormat {# const ARCHIVE_FORMAT_CPIO #}
+
+archiveFormatShar :: ArchiveFormat
+archiveFormatShar = ArchiveFormat {# const ARCHIVE_FORMAT_SHAR #}
+
+archiveFormatTar :: ArchiveFormat
+archiveFormatTar = ArchiveFormat {# const ARCHIVE_FORMAT_TAR #}
+
+archiveFormatIso9660 :: ArchiveFormat
+archiveFormatIso9660 = ArchiveFormat {# const ARCHIVE_FORMAT_ISO9660 #}
+
+archiveFormatZip :: ArchiveFormat
+archiveFormatZip = ArchiveFormat {# const ARCHIVE_FORMAT_ZIP #}
+
+archiveFormatEmpty :: ArchiveFormat
+archiveFormatEmpty = ArchiveFormat {# const ARCHIVE_FORMAT_EMPTY #}
+
+archiveFormatAr :: ArchiveFormat
+archiveFormatAr = ArchiveFormat {# const ARCHIVE_FORMAT_AR #}
+
+archiveFormatMtree :: ArchiveFormat
+archiveFormatMtree = ArchiveFormat {# const ARCHIVE_FORMAT_MTREE #}
+
+archiveFormatRaw :: ArchiveFormat
+archiveFormatRaw = ArchiveFormat {# const ARCHIVE_FORMAT_RAW #}
+
+archiveFormatXar :: ArchiveFormat
+archiveFormatXar = ArchiveFormat {# const ARCHIVE_FORMAT_XAR #}
+
+archiveFormatLha :: ArchiveFormat
+archiveFormatLha = ArchiveFormat {# const ARCHIVE_FORMAT_LHA #}
+
+archiveFormatCab :: ArchiveFormat
+archiveFormatCab = ArchiveFormat {# const ARCHIVE_FORMAT_CAB #}
+
+archiveFormatRar :: ArchiveFormat
+archiveFormatRar = ArchiveFormat {# const ARCHIVE_FORMAT_RAR #}
+
+archiveFormat7zip :: ArchiveFormat
+archiveFormat7zip = ArchiveFormat {# const ARCHIVE_FORMAT_7ZIP #}
+
+archiveFormatWarc :: ArchiveFormat
+archiveFormatWarc = ArchiveFormat {# const ARCHIVE_FORMAT_WARC #}
+
+archiveReadHasEncryptedEntries :: Ptr Archive -> IO ArchiveEncryption
+archiveReadHasEncryptedEntries = fmap encryptionResult . archive_read_has_encrypted_entries
+
+encryptionResult :: CInt -> ArchiveEncryption
+encryptionResult 0                                                        = NoEncryption
+encryptionResult 1                                                        = HasEncryption
+encryptionResult ({# const ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED #}) = EncryptionUnsupported
+encryptionResult ({# const ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW #})   = EncryptionUnknown
+encryptionResult _                                                        = error "Should not happen."
+
+archiveReadFormatCapsNone :: ArchiveCapabilities
+archiveReadFormatCapsNone = ArchiveCapabilities {# const ARCHIVE_READ_FORMAT_CAPS_NONE #}
+
+(<<) :: Bits a => a -> Int -> a
+m << n = m `shift` n
+
+archiveReadFormatCapsEncryptData :: ArchiveCapabilities
+archiveReadFormatCapsEncryptData = ArchiveCapabilities ({# const ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA #})
+
+archiveReadFormatCapsEncryptMetadata :: ArchiveCapabilities
+archiveReadFormatCapsEncryptMetadata = ArchiveCapabilities ({# const ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA #})
+
+archiveReadDiskCanDescend :: Ptr Archive -> IO Bool
+archiveReadDiskCanDescend = fmap intToBool . archive_read_disk_can_descend
+
+archiveReadDiskCurrentFilesystemIsSynthetic :: Ptr Archive -> IO Bool
+archiveReadDiskCurrentFilesystemIsSynthetic = fmap intToBool . archive_read_disk_current_filesystem_is_synthetic
+
+archiveReadDiskCurrentFilesystemIsRemote :: Ptr Archive -> IO Bool
+archiveReadDiskCurrentFilesystemIsRemote = fmap intToBool . archive_read_disk_current_filesystem_is_remote
+
+archiveReadDiskRestoreATime :: ReadDiskFlags
+archiveReadDiskRestoreATime = ReadDiskFlags {# const ARCHIVE_READDISK_RESTORE_ATIME #}
+
+archiveReadDiskHonorNoDump :: ReadDiskFlags
+archiveReadDiskHonorNoDump = ReadDiskFlags {# const ARCHIVE_READDISK_HONOR_NODUMP #}
+
+archiveReadDiskMacCopyFile :: ReadDiskFlags
+archiveReadDiskMacCopyFile = ReadDiskFlags {# const ARCHIVE_READDISK_MAC_COPYFILE #}
+
+archiveReadDiskNoTraverseMounts :: ReadDiskFlags
+archiveReadDiskNoTraverseMounts = ReadDiskFlags {# const ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS #}
+
+archiveReadDiskNoXattr :: ReadDiskFlags
+archiveReadDiskNoXattr = ReadDiskFlags {# const ARCHIVE_READDISK_NO_XATTR #}
+
+-- archiveReadDiskNoAcl :: ReadDiskFlags
+-- archiveReadDiskNoAcl = ReadDiskFlags {# const ARCHIVE_READDISK_NO_ACL #}
+
+-- archiveReadDiskNoFFlags :: ReadDiskFlags
+-- archiveReadDiskNoFFlags = ReadDiskFlags {# const ARCHIVE_READDISK_NO_FFLAGS #}
+
+archiveMatchExcluded :: Ptr Archive -> IO Bool
+archiveMatchExcluded = fmap intToBool . archive_match_excluded
+
+archiveMatchPathExcluded :: Ptr Archive -> Ptr ArchiveEntry -> IO Bool
+archiveMatchPathExcluded = fmap intToBool .* archive_match_path_excluded
+
+archiveMatchExcludePatternFromFile :: Ptr Archive -> CString -> Bool -> IO ArchiveError
+archiveMatchExcludePatternFromFile a str b = archive_match_exclude_pattern_from_file a str (boolToInt b)
+
+archiveMatchExcludePatternFromFileW :: Ptr Archive -> CWString -> Bool -> IO ArchiveError
+archiveMatchExcludePatternFromFileW a str b = archive_match_exclude_pattern_from_file_w a str (boolToInt b)
+
+archiveMatchIncludePatternFromFile :: Ptr Archive -> CString -> Bool -> IO ArchiveError
+archiveMatchIncludePatternFromFile a str b = archive_match_include_pattern_from_file a str (boolToInt b)
+
+archiveMatchIncludePatternFromFileW :: Ptr Archive -> CString -> Bool -> IO ArchiveError
+archiveMatchIncludePatternFromFileW a str b = archive_match_include_pattern_from_file_w a str (boolToInt b)
+
+archiveMatchTimeExcluded :: Ptr Archive -> Ptr ArchiveEntry -> IO Bool
+archiveMatchTimeExcluded = fmap intToBool .* archive_match_time_excluded
+
+archiveMatchMTime :: TimeFlag
+archiveMatchMTime = TimeFlag {# const ARCHIVE_MATCH_MTIME #}
+
+archiveMatchCTime :: TimeFlag
+archiveMatchCTime = TimeFlag {# const ARCHIVE_MATCH_CTIME #}
+
+archiveMatchNewer :: TimeFlag
+archiveMatchNewer = TimeFlag {# const ARCHIVE_MATCH_NEWER #}
+
+archiveMatchOlder :: TimeFlag
+archiveMatchOlder = TimeFlag {# const ARCHIVE_MATCH_OLDER #}
+
+archiveMatchEqual :: TimeFlag
+archiveMatchEqual = TimeFlag {# const ARCHIVE_MATCH_EQUAL #}
+
+archiveMatchOwnerExcluded :: Ptr Archive -> Ptr ArchiveEntry -> IO Bool
+archiveMatchOwnerExcluded = fmap intToBool .* archive_match_owner_excluded
diff --git a/src/Codec/Archive/Foreign/ArchiveEntry.chs b/src/Codec/Archive/Foreign/ArchiveEntry.chs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Archive/Foreign/ArchiveEntry.chs
@@ -0,0 +1,595 @@
+-- | Functions found in @archive_entry.h@
+module Codec.Archive.Foreign.ArchiveEntry ( -- * Direct bindings (entry)
+                                            archive_entry_clear
+                                          , archive_entry_clone
+                                          , archive_entry_new
+                                          , archive_entry_free
+                                          , archive_entry_new2
+                                          , archive_entry_atime
+                                          , archive_entry_atime_nsec
+                                          , archiveEntryATimeIsSet
+                                          , archive_entry_birthtime
+                                          , archive_entry_birthtime_nsec
+                                          , archiveEntryBirthtimeIsSet
+                                          , archive_entry_ctime
+                                          , archive_entry_ctime_nsec
+                                          , archiveEntryCTimeIsSet
+                                          , archive_entry_dev
+                                          , archiveEntryDevIsSet
+                                          , archive_entry_devminor
+                                          , archive_entry_devmajor
+                                          , archive_entry_fflags
+                                          , archive_entry_fflags_text
+                                          , archive_entry_filetype
+                                          , archive_entry_gid
+                                          , archive_entry_gname
+                                          , archive_entry_gname_utf8
+                                          , archive_entry_gname_w
+                                          , archive_entry_hardlink
+                                          , archive_entry_hardlink_utf8
+                                          , archive_entry_hardlink_w
+                                          , archive_entry_ino
+                                          , archive_entry_ino64
+                                          , archiveEntryInoIsSet
+                                          , archive_entry_mode
+                                          , archive_entry_mtime
+                                          , archive_entry_mtime_nsec
+                                          , archiveEntryMTimeIsSet
+                                          , archive_entry_nlink
+                                          , archive_entry_pathname
+                                          , archive_entry_pathname_utf8
+                                          , archive_entry_pathname_w
+                                          , archive_entry_perm
+                                          , archive_entry_rdev
+                                          , archive_entry_rdevmajor
+                                          , archive_entry_rdevminor
+                                          , archive_entry_sourcepath
+                                          , archive_entry_sourcepath_w
+                                          , archive_entry_size
+                                          , archiveEntrySizeIsSet
+                                          , archive_entry_strmode
+                                          , archive_entry_symlink
+                                          , archive_entry_symlink_w
+                                          , archive_entry_symlink_utf8
+                                          , archive_entry_uid
+                                          , archive_entry_uname
+                                          , archive_entry_uname_utf8
+                                          , archive_entry_uname_w
+                                          , archiveEntryIsDataEncrypted
+                                          , archiveEntryIsMetadataEncrypted
+                                          , archiveEntryIsEncrypted
+                                          , archive_entry_set_atime
+                                          , archive_entry_unset_atime
+                                          , archive_entry_set_birthtime
+                                          , archive_entry_unset_birthtime
+                                          , archive_entry_set_ctime
+                                          , archive_entry_unset_ctime
+                                          , archive_entry_set_dev
+                                          , archive_entry_set_devmajor
+                                          , archive_entry_set_devminor
+                                          , archive_entry_set_fflags
+                                          , archive_entry_copy_fflags_text
+                                          , archive_entry_copy_fflags_text_w
+                                          , archive_entry_set_filetype
+                                          , archive_entry_set_gid
+                                          , archive_entry_set_gname
+                                          , archive_entry_set_gname_utf8
+                                          , archive_entry_copy_gname
+                                          , archive_entry_copy_gname_w
+                                          , archiveEntryUpdateGNameUtf8
+                                          , archive_entry_set_hardlink
+                                          , archive_entry_set_hardlink_utf8
+                                          , archive_entry_copy_hardlink
+                                          , archive_entry_copy_hardlink_w
+                                          , archiveEntryUpdateHardlinkUtf8
+                                          , archive_entry_set_ino
+                                          , archive_entry_set_ino64
+                                          , archive_entry_set_link
+                                          , archive_entry_set_link_utf8
+                                          , archive_entry_copy_link
+                                          , archive_entry_copy_link_w
+                                          , archiveEntryUpdateLinkUtf8
+                                          , archive_entry_set_mode
+                                          , archive_entry_set_mtime
+                                          , archive_entry_unset_mtime
+                                          , archive_entry_set_nlink
+                                          , archive_entry_set_pathname
+                                          , archive_entry_set_pathname_utf8
+                                          , archive_entry_copy_pathname
+                                          , archive_entry_copy_pathname_w
+                                          , archiveEntryUpdatePathnameUtf8
+                                          , archive_entry_set_perm
+                                          , archive_entry_set_rdev
+                                          , archive_entry_set_rdevmajor
+                                          , archive_entry_set_rdevminor
+                                          , archive_entry_set_size
+                                          , archive_entry_unset_size
+                                          , archive_entry_copy_sourcepath
+                                          , archive_entry_copy_sourcepath_w
+                                          , archive_entry_set_symlink
+                                          , archive_entry_set_symlink_utf8
+                                          , archive_entry_copy_symlink
+                                          , archive_entry_copy_symlink_w
+                                          , archiveEntryUpdateSymlinkUtf8
+                                          , archive_entry_set_uid
+                                          , archive_entry_set_uname
+                                          , archive_entry_set_uname_utf8
+                                          , archive_entry_copy_uname
+                                          , archive_entry_copy_uname_w
+                                          , archiveEntryUpdateUNameUtf8
+                                          , archive_entry_stat
+                                          , archive_entry_copy_stat
+                                          , archive_entry_mac_metadata
+                                          , archive_entry_copy_mac_metadata
+                                          -- * ACL functions
+                                          , archive_entry_acl_add_entry
+                                          , archive_entry_acl_add_entry_w
+                                          , archive_entry_acl_reset
+                                          , archive_entry_acl_next
+                                          , archive_entry_acl_next_w
+                                          , archive_entry_acl_to_text
+                                          , archive_entry_acl_to_text_w
+                                          , archive_entry_acl_from_text
+                                          , archive_entry_acl_from_text_w
+                                          , archive_entry_acl_types
+                                          , archive_entry_count
+                                          -- * Xattr functions
+                                          , archive_entry_xattr_clear
+                                          , archive_entry_xattr_add_entry
+                                          , archive_entry_xattr_count
+                                          , archive_entry_xattr_reset
+                                          , archive_entry_xattr_next
+                                          -- * For sparse archives
+                                          , archive_entry_sparse_clear
+                                          , archive_entry_sparse_add_entry
+                                          , archive_entry_sparse_count
+                                          , archive_entry_sparse_reset
+                                          , archive_entry_sparse_next
+                                          -- * Link resolver
+                                          , archive_entry_linkresolver_new
+                                          , archive_entry_linkresolver_set_strategy
+                                          , archive_entry_linkresolver_free
+                                          , archive_entry_linkify
+                                          , archive_entry_partial_links
+                                          -- * ACL
+                                          , archive_entry_acl_clear
+                                          -- * File types
+                                          , regular
+                                          , symlink
+                                          , socket
+                                          , characterDevice
+                                          , blockDevice
+                                          , directory
+                                          , fifo
+                                          -- * ACL macros
+                                          , archiveEntryACLExecute
+                                          , archiveEntryACLWrite
+                                          , archiveEntryACLRead
+                                          , archiveEntryACLReadData
+                                          , archiveEntryACLListData
+                                          , archiveEntryACLWriteData
+                                          , archiveEntryACLAddFile
+                                          , archiveEntryACLAppendData
+                                          , archiveEntryACLAddSubdirectory
+                                          , archiveEntryACLReadNamedAttrs
+                                          , archiveEntryACLWriteNamedAttrs
+                                          , archiveEntryACLDeleteChild
+                                          , archiveEntryACLReadAttributes
+                                          , archiveEntryACLWriteAttributes
+                                          , archiveEntryACLDelete
+                                          , archiveEntryACLReadACL
+                                          , archiveEntryACLWriteACL
+                                          , archiveEntryACLWriteOwner
+                                          , archiveEntryACLSynchronize
+                                          , archiveEntryACLEntryFileInherit
+                                          , archiveEntryACLEntryDirectoryInherit
+                                          , archiveEntryACLEntryNoPropagateInherit
+                                          , archiveEntryACLEntryInheritOnly
+                                          , archiveEntryACLEntrySuccessfulAccess
+                                          , archiveEntryACLEntryFailedAccess
+                                          , archiveEntryACLTypeAccess
+                                          , archiveEntryACLTypeDefault
+                                          , archiveEntryACLTypeAllow
+                                          , archiveEntryACLTypeDeny
+                                          , archiveEntryACLTypeAudit
+                                          , archiveEntryACLTypeAlarm
+                                          , archiveEntryACLUser
+                                          , archiveEntryACLUserObj
+                                          , archiveEntryACLGroup
+                                          , archiveEntryACLGroupObj
+                                          , archiveEntryACLMask
+                                          , archiveEntryACLOther
+                                          , archiveEntryACLEveryone
+                                          , archiveEntryACLStyleExtraID
+                                          , archiveEntryACLStyleMarkDefault
+                                          -- * Abstract types
+                                          , ArchiveEntry
+                                          , Stat
+                                          , LinkResolver
+                                          -- * Lower-level API types
+                                          , FileType
+                                          , EntryACL
+                                          ) where
+
+import Codec.Archive.Foreign.Common
+import Codec.Archive.Types
+import Control.Composition ((.*))
+import Data.Int (Int64)
+import Data.Word (Word64)
+import Foreign.C.String
+import Foreign.C.Types
+import Foreign.Ptr (Ptr)
+import System.Posix.Types (CMode (..))
+
+#include <archive_entry.h>
+
+-- Archive entry
+foreign import ccall unsafe archive_entry_clear :: Ptr ArchiveEntry -> IO (Ptr ArchiveEntry)
+foreign import ccall unsafe archive_entry_clone :: Ptr ArchiveEntry -> IO (Ptr ArchiveEntry)
+foreign import ccall unsafe archive_entry_free :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_new :: IO (Ptr ArchiveEntry)
+foreign import ccall unsafe archive_entry_new2 :: Ptr ArchiveEntry -> IO (Ptr ArchiveEntry)
+
+foreign import ccall unsafe archive_entry_atime :: Ptr ArchiveEntry -> IO CTime
+foreign import ccall unsafe archive_entry_atime_nsec :: Ptr ArchiveEntry -> IO CLong
+foreign import ccall unsafe archive_entry_atime_is_set :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_birthtime :: Ptr ArchiveEntry -> IO CTime
+foreign import ccall unsafe archive_entry_birthtime_nsec :: Ptr ArchiveEntry -> IO CLong
+foreign import ccall unsafe archive_entry_birthtime_is_set :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_ctime :: Ptr ArchiveEntry -> IO CTime
+foreign import ccall unsafe archive_entry_ctime_nsec :: Ptr ArchiveEntry -> IO CLong
+foreign import ccall unsafe archive_entry_ctime_is_set :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_dev :: Ptr ArchiveEntry -> IO Word64
+foreign import ccall unsafe archive_entry_dev_is_set :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_devmajor :: Ptr ArchiveEntry -> IO Word64
+foreign import ccall unsafe archive_entry_devminor :: Ptr ArchiveEntry -> IO Word64
+foreign import ccall unsafe archive_entry_filetype :: Ptr ArchiveEntry -> IO FileType
+foreign import ccall unsafe archive_entry_fflags :: Ptr ArchiveEntry -> CULong -> CULong -> IO ()
+foreign import ccall unsafe archive_entry_fflags_text :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_gid :: Ptr ArchiveEntry -> IO Id
+foreign import ccall unsafe archive_entry_gname :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_gname_utf8 :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_gname_w :: Ptr ArchiveEntry -> IO CWString
+foreign import ccall unsafe archive_entry_hardlink :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_hardlink_utf8 :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_hardlink_w :: Ptr ArchiveEntry -> IO CWString
+foreign import ccall unsafe archive_entry_ino :: Ptr ArchiveEntry -> IO Int64
+foreign import ccall unsafe archive_entry_ino64 :: Ptr ArchiveEntry -> IO Int64
+foreign import ccall unsafe archive_entry_ino_is_set :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_mode :: Ptr ArchiveEntry -> IO CMode
+foreign import ccall unsafe archive_entry_mtime :: Ptr ArchiveEntry -> IO CTime
+foreign import ccall unsafe archive_entry_mtime_nsec :: Ptr ArchiveEntry -> IO CLong
+foreign import ccall unsafe archive_entry_mtime_is_set :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_nlink :: Ptr ArchiveEntry -> IO CUInt
+foreign import ccall unsafe archive_entry_pathname :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_pathname_utf8 :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_pathname_w :: Ptr ArchiveEntry -> IO CWString
+foreign import ccall unsafe archive_entry_perm :: Ptr ArchiveEntry -> IO CMode
+foreign import ccall unsafe archive_entry_rdev :: Ptr ArchiveEntry -> IO Word64
+foreign import ccall unsafe archive_entry_rdevmajor :: Ptr ArchiveEntry -> IO Word64
+foreign import ccall unsafe archive_entry_rdevminor :: Ptr ArchiveEntry -> IO Word64
+foreign import ccall unsafe archive_entry_sourcepath :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_sourcepath_w :: Ptr ArchiveEntry -> IO CWString
+foreign import ccall unsafe archive_entry_size :: Ptr ArchiveEntry -> IO Int64
+foreign import ccall unsafe archive_entry_size_is_set :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_strmode :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_symlink :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_symlink_utf8 :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_symlink_w :: Ptr ArchiveEntry -> IO CWString
+foreign import ccall unsafe archive_entry_uid :: Ptr ArchiveEntry -> IO Id
+foreign import ccall unsafe archive_entry_uname :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_uname_utf8 :: Ptr ArchiveEntry -> IO CString
+foreign import ccall unsafe archive_entry_uname_w :: Ptr ArchiveEntry -> IO CWString
+foreign import ccall unsafe archive_entry_is_data_encrypted :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_is_metadata_encrypted :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_is_encrypted :: Ptr ArchiveEntry -> IO CInt
+
+foreign import ccall unsafe archive_entry_set_atime :: Ptr ArchiveEntry -> CTime -> CLong -> IO ()
+foreign import ccall unsafe archive_entry_unset_atime :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_set_birthtime :: Ptr ArchiveEntry -> CTime -> CLong -> IO ()
+foreign import ccall unsafe archive_entry_unset_birthtime :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_set_ctime :: Ptr ArchiveEntry -> CTime -> CLong -> IO ()
+foreign import ccall unsafe archive_entry_unset_ctime :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_set_dev :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_devmajor :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_devminor :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_filetype :: Ptr ArchiveEntry -> FileType -> IO ()
+foreign import ccall unsafe archive_entry_set_fflags :: Ptr ArchiveEntry -> CULong -> CULong -> IO ()
+foreign import ccall unsafe archive_entry_copy_fflags_text :: Ptr ArchiveEntry -> CString -> IO CString
+foreign import ccall unsafe archive_entry_copy_fflags_text_w :: Ptr ArchiveEntry -> CWString -> IO CWString
+foreign import ccall unsafe archive_entry_set_gid :: Ptr ArchiveEntry -> Id -> IO ()
+foreign import ccall unsafe archive_entry_set_gname :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_set_gname_utf8 :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_gname :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_gname_w :: Ptr ArchiveEntry -> CWString -> IO ()
+foreign import ccall unsafe archive_entry_update_gname_utf8 :: Ptr ArchiveEntry -> CString -> IO CInt
+foreign import ccall unsafe archive_entry_set_hardlink :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_set_hardlink_utf8 :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_hardlink :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_hardlink_w :: Ptr ArchiveEntry -> CWString -> IO ()
+foreign import ccall unsafe archive_entry_update_hardlink_utf8 :: Ptr ArchiveEntry -> CString -> IO CInt
+foreign import ccall unsafe archive_entry_set_ino :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_ino64 :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_link :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_set_link_utf8 :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_link :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_link_w :: Ptr ArchiveEntry -> CWString -> IO ()
+foreign import ccall unsafe archive_entry_update_link_utf8 :: Ptr ArchiveEntry -> CString -> IO CInt
+foreign import ccall unsafe archive_entry_set_mode :: Ptr ArchiveEntry -> CMode -> IO ()
+foreign import ccall unsafe archive_entry_set_mtime :: Ptr ArchiveEntry -> CTime -> CLong -> IO ()
+foreign import ccall unsafe archive_entry_unset_mtime :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_set_nlink :: Ptr ArchiveEntry -> CUInt -> IO ()
+foreign import ccall unsafe archive_entry_set_pathname :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_set_pathname_utf8 :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_pathname :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_pathname_w :: Ptr ArchiveEntry -> CWString -> IO ()
+foreign import ccall unsafe archive_entry_update_pathname_utf8 :: Ptr ArchiveEntry -> CString -> IO CInt
+foreign import ccall unsafe archive_entry_set_perm :: Ptr ArchiveEntry -> CMode -> IO ()
+foreign import ccall unsafe archive_entry_set_rdev :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_rdevmajor :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_rdevminor :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_set_size :: Ptr ArchiveEntry -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_unset_size :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_copy_sourcepath :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_sourcepath_w :: Ptr ArchiveEntry -> CWString -> IO ()
+foreign import ccall unsafe archive_entry_set_symlink :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_set_symlink_utf8 :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_symlink :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_symlink_w :: Ptr ArchiveEntry -> CWString -> IO ()
+foreign import ccall unsafe archive_entry_update_symlink_utf8 :: Ptr ArchiveEntry -> CString -> IO CInt
+foreign import ccall unsafe archive_entry_set_uid :: Ptr ArchiveEntry -> Id -> IO ()
+foreign import ccall unsafe archive_entry_set_uname :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_set_uname_utf8 :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_uname :: Ptr ArchiveEntry -> CString -> IO ()
+foreign import ccall unsafe archive_entry_copy_uname_w :: Ptr ArchiveEntry -> CWString -> IO ()
+foreign import ccall unsafe archive_entry_update_uname_utf8 :: Ptr ArchiveEntry -> CString -> IO CInt
+foreign import ccall unsafe archive_entry_stat :: Ptr ArchiveEntry -> IO (Ptr Stat)
+foreign import ccall unsafe archive_entry_copy_stat :: Ptr ArchiveEntry -> Ptr Stat -> IO ()
+foreign import ccall unsafe archive_entry_mac_metadata :: Ptr ArchiveEntry -> Ptr CSize -> IO (Ptr a)
+foreign import ccall unsafe archive_entry_copy_mac_metadata :: Ptr ArchiveEntry -> Ptr a -> CSize -> IO ()
+
+foreign import ccall unsafe archive_entry_acl_clear :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_acl_add_entry :: Ptr ArchiveEntry -> EntryACL -> EntryACL -> EntryACL -> CInt -> CString -> IO ArchiveError
+foreign import ccall unsafe archive_entry_acl_add_entry_w :: Ptr ArchiveEntry -> EntryACL -> EntryACL -> EntryACL -> CInt -> CWString -> IO ArchiveError
+foreign import ccall unsafe archive_entry_acl_reset :: Ptr ArchiveEntry -> EntryACL -> IO CInt
+foreign import ccall unsafe archive_entry_acl_next :: Ptr ArchiveEntry -> EntryACL -> EntryACL -> EntryACL -> EntryACL -> CInt -> Ptr CString -> IO ArchiveError
+foreign import ccall unsafe archive_entry_acl_next_w :: Ptr ArchiveEntry -> EntryACL -> EntryACL -> EntryACL -> EntryACL -> CInt -> Ptr CWString -> IO ArchiveError
+
+foreign import ccall unsafe archive_entry_acl_to_text_w :: Ptr ArchiveEntry -> CSize -> EntryACL -> IO CWString
+foreign import ccall unsafe archive_entry_acl_to_text :: Ptr ArchiveEntry -> CSize -> EntryACL -> IO CString
+foreign import ccall unsafe archive_entry_acl_from_text :: Ptr ArchiveEntry -> CString -> EntryACL -> IO ArchiveError
+foreign import ccall unsafe archive_entry_acl_from_text_w :: Ptr ArchiveEntry -> CWString -> EntryACL -> IO ArchiveError
+foreign import ccall unsafe archive_entry_acl_types :: Ptr ArchiveEntry -> IO EntryACL
+foreign import ccall unsafe archive_entry_count :: Ptr ArchiveEntry -> EntryACL -> IO CInt
+
+-- don't bother with archive_entry_acl
+
+foreign import ccall unsafe archive_entry_xattr_clear :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_xattr_add_entry :: Ptr ArchiveEntry -> CString -> Ptr a -> CSize -> IO ()
+foreign import ccall unsafe archive_entry_xattr_count :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_xattr_reset :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_xattr_next :: Ptr ArchiveEntry -> Ptr CString -> Ptr (Ptr a) -> Ptr CSize -> IO ArchiveError
+-- TODO: higher level archiveEntryXattrList?
+
+foreign import ccall unsafe archive_entry_sparse_clear :: Ptr ArchiveEntry -> IO ()
+foreign import ccall unsafe archive_entry_sparse_add_entry :: Ptr ArchiveEntry -> Int64 -> Int64 -> IO ()
+foreign import ccall unsafe archive_entry_sparse_count :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_sparse_reset :: Ptr ArchiveEntry -> IO CInt
+foreign import ccall unsafe archive_entry_sparse_next :: Ptr ArchiveEntry -> Ptr Int64 -> Ptr Int64 -> IO ArchiveError
+
+foreign import ccall unsafe archive_entry_linkresolver_new :: Ptr LinkResolver
+foreign import ccall unsafe archive_entry_linkresolver_set_strategy :: Ptr LinkResolver -> ArchiveFormat -> IO ()
+foreign import ccall unsafe archive_entry_linkresolver_free :: Ptr LinkResolver -> IO ()
+foreign import ccall unsafe archive_entry_linkify :: Ptr LinkResolver -> Ptr (Ptr ArchiveEntry) -> Ptr (Ptr ArchiveEntry) -> IO ()
+foreign import ccall unsafe archive_entry_partial_links :: Ptr LinkResolver -> Ptr CUInt -> IO (Ptr ArchiveEntry)
+
+-- stupid function to work around some annoying C quirk
+mode_t :: Integer -> FileType
+mode_t = FileType . fromIntegral . asOctal
+
+-- converts 0020000 to 16384 etc.
+asOctal :: Integral a => a -> a
+asOctal n | n < 10 = n
+          | otherwise = 8 * asOctal (n `div` 10) + n `mod` 10
+
+-- filetype
+regular :: FileType
+regular = {# const AE_IFREG #}
+
+symlink :: FileType
+symlink = {# const AE_IFLNK #}
+
+socket :: FileType
+socket = {# const AE_IFSOCK #}
+
+characterDevice :: FileType
+characterDevice = {# const AE_IFCHR #}
+
+blockDevice :: FileType
+blockDevice = {# const AE_IFBLK #}
+
+directory :: FileType
+directory = {# const AE_IFDIR #}
+
+fifo :: FileType
+fifo = {# const AE_IFIFO #}
+
+archiveEntryATimeIsSet :: Ptr ArchiveEntry -> IO Bool
+archiveEntryATimeIsSet = fmap intToBool . archive_entry_atime_is_set
+
+archiveEntryBirthtimeIsSet :: Ptr ArchiveEntry -> IO Bool
+archiveEntryBirthtimeIsSet = fmap intToBool . archive_entry_birthtime_is_set
+
+archiveEntryCTimeIsSet :: Ptr ArchiveEntry -> IO Bool
+archiveEntryCTimeIsSet = fmap intToBool . archive_entry_ctime_is_set
+
+archiveEntryDevIsSet :: Ptr ArchiveEntry -> IO Bool
+archiveEntryDevIsSet = fmap intToBool . archive_entry_dev_is_set
+
+archiveEntryInoIsSet :: Ptr ArchiveEntry -> IO Bool
+archiveEntryInoIsSet = fmap intToBool . archive_entry_ino_is_set
+
+archiveEntryMTimeIsSet :: Ptr ArchiveEntry -> IO Bool
+archiveEntryMTimeIsSet = fmap intToBool . archive_entry_mtime_is_set
+
+archiveEntrySizeIsSet :: Ptr ArchiveEntry -> IO Bool
+archiveEntrySizeIsSet = fmap intToBool . archive_entry_size_is_set
+
+archiveEntryIsDataEncrypted :: Ptr ArchiveEntry -> IO Bool
+archiveEntryIsDataEncrypted = fmap intToBool . archive_entry_is_data_encrypted
+
+archiveEntryIsMetadataEncrypted :: Ptr ArchiveEntry -> IO Bool
+archiveEntryIsMetadataEncrypted = fmap intToBool . archive_entry_is_metadata_encrypted
+
+archiveEntryIsEncrypted :: Ptr ArchiveEntry -> IO Bool
+archiveEntryIsEncrypted = fmap intToBool . archive_entry_is_encrypted
+
+archiveEntryUpdateGNameUtf8 :: Ptr ArchiveEntry -> CString -> IO Bool
+archiveEntryUpdateGNameUtf8 = fmap intToBool .* archive_entry_update_gname_utf8
+
+archiveEntryUpdateHardlinkUtf8 :: Ptr ArchiveEntry -> CString -> IO Bool
+archiveEntryUpdateHardlinkUtf8 = fmap intToBool .* archive_entry_update_hardlink_utf8
+
+archiveEntryUpdateLinkUtf8 :: Ptr ArchiveEntry -> CString -> IO Bool
+archiveEntryUpdateLinkUtf8 = fmap intToBool .* archive_entry_update_link_utf8
+
+archiveEntryUpdatePathnameUtf8 :: Ptr ArchiveEntry -> CString -> IO Bool
+archiveEntryUpdatePathnameUtf8 = fmap intToBool .* archive_entry_update_pathname_utf8
+
+archiveEntryUpdateSymlinkUtf8 :: Ptr ArchiveEntry -> CString -> IO Bool
+archiveEntryUpdateSymlinkUtf8 = fmap intToBool .* archive_entry_update_symlink_utf8
+
+archiveEntryUpdateUNameUtf8 :: Ptr ArchiveEntry -> CString -> IO Bool
+archiveEntryUpdateUNameUtf8 = fmap intToBool .* archive_entry_update_uname_utf8
+
+archiveEntryACLExecute :: EntryACL
+archiveEntryACLExecute = EntryACL {# const ARCHIVE_ENTRY_ACL_EXECUTE #}
+
+archiveEntryACLWrite :: EntryACL
+archiveEntryACLWrite = EntryACL {# const ARCHIVE_ENTRY_ACL_WRITE #}
+
+archiveEntryACLRead :: EntryACL
+archiveEntryACLRead = EntryACL {# const ARCHIVE_ENTRY_ACL_READ #}
+
+archiveEntryACLReadData :: EntryACL
+archiveEntryACLReadData = EntryACL {# const ARCHIVE_ENTRY_ACL_READ_DATA #}
+
+archiveEntryACLListData :: EntryACL
+archiveEntryACLListData = EntryACL {# const ARCHIVE_ENTRY_ACL_LIST_DIRECTORY #}
+
+archiveEntryACLWriteData :: EntryACL
+archiveEntryACLWriteData = EntryACL {# const ARCHIVE_ENTRY_ACL_WRITE_DATA #}
+
+archiveEntryACLAddFile :: EntryACL
+archiveEntryACLAddFile = EntryACL {# const ARCHIVE_ENTRY_ACL_ADD_FILE #}
+
+archiveEntryACLAppendData :: EntryACL
+archiveEntryACLAppendData = EntryACL {# const ARCHIVE_ENTRY_ACL_APPEND_DATA #}
+
+archiveEntryACLAddSubdirectory :: EntryACL
+archiveEntryACLAddSubdirectory = EntryACL {# const ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY #}
+
+archiveEntryACLReadNamedAttrs :: EntryACL
+archiveEntryACLReadNamedAttrs = EntryACL {# const ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS #}
+
+archiveEntryACLWriteNamedAttrs :: EntryACL
+archiveEntryACLWriteNamedAttrs = EntryACL {# const ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS #}
+
+archiveEntryACLDeleteChild :: EntryACL
+archiveEntryACLDeleteChild = EntryACL {# const ARCHIVE_ENTRY_ACL_DELETE_CHILD #}
+
+archiveEntryACLReadAttributes :: EntryACL
+archiveEntryACLReadAttributes = EntryACL {# const ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES #}
+
+archiveEntryACLWriteAttributes :: EntryACL
+archiveEntryACLWriteAttributes = EntryACL {# const ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES #}
+
+archiveEntryACLDelete :: EntryACL
+archiveEntryACLDelete = EntryACL {# const ARCHIVE_ENTRY_ACL_DELETE #}
+
+archiveEntryACLReadACL :: EntryACL
+archiveEntryACLReadACL = EntryACL {# const ARCHIVE_ENTRY_ACL_READ_ACL #}
+
+archiveEntryACLWriteACL :: EntryACL
+archiveEntryACLWriteACL = EntryACL {# const ARCHIVE_ENTRY_ACL_WRITE_ACL #}
+
+archiveEntryACLWriteOwner :: EntryACL
+archiveEntryACLWriteOwner = EntryACL {# const ARCHIVE_ENTRY_ACL_WRITE_OWNER #}
+
+archiveEntryACLSynchronize :: EntryACL
+archiveEntryACLSynchronize = EntryACL {# const ARCHIVE_ENTRY_ACL_SYNCHRONIZE #}
+
+-- archiveEntryACLEntryInherited :: EntryACL
+-- archiveEntryACLEntryInherited = EntryACL {# const ARCHIVE_ENTRY_ACL_ENTRY_INHERITED #}
+
+archiveEntryACLEntryFileInherit :: EntryACL
+archiveEntryACLEntryFileInherit = EntryACL {# const ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT #}
+
+archiveEntryACLEntryDirectoryInherit :: EntryACL
+archiveEntryACLEntryDirectoryInherit = EntryACL {# const ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT #}
+
+archiveEntryACLEntryNoPropagateInherit :: EntryACL
+archiveEntryACLEntryNoPropagateInherit = EntryACL {# const ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT #}
+
+archiveEntryACLEntryInheritOnly :: EntryACL
+archiveEntryACLEntryInheritOnly = EntryACL {# const ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY #}
+
+archiveEntryACLEntrySuccessfulAccess :: EntryACL
+archiveEntryACLEntrySuccessfulAccess = EntryACL {# const ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS #}
+
+archiveEntryACLEntryFailedAccess :: EntryACL
+archiveEntryACLEntryFailedAccess = EntryACL {# const ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS #}
+
+archiveEntryACLTypeAccess :: EntryACL
+archiveEntryACLTypeAccess = EntryACL {# const ARCHIVE_ENTRY_ACL_TYPE_ACCESS #}
+
+archiveEntryACLTypeDefault :: EntryACL
+archiveEntryACLTypeDefault = EntryACL {# const ARCHIVE_ENTRY_ACL_TYPE_DEFAULT #}
+
+archiveEntryACLTypeAllow :: EntryACL
+archiveEntryACLTypeAllow = EntryACL {# const ARCHIVE_ENTRY_ACL_TYPE_ALLOW #}
+
+archiveEntryACLTypeDeny :: EntryACL
+archiveEntryACLTypeDeny = EntryACL {# const ARCHIVE_ENTRY_ACL_TYPE_DENY #}
+
+archiveEntryACLTypeAudit :: EntryACL
+archiveEntryACLTypeAudit = EntryACL {# const ARCHIVE_ENTRY_ACL_TYPE_AUDIT #}
+
+archiveEntryACLTypeAlarm :: EntryACL
+archiveEntryACLTypeAlarm = EntryACL {# const ARCHIVE_ENTRY_ACL_TYPE_ALARM #}
+
+archiveEntryACLUser :: EntryACL
+archiveEntryACLUser = EntryACL {# const ARCHIVE_ENTRY_ACL_USER #}
+
+archiveEntryACLUserObj :: EntryACL
+archiveEntryACLUserObj = EntryACL {# const ARCHIVE_ENTRY_ACL_USER_OBJ #}
+
+archiveEntryACLGroup :: EntryACL
+archiveEntryACLGroup = EntryACL {# const ARCHIVE_ENTRY_ACL_GROUP #}
+
+archiveEntryACLGroupObj :: EntryACL
+archiveEntryACLGroupObj = EntryACL {# const ARCHIVE_ENTRY_ACL_GROUP_OBJ #}
+
+archiveEntryACLMask :: EntryACL
+archiveEntryACLMask = EntryACL {# const ARCHIVE_ENTRY_ACL_MASK #}
+
+archiveEntryACLOther :: EntryACL
+archiveEntryACLOther = EntryACL {# const ARCHIVE_ENTRY_ACL_OTHER #}
+
+archiveEntryACLEveryone :: EntryACL
+archiveEntryACLEveryone = EntryACL {# const ARCHIVE_ENTRY_ACL_EVERYONE #}
+
+archiveEntryACLStyleExtraID :: EntryACL
+archiveEntryACLStyleExtraID = EntryACL {# const ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID #}
+
+archiveEntryACLStyleMarkDefault :: EntryACL
+archiveEntryACLStyleMarkDefault = EntryACL {# const ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT #}
+
+-- archiveEntryACLStyleSolaris :: EntryACL
+-- archiveEntryACLStyleSolaris = EntryACL {# const ARCHIVE_ENTRY_ACL_STYLE_SOLARIS #}
+
+-- archiveEntryACLStyleSeparatorComma :: EntryACL
+-- archiveEntryACLStyleSeparatorComma = EntryACL {# const ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA #}
+
+-- archiveEntryACLStyleCompact :: EntryACL
+-- archiveEntryACLStyleCompact = EntryACL {# const ARCHIVE_ENTRY_ACL_STYLE_COMPACT #}
diff --git a/src/Codec/Archive/Foreign/Common.hs b/src/Codec/Archive/Foreign/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Archive/Foreign/Common.hs
@@ -0,0 +1,7 @@
+module Codec.Archive.Foreign.Common ( intToBool ) where
+
+import           Foreign.C.Types
+
+-- TODO: this should check against ArchiveFatal or whatnot?
+intToBool :: CInt -> Bool
+intToBool = toEnum . fromIntegral
diff --git a/src/Codec/Archive/Pack.hs b/src/Codec/Archive/Pack.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Archive/Pack.hs
@@ -0,0 +1,138 @@
+module Codec.Archive.Pack ( packEntries
+                          , entriesToFile
+                          , entriesToFileZip
+                          , entriesToFile7Zip
+                          , entriesToBS
+                          , entriesToBSzip
+                          , entriesToBS7zip
+                          ) where
+
+import           Codec.Archive.Foreign
+import           Codec.Archive.Types
+import           Control.Monad         (void)
+import           Data.ByteString       (packCStringLen, useAsCStringLen)
+import qualified Data.ByteString       as BS
+import           Data.Foldable         (traverse_)
+import           Data.Semigroup        (Sum (..))
+import           Foreign.C.String
+import           Foreign.Marshal.Alloc (alloca, allocaBytes)
+import           Foreign.Ptr           (Ptr)
+import           Foreign.Storable      (peek)
+import           System.IO.Unsafe      (unsafePerformIO)
+
+contentAdd :: EntryContent -> Ptr Archive -> Ptr ArchiveEntry -> IO ()
+contentAdd (NormalFile contents) a entry = do
+    archive_entry_set_filetype entry regular
+    archive_entry_set_size entry (fromIntegral (BS.length contents))
+    void $ archive_write_header a entry
+    useAsCStringLen contents $ \(buff, sz) ->
+        void $ archive_write_data a buff (fromIntegral sz)
+contentAdd Directory a entry = do
+    archive_entry_set_filetype entry directory
+    void $ archive_write_header a entry
+contentAdd (Symlink fp) a entry = do
+    archive_entry_set_filetype entry symlink
+    withCString fp $ \fpc ->
+        archive_entry_set_symlink entry fpc
+    void $ archive_write_header a entry
+
+setOwnership :: Ownership -> Ptr ArchiveEntry -> IO ()
+setOwnership (Ownership uname gname uid gid) entry =
+    withCString uname $ \unameC ->
+    withCString gname $ \gnameC ->
+    sequence_
+        [ archive_entry_set_uname entry unameC
+        , archive_entry_set_gname entry gnameC
+        , archive_entry_set_uid entry uid
+        , archive_entry_set_gid entry gid
+        ]
+
+setTime :: ModTime -> Ptr ArchiveEntry -> IO ()
+setTime (time', nsec) entry = archive_entry_set_mtime entry time' nsec
+
+packEntries :: (Foldable t) => Ptr Archive -> t Entry -> IO ()
+packEntries a = traverse_ (archiveEntryAdd a)
+
+-- Get a number of bytes appropriate for creating the archive.
+entriesSz :: (Foldable t, Integral a) => t Entry -> a
+entriesSz = getSum . foldMap (Sum . entrySz)
+    where entrySz e = 512 + 512 * (contentSz (content e) `div` 512 + 1)
+          contentSz (NormalFile str) = fromIntegral $ BS.length str
+          contentSz Directory        = 0
+          contentSz (Symlink fp)     = fromIntegral $ length fp
+
+-- | Returns a 'BS.ByteString' containing a tar archive with the 'Entry's
+entriesToBS :: Foldable t => t Entry -> BS.ByteString
+entriesToBS = unsafePerformIO . entriesToBSGeneral archive_write_set_format_pax_restricted
+{-# NOINLINE entriesToBS #-}
+
+-- | Returns a 'BS.ByteString' containing a @.7z@ archive with the 'Entry's
+entriesToBS7zip :: Foldable t => t Entry -> BS.ByteString
+entriesToBS7zip = unsafePerformIO . entriesToBSGeneral archive_write_set_format_7zip
+{-# NOINLINE entriesToBS7zip #-}
+
+-- | Returns a 'BS.ByteString' containing a zip archive with the 'Entry's
+entriesToBSzip :: Foldable t => t Entry -> BS.ByteString
+entriesToBSzip = unsafePerformIO . entriesToBSGeneral archive_write_set_format_zip
+{-# NOINLINE entriesToBSzip #-}
+
+entriesToBSGeneral :: (Foldable t) => (Ptr Archive -> IO ArchiveError) -> t Entry -> IO BS.ByteString
+entriesToBSGeneral modifier hsEntries' = do
+    a <- archive_write_new
+    void $ modifier a
+    alloca $ \used ->
+        allocaBytes bufSize $ \buffer -> do
+            void $ archive_write_open_memory a buffer bufSize used
+            packEntries a hsEntries'
+            void $ archive_write_close a
+            usedSz <- peek used
+            res <- curry packCStringLen buffer (fromIntegral usedSz)
+            void $ archive_write_free a
+            pure res
+
+    where bufSize :: Integral a => a
+          bufSize = entriesSz hsEntries'
+
+-- | Write some entries to a file, creating a tar archive. This is more
+-- efficient than
+--
+-- @
+-- BS.writeFile "file.tar" (entriesToBS entries)
+-- @
+entriesToFile :: Foldable t => FilePath -> t Entry -> IO ()
+entriesToFile = entriesToFileGeneral archive_write_set_format_pax_restricted
+-- this is the recommended format; it is a tar archive
+
+-- | Write some entries to a file, creating a zip archive.
+entriesToFileZip :: Foldable t => FilePath -> t Entry -> IO ()
+entriesToFileZip = entriesToFileGeneral archive_write_set_format_zip
+
+-- | Write some entries to a file, creating a @.7z@ archive.
+entriesToFile7Zip :: Foldable t => FilePath -> t Entry -> IO ()
+entriesToFile7Zip = entriesToFileGeneral archive_write_set_format_7zip
+
+entriesToFileGeneral :: Foldable t => (Ptr Archive -> IO ArchiveError) -> FilePath -> t Entry -> IO ()
+entriesToFileGeneral modifier fp hsEntries' = do
+    a <- archive_write_new
+    void $ modifier a
+    withCString fp $ \fpc ->
+        void $ archive_write_open_filename a fpc
+    packEntries a hsEntries'
+    void $ archive_write_free a
+
+withArchiveEntry :: (Ptr ArchiveEntry -> IO a) -> IO a
+withArchiveEntry fact = do
+    entry <- archive_entry_new
+    res <- fact entry
+    archive_entry_free entry
+    pure res
+
+archiveEntryAdd :: Ptr Archive -> Entry -> IO ()
+archiveEntryAdd a (Entry fp contents perms owner mtime) =
+    withArchiveEntry $ \entry -> do
+        withCString fp $ \fpc ->
+            archive_entry_set_pathname entry fpc
+        archive_entry_set_perm entry perms
+        setOwnership owner entry
+        setTime mtime entry
+        contentAdd contents a entry
diff --git a/src/Codec/Archive/Types.hs b/src/Codec/Archive/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Archive/Types.hs
@@ -0,0 +1,123 @@
+module Codec.Archive.Types ( -- * Abstract data types
+                             Archive
+                           , ArchiveEntry
+                           , Stat
+                           , LinkResolver
+                           -- * Concrete (Haskell) data types
+                           , Entry (..)
+                           , EntryContent (..)
+                           , Ownership (..)
+                           , ModTime
+                           , Id
+                           , Permissions
+                           , ArchiveEncryption (..)
+                           -- * Macros
+                           , Flags (..)
+                           , ArchiveError (..)
+                           , ArchiveFilter (..)
+                           , ArchiveFormat (..)
+                           , FileType (..)
+                           , ArchiveCapabilities (..)
+                           , ReadDiskFlags (..)
+                           , TimeFlag (..)
+                           , EntryACL (..)
+                           -- * Values
+                           , standardPermissions
+                           , executablePermissions
+                           ) where
+
+import           Data.Bits          (Bits (..))
+import qualified Data.ByteString    as BS
+import           Data.Int           (Int64)
+import           Data.Semigroup
+import           Foreign.C.Types    (CInt, CLong, CTime)
+import           System.Posix.Types (CMode (..))
+
+-- | Abstract type
+data Archive
+
+-- | Abstract type
+data ArchiveEntry
+
+data Stat
+
+data LinkResolver
+
+-- TODO: support everything here: http://hackage.haskell.org/package/tar/docs/Codec-Archive-Tar-Entry.html#t:EntryContent
+data EntryContent = NormalFile !BS.ByteString
+                  | Directory
+                  | Symlink !FilePath
+
+data Entry = Entry { filepath    :: !FilePath
+                   , content     :: !EntryContent
+                   , permissions :: !Permissions
+                   , ownership   :: !Ownership
+                   , time        :: !ModTime
+                   }
+
+data Ownership = Ownership { userName  :: !String
+                           , groupName :: !String
+                           , ownerId   :: !Id
+                           , groupId   :: !Id
+                           }
+
+type Permissions = CMode
+type ModTime = (CTime, CLong)
+
+-- | A user or group ID
+type Id = Int64
+
+standardPermissions :: Permissions
+standardPermissions = 0o644
+
+executablePermissions :: Permissions
+executablePermissions = 0o755
+
+newtype ArchiveFormat = ArchiveFormat CInt
+
+newtype FileType = FileType CMode
+    deriving (Eq)
+
+-- TODO: make this a sum type ?
+newtype ArchiveError = ArchiveError CInt
+    deriving (Eq)
+
+newtype Flags = Flags CInt
+
+newtype ReadDiskFlags = ReadDiskFlags CInt
+
+newtype TimeFlag = TimeFlag CInt
+
+newtype EntryACL = EntryACL CInt
+
+newtype ArchiveFilter = ArchiveFilter CInt
+
+newtype ArchiveCapabilities = ArchiveCapabilities CInt
+    deriving (Eq)
+
+data ArchiveEncryption = HasEncryption
+                       | NoEncryption
+                       | EncryptionUnsupported
+                       | EncryptionUnknown
+
+instance Semigroup ArchiveCapabilities where
+    (<>) (ArchiveCapabilities x) (ArchiveCapabilities y) = ArchiveCapabilities (x .|. y)
+
+instance Monoid ArchiveCapabilities where
+    mempty = ArchiveCapabilities 0
+    mappend = (<>)
+
+instance Semigroup ReadDiskFlags where
+    (<>) (ReadDiskFlags x) (ReadDiskFlags y) = ReadDiskFlags (x .|. y)
+
+instance Semigroup Flags where
+    (<>) (Flags x) (Flags y) = Flags (x .|. y)
+
+instance Monoid Flags where
+    mempty = Flags 0
+    mappend = (<>)
+
+instance Semigroup EntryACL where
+    (<>) (EntryACL x) (EntryACL y) = EntryACL (x .|. y)
+
+-- TODO: `has` function for EntryACL
diff --git a/src/Codec/Archive/Unpack.hs b/src/Codec/Archive/Unpack.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Archive/Unpack.hs
@@ -0,0 +1,88 @@
+module Codec.Archive.Unpack ( hsEntries
+                            , unpackEntriesFp
+                            ) where
+
+import           Codec.Archive.Foreign
+import           Codec.Archive.Types
+import           Control.Monad         (void)
+import qualified Data.ByteString       as BS
+import           Foreign.C.String
+import           Foreign.Marshal.Alloc (alloca, allocaBytes)
+import           Foreign.Ptr           (Ptr)
+import           Foreign.Storable      (Storable (..))
+import           System.FilePath       ((</>))
+
+readEntry :: Ptr Archive -> Ptr ArchiveEntry -> IO Entry
+readEntry a entry =
+    Entry
+        <$> (peekCString =<< archive_entry_pathname entry)
+        <*> readContents a entry
+        <*> archive_entry_perm entry
+        <*> readOwnership entry
+        <*> readTimes entry
+
+getHsEntry :: Ptr Archive -> IO (Maybe Entry)
+getHsEntry a = do
+    entry <- getEntry a
+    case entry of
+        Nothing -> pure Nothing
+        Just x  -> Just <$> readEntry a x
+
+hsEntries :: Ptr Archive -> IO [Entry]
+hsEntries a = do
+    next <- getHsEntry a
+    case next of
+        Nothing -> pure []
+        Just x  -> (x:) <$> hsEntries a
+
+-- | Unpack an archive in a given directory
+unpackEntriesFp :: Ptr Archive -> FilePath -> IO ()
+unpackEntriesFp a fp = do
+    res <- getEntry a
+    case res of
+        Nothing -> pure ()
+        Just x  -> do
+            preFile <- archive_entry_pathname x
+            file <- peekCString preFile
+            let file' = fp </> file
+            withCString file' $ \fileC ->
+                archive_entry_set_pathname x fileC
+            void $ archive_read_extract a x archiveExtractTime
+            archive_entry_set_pathname x preFile
+            void $ archive_read_data_skip a
+            unpackEntriesFp a fp
+
+readBS :: Ptr Archive -> Int -> IO BS.ByteString
+readBS a sz =
+    allocaBytes sz $ \buff ->
+        archive_read_data a buff (fromIntegral sz) *>
+        BS.packCStringLen (buff, sz)
+
+readContents :: Ptr Archive -> Ptr ArchiveEntry -> IO EntryContent
+readContents a entry = go =<< archive_entry_filetype entry
+    where go ft | ft == regular = NormalFile <$> (readBS a =<< sz)
+                | ft == symlink = Symlink <$> (peekCString =<< archive_entry_symlink entry)
+                | ft == directory = pure Directory
+                | otherwise = error "Unsupported filetype"
+          sz = fromIntegral <$> archive_entry_size entry
+
+readOwnership :: Ptr ArchiveEntry -> IO Ownership
+readOwnership entry =
+    Ownership
+        <$> (peekCString =<< archive_entry_uname entry)
+        <*> (peekCString =<< archive_entry_gname entry)
+        <*> archive_entry_uid entry
+        <*> archive_entry_gid entry
+
+readTimes :: Ptr ArchiveEntry -> IO ModTime
+readTimes entry =
+    (,) <$> archive_entry_mtime entry <*> archive_entry_mtime_nsec entry
+
+getEntry :: Ptr Archive -> IO (Maybe (Ptr ArchiveEntry))
+getEntry a = alloca $ \ptr -> do
+    let done res = not (res == archiveOk || res == archiveRetry)
+    stop <- done <$> archive_read_next_header a ptr
+    if stop
+        then pure Nothing
+        else Just <$> peek ptr
+
