zip-2.2.1: Operations on zip archives

Copyright | © 2016–present Mark Karpov
License | BSD 3 clause
Maintainer | Mark Karpov <markkarpov92@gmail.com>
Stability | experimental
Portability | portable
Safe Haskell | None
Language | GHC2021

Codec.Archive.Zip

Contents

- Types
  - Entry selector
  - Entry description
  - Archive description
  - Exceptions
- Archive monad
- Retrieving information
- Modifying archive
  - Adding entries
  - Modifying entries
  - Operations on archive as a whole
  - Control over editing

Description

The module provides everything you may need to manipulate Zip archives. There are three things that should be clarified right away, to avoid confusion.

First, we use the `EntrySelector` type that can be obtained from relative `FilePath`s (paths to directories are not allowed). This method may seem awkward at first, but it will protect you from the problems with portability when your archive is unpacked on a different platform.

Second, there is no way to add directories, or to be precise, /empty directories/ to your archive. This approach is used in Git, and I find it sane.

Finally, the third feature of the library is that it does not modify archive instantly, because doing so on every manipulation would often be inefficient. Instead, we maintain a collection of pending actions that can be turned into an optimized procedure that efficiently modifies the archive in one pass. Normally, this should be of no concern to you, because all actions are performed automatically when you leave the `ZipArchive` monad. If, however, you ever need to force an update, the `commit` function is your friend.

### Examples

An example of a program that prints a list of archive entries:

    import Codec.Archive.Zip
    import System.Environment (getArgs)
    import qualified Data.Map as M

    main :: IO ()
    main = do
      [path]  <- getArgs
      entries <- withArchive path (M.keys <$> getEntries)
      mapM_ print entries

Create a Zip archive with a “Hello World” file:

    import Codec.Archive.Zip
    import System.Environment (getArgs)

    main :: IO ()
    main = do
      [path] <- getArgs
      s      <- mkEntrySelector "hello-world.txt"
      createArchive path (addEntry Store "Hello, World!" s)

Extract contents of a file and print them:

    import Codec.Archive.Zip
    import System.Environment (getArgs)
    import qualified Data.ByteString.Char8 as B

    main :: IO ()
    main = do
      [path,f] <- getArgs
      s        <- mkEntrySelector f
      bs       <- withArchive path (getEntry s)
      B.putStrLn bs

Synopsis

- data EntrySelector
- mkEntrySelector :: MonadThrow m => FilePath -> m EntrySelector
- unEntrySelector :: EntrySelector -> FilePath
- getEntryName :: EntrySelector -> Text
- newtype EntrySelectorException = InvalidEntrySelector FilePath
- data EntryDescription = EntryDescription {
  - edVersionMadeBy :: Version
  - edVersionNeeded :: Version
  - edCompression :: CompressionMethod
  - edModTime :: UTCTime
  - edCRC32 :: Word32
  - edCompressedSize :: Natural
  - edUncompressedSize :: Natural
  - edOffset :: Natural
  - edComment :: Maybe Text
  - edExtraField :: Map Word16 ByteString
  - edExternalFileAttrs :: Word32
  }
- data CompressionMethod
  - = Store
  - | Deflate
  - | BZip2
  - | Zstd
- data ArchiveDescription = ArchiveDescription {
  - adComment :: Maybe Text
  - adCDOffset :: Natural
  - adCDSize :: Natural
  }
- data ZipException
  - = EntryDoesNotExist FilePath EntrySelector
  - | UnsupportedCompressionMethod CompressionMethod
  - | ParsingFailed FilePath String
- data ZipArchive a
- data ZipState
- createArchive :: MonadIO m => FilePath -> ZipArchive a -> m a
- withArchive :: MonadIO m => FilePath -> ZipArchive a -> m a
- getEntries :: ZipArchive (Map EntrySelector EntryDescription)
- doesEntryExist :: EntrySelector -> ZipArchive Bool
- getEntryDesc :: EntrySelector -> ZipArchive (Maybe EntryDescription)
- getEntry :: EntrySelector -> ZipArchive ByteString
- getEntrySource :: forall (m :: Type -> Type). (PrimMonad m, MonadThrow m, MonadResource m) => EntrySelector -> ZipArchive (ConduitT () ByteString m ())
- sourceEntry :: EntrySelector -> ConduitT ByteString Void (ResourceT IO) a -> ZipArchive a
- saveEntry :: EntrySelector -> FilePath -> ZipArchive ()
- checkEntry :: EntrySelector -> ZipArchive Bool
- unpackInto :: FilePath -> ZipArchive ()
- getArchiveComment :: ZipArchive (Maybe Text)
- getArchiveDescription :: ZipArchive ArchiveDescription
- addEntry :: CompressionMethod -> ByteString -> EntrySelector -> ZipArchive ()
- sinkEntry :: CompressionMethod -> ConduitT () ByteString (ResourceT IO) () -> EntrySelector -> ZipArchive ()
- loadEntry :: CompressionMethod -> EntrySelector -> FilePath -> ZipArchive ()
- copyEntry :: FilePath -> EntrySelector -> EntrySelector -> ZipArchive ()
- packDirRecur :: CompressionMethod -> (FilePath -> ZipArchive EntrySelector) -> FilePath -> ZipArchive ()
- packDirRecur' :: CompressionMethod -> (FilePath -> ZipArchive EntrySelector) -> (EntrySelector -> ZipArchive ()) -> FilePath -> ZipArchive ()
- renameEntry :: EntrySelector -> EntrySelector -> ZipArchive ()
- deleteEntry :: EntrySelector -> ZipArchive ()
- recompress :: CompressionMethod -> EntrySelector -> ZipArchive ()
- setEntryComment :: Text -> EntrySelector -> ZipArchive ()
- deleteEntryComment :: EntrySelector -> ZipArchive ()
- setModTime :: UTCTime -> EntrySelector -> ZipArchive ()
- addExtraField :: Word16 -> ByteString -> EntrySelector -> ZipArchive ()
- deleteExtraField :: Word16 -> EntrySelector -> ZipArchive ()
- setExternalFileAttrs :: Word32 -> EntrySelector -> ZipArchive ()
- forEntries :: (EntrySelector -> ZipArchive ()) -> ZipArchive ()
- setArchiveComment :: Text -> ZipArchive ()
- deleteArchiveComment :: ZipArchive ()
- undoEntryChanges :: EntrySelector -> ZipArchive ()
- undoArchiveChanges :: ZipArchive ()
- undoAll :: ZipArchive ()
- commit :: ZipArchive ()

# Types

## Entry selector

data EntrySelector Source #

This data type serves for naming and selection of archive entries. It can be created only with the help of the smart constructor `mkEntrySelector`, and it's the only “key” that can be used to refer to files in the archive or to name new archive entries.

The abstraction is crucial for ensuring that created archives are portable across operating systems, file systems, and platforms. Since on some operating systems, file paths are case-insensitive, this selector is also case-insensitive. It makes sure that only relative paths are used to name files inside archive, as it's recommended in the specification. It also guarantees that forward slashes are used when the path is stored inside the archive for compatibility with Unix-like operating systems (as recommended in the specification). On the other hand, in can be rendered as an ordinary relative file path in OS-specific format when needed.

#### Instances

Instances details

Show EntrySelector Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods showsPrec :: Int -> EntrySelector -> ShowS Source # show :: EntrySelector -> String Source # showList :: [EntrySelector] -> ShowS Source #
Eq EntrySelector Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods (==) :: EntrySelector -> EntrySelector -> Bool Source # (/=) :: EntrySelector -> EntrySelector -> Bool Source #
Ord EntrySelector Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

compare :: EntrySelector -> EntrySelector -> Ordering Source #

(<) :: EntrySelector -> EntrySelector -> Bool Source #

(<=) :: EntrySelector -> EntrySelector -> Bool Source #

(>) :: EntrySelector -> EntrySelector -> Bool Source #

(>=) :: EntrySelector -> EntrySelector -> Bool Source #

max :: EntrySelector -> EntrySelector -> EntrySelector Source #

min :: EntrySelector -> EntrySelector -> EntrySelector Source #

mkEntrySelector :: MonadThrow m => FilePath -> m EntrySelector Source #

Create an `EntrySelector` from a `FilePath`. To avoid problems with distribution of the archive, characters that some operating systems do not expect in paths are not allowed.

Argument to `mkEntrySelector` should pass these checks:

- `isValid`
- `isValid`
- it is a relative path without slash at the end
- binary representations of normalized path should be not longer than 65535 bytes

This function can throw an `EntrySelectorException`.

unEntrySelector :: EntrySelector -> FilePath Source #

Restore a relative path from `EntrySelector`. Every `EntrySelector` corresponds to a `FilePath`.

getEntryName :: EntrySelector -> Text Source #

Get an entry name in the from that is suitable for writing to file header, given an `EntrySelector`.

newtype EntrySelectorException Source #

The problems you can have with an `EntrySelector`.

Constructors

InvalidEntrySelector FilePath | `EntrySelector` cannot be created from this path

#### Instances

Instances details

Exception EntrySelectorException Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods toException :: EntrySelectorException -> SomeException Source # fromException :: SomeException -> Maybe EntrySelectorException Source # displayException :: EntrySelectorException -> String Source # backtraceDesired :: EntrySelectorException -> Bool Source #
Show EntrySelectorException Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods showsPrec :: Int -> EntrySelectorException -> ShowS Source # show :: EntrySelectorException -> String Source # showList :: [EntrySelectorException] -> ShowS Source #
Eq EntrySelectorException Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods (==) :: EntrySelectorException -> EntrySelectorException -> Bool Source # (/=) :: EntrySelectorException -> EntrySelectorException -> Bool Source #
Ord EntrySelectorException Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

compare :: EntrySelectorException -> EntrySelectorException -> Ordering Source #

(<) :: EntrySelectorException -> EntrySelectorException -> Bool Source #

(<=) :: EntrySelectorException -> EntrySelectorException -> Bool Source #

(>) :: EntrySelectorException -> EntrySelectorException -> Bool Source #

(>=) :: EntrySelectorException -> EntrySelectorException -> Bool Source #

max :: EntrySelectorException -> EntrySelectorException -> EntrySelectorException Source #

min :: EntrySelectorException -> EntrySelectorException -> EntrySelectorException Source #

## Entry description

data EntryDescription Source #

The information about archive entry that can be stored in a zip archive. It does not mirror local file header or central directory file header, but their binary representations can be built given this data structure and the archive contents.

Constructors

EntryDescription |

Fields

- edVersionMadeBy :: Version

  Version made by

- edVersionNeeded :: Version

  Version needed to extract

- edCompression :: CompressionMethod

  Compression method

- edModTime :: UTCTime

  Last modification date and time

- edCRC32 :: Word32

  CRC32 check sum

- edCompressedSize :: Natural

  Size of compressed entry

- edUncompressedSize :: Natural

  Size of uncompressed entry

- edOffset :: Natural

  Absolute offset of local file header

- edComment :: Maybe Text

  Entry comment

- edExtraField :: Map Word16 ByteString

  All extra fields found

- edExternalFileAttrs :: Word32

  External file attributes

  Since: 1.2.0

#### Instances

Instances details

Show EntryDescription Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods showsPrec :: Int -> EntryDescription -> ShowS Source # show :: EntryDescription -> String Source # showList :: [EntryDescription] -> ShowS Source #
Eq EntryDescription Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods (==) :: EntryDescription -> EntryDescription -> Bool Source # (/=) :: EntryDescription -> EntryDescription -> Bool Source #

data CompressionMethod Source #

The supported compression methods.

Constructors

Store | Store file uncompressed
Deflate | Deflate
BZip2 | Compressed using BZip2 algorithm
Zstd | Compressed using Zstandard algorithm Since: 1.6.0

#### Instances

Instances details

Data CompressionMethod Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> CompressionMethod -> c CompressionMethod Source #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c CompressionMethod Source #

toConstr :: CompressionMethod -> Constr Source #

dataTypeOf :: CompressionMethod -> DataType Source #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c CompressionMethod) Source #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c CompressionMethod) Source #

gmapT :: (forall b. Data b => b -> b) -> CompressionMethod -> CompressionMethod Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> CompressionMethod -> r Source #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> CompressionMethod -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> CompressionMethod -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> CompressionMethod -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> CompressionMethod -> m CompressionMethod Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> CompressionMethod -> m CompressionMethod Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> CompressionMethod -> m CompressionMethod Source #

Bounded CompressionMethod Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods minBound :: CompressionMethod Source # maxBound :: CompressionMethod Source #
Enum CompressionMethod Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

succ :: CompressionMethod -> CompressionMethod Source #

pred :: CompressionMethod -> CompressionMethod Source #

toEnum :: Int -> CompressionMethod Source #

fromEnum :: CompressionMethod -> Int Source #

enumFrom :: CompressionMethod -> [CompressionMethod] Source #

enumFromThen :: CompressionMethod -> CompressionMethod -> [CompressionMethod] Source #

enumFromTo :: CompressionMethod -> CompressionMethod -> [CompressionMethod] Source #

enumFromThenTo :: CompressionMethod -> CompressionMethod -> CompressionMethod -> [CompressionMethod] Source #

Read CompressionMethod Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods readsPrec :: Int -> ReadS CompressionMethod Source # readList :: ReadS [CompressionMethod] Source # readPrec :: ReadPrec CompressionMethod Source # readListPrec :: ReadPrec [CompressionMethod] Source #
Show CompressionMethod Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods showsPrec :: Int -> CompressionMethod -> ShowS Source # show :: CompressionMethod -> String Source # showList :: [CompressionMethod] -> ShowS Source #
Eq CompressionMethod Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods (==) :: CompressionMethod -> CompressionMethod -> Bool Source # (/=) :: CompressionMethod -> CompressionMethod -> Bool Source #
Ord CompressionMethod Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

compare :: CompressionMethod -> CompressionMethod -> Ordering Source #

(<) :: CompressionMethod -> CompressionMethod -> Bool Source #

(<=) :: CompressionMethod -> CompressionMethod -> Bool Source #

(>) :: CompressionMethod -> CompressionMethod -> Bool Source #

(>=) :: CompressionMethod -> CompressionMethod -> Bool Source #

max :: CompressionMethod -> CompressionMethod -> CompressionMethod Source #

min :: CompressionMethod -> CompressionMethod -> CompressionMethod Source #

## Archive description

data ArchiveDescription Source #

The information about the archive as a whole.

Constructors

ArchiveDescription |

Fields

- adComment :: Maybe Text

  The comment of the entire archive

- adCDOffset :: Natural

  Absolute offset of the start of central directory

- adCDSize :: Natural

  The size of central directory record

#### Instances

Instances details

Data ArchiveDescription Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ArchiveDescription -> c ArchiveDescription Source #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ArchiveDescription Source #

toConstr :: ArchiveDescription -> Constr Source #

dataTypeOf :: ArchiveDescription -> DataType Source #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ArchiveDescription) Source #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ArchiveDescription) Source #

gmapT :: (forall b. Data b => b -> b) -> ArchiveDescription -> ArchiveDescription Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ArchiveDescription -> r Source #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ArchiveDescription -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> ArchiveDescription -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> ArchiveDescription -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> ArchiveDescription -> m ArchiveDescription Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ArchiveDescription -> m ArchiveDescription Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ArchiveDescription -> m ArchiveDescription Source #

Read ArchiveDescription Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods readsPrec :: Int -> ReadS ArchiveDescription Source # readList :: ReadS [ArchiveDescription] Source # readPrec :: ReadPrec ArchiveDescription Source # readListPrec :: ReadPrec [ArchiveDescription] Source #
Show ArchiveDescription Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods showsPrec :: Int -> ArchiveDescription -> ShowS Source # show :: ArchiveDescription -> String Source # showList :: [ArchiveDescription] -> ShowS Source #
Eq ArchiveDescription Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods (==) :: ArchiveDescription -> ArchiveDescription -> Bool Source # (/=) :: ArchiveDescription -> ArchiveDescription -> Bool Source #
Ord ArchiveDescription Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

compare :: ArchiveDescription -> ArchiveDescription -> Ordering Source #

(<) :: ArchiveDescription -> ArchiveDescription -> Bool Source #

(<=) :: ArchiveDescription -> ArchiveDescription -> Bool Source #

(>) :: ArchiveDescription -> ArchiveDescription -> Bool Source #

(>=) :: ArchiveDescription -> ArchiveDescription -> Bool Source #

max :: ArchiveDescription -> ArchiveDescription -> ArchiveDescription Source #

min :: ArchiveDescription -> ArchiveDescription -> ArchiveDescription Source #

## Exceptions

data ZipException Source #

The bad things that can happen when you use the library.

Constructors

EntryDoesNotExist FilePath EntrySelector | Thrown when you try to get contents of non-existing entry
UnsupportedCompressionMethod CompressionMethod | Thrown when attempting to decompress an entry compressed with an unsupported compression method or the library is compiled without support for it. Since: 2.0.0
ParsingFailed FilePath String | Thrown when archive structure cannot be parsed.

#### Instances

Instances details

Exception ZipException Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods toException :: ZipException -> SomeException Source # fromException :: SomeException -> Maybe ZipException Source # displayException :: ZipException -> String Source # backtraceDesired :: ZipException -> Bool Source #
Show ZipException Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods showsPrec :: Int -> ZipException -> ShowS Source # show :: ZipException -> String Source # showList :: [ZipException] -> ShowS Source #
Eq ZipException Source # |
Instance details Defined in Codec.Archive.Zip.Internal.Type Methods (==) :: ZipException -> ZipException -> Bool Source # (/=) :: ZipException -> ZipException -> Bool Source #
Ord ZipException Source # |

Instance details

Defined in Codec.Archive.Zip.Internal.Type

Methods

compare :: ZipException -> ZipException -> Ordering Source #

(<) :: ZipException -> ZipException -> Bool Source #

(<=) :: ZipException -> ZipException -> Bool Source #

(>) :: ZipException -> ZipException -> Bool Source #

(>=) :: ZipException -> ZipException -> Bool Source #

max :: ZipException -> ZipException -> ZipException Source #

min :: ZipException -> ZipException -> ZipException Source #

# Archive monad

data ZipArchive a Source #

Monad that provides context necessary for performing operations on zip archives. It's intentionally opaque and not a monad transformer to limit the actions that can be performed in it to those provided by this module and their combinations.

#### Instances

Instances details

MonadIO ZipArchive Source # |
Instance details Defined in Codec.Archive.Zip Methods liftIO :: IO a -> ZipArchive a Source #
MonadCatch ZipArchive Source # |
Instance details Defined in Codec.Archive.Zip Methods catch :: (HasCallStack, Exception e) => ZipArchive a -> (e -> ZipArchive a) -> ZipArchive a Source #
MonadMask ZipArchive Source # |

Instance details

Defined in Codec.Archive.Zip

Methods

mask :: HasCallStack => ((forall a. ZipArchive a -> ZipArchive a) -> ZipArchive b) -> ZipArchive b Source #

uninterruptibleMask :: HasCallStack => ((forall a. ZipArchive a -> ZipArchive a) -> ZipArchive b) -> ZipArchive b Source #

generalBracket :: HasCallStack => ZipArchive a -> (a -> ExitCase b -> ZipArchive c) -> (a -> ZipArchive b) -> ZipArchive (b, c) Source #

MonadThrow ZipArchive Source # |
Instance details Defined in Codec.Archive.Zip Methods throwM :: (HasCallStack, Exception e) => e -> ZipArchive a Source #
Applicative ZipArchive Source # |
Instance details Defined in Codec.Archive.Zip Methods pure :: a -> ZipArchive a Source # (<*>) :: ZipArchive (a -> b) -> ZipArchive a -> ZipArchive b Source # liftA2 :: (a -> b -> c) -> ZipArchive a -> ZipArchive b -> ZipArchive c Source # (*>) :: ZipArchive a -> ZipArchive b -> ZipArchive b Source # (<*) :: ZipArchive a -> ZipArchive b -> ZipArchive a Source #
Functor ZipArchive Source # |
Instance details Defined in Codec.Archive.Zip Methods fmap :: (a -> b) -> ZipArchive a -> ZipArchive b Source # (<$) :: a -> ZipArchive b -> ZipArchive a Source #
Monad ZipArchive Source # |
Instance details Defined in Codec.Archive.Zip Methods (>>=) :: ZipArchive a -> (a -> ZipArchive b) -> ZipArchive b Source # (>>) :: ZipArchive a -> ZipArchive b -> ZipArchive b Source # return :: a -> ZipArchive a Source #
MonadBaseControl IO ZipArchive Source # | Since: 0.2.0

Instance details

Defined in Codec.Archive.Zip

Associated Types

type StM ZipArchive a |
Instance details Defined in Codec.Archive.Zip type StM ZipArchive a = (a, ZipState)

Methods

liftBaseWith :: (RunInBase ZipArchive IO -> IO a) -> ZipArchive a Source #

restoreM :: StM ZipArchive a -> ZipArchive a Source #

MonadBase IO ZipArchive Source # | Since: 0.2.0
Instance details Defined in Codec.Archive.Zip Methods liftBase :: IO α -> ZipArchive α Source #
type StM ZipArchive a Source # |
Instance details Defined in Codec.Archive.Zip type StM ZipArchive a = (a, ZipState)

data ZipState Source #

The internal state record used by the `ZipArchive` monad. This is only exported for use with `MonadBaseControl` methods, you can't look inside.

Since: 0.2.0

createArchive Source #

Arguments

:: MonadIO m |
=> FilePath | Location of the archive file to create
-> ZipArchive a | Actions that create the archive's content
-> m a |

Create a new archive given its location and an action that describes how to create contents of the archive. This will silently overwrite the specified file if it already exists. See `withArchive` if you want to work with an existing archive.

withArchive Source #

Arguments

:: MonadIO m |
=> FilePath | Location of the archive to work with
-> ZipArchive a | Actions on that archive
-> m a |

Work with an existing archive. See `createArchive` if you want to create a new archive instead.

This operation may fail with:

- `isAlreadyInUseError` if the file is already open and cannot be reopened;
- `isDoesNotExistError` if the file does not exist;
- `isPermissionError` if the user does not have permission to open the file;
- `ParsingFailed` when specified archive is something this library cannot parse (this includes multi-disk archives, for example).

Please note that entries with invalid (non-portable) file names may be missing in the list of entries. Files that are compressed with unsupported compression methods are skipped as well. Also, if several entries would collide on some operating systems (such as Windows, because of its case-insensitivity), only one of them will be available, because `EntrySelector` is case-insensitive. These are the consequences of the design decision to make it impossible to create non-portable archives with this library.

# Retrieving information

getEntries :: ZipArchive (Map EntrySelector EntryDescription) Source #

Retrieve a description of all archive entries. This is an efficient operation that can be used for example to list all entries in the archive. Do not hesitate to use the function frequently: scanning of the archive happens only once.

Please note that the returned value only reflects the current contents of the archive in file system, non-committed actions are not reflected, see `commit` for more information.

doesEntryExist :: EntrySelector -> ZipArchive Bool Source #

Check whether the specified entry exists in the archive. This is a simple shortcut defined as:

    doesEntryExist s = M.member s <$> getEntries

getEntryDesc :: EntrySelector -> ZipArchive (Maybe EntryDescription) Source #

Get `EntryDescription` for a specified entry. This is a simple shortcut defined as:

    getEntryDesc s = M.lookup s <$> getEntries

getEntry Source #

Arguments

:: EntrySelector | Selector that identifies archive entry
-> ZipArchive ByteString | Contents of the entry

Get contents of a specific archive entry as a strict `ByteString`. It's not recommended to use this on big entries, because it will suck out a lot of memory. For big entries, use conduits: `sourceEntry`.

Throws: `EntryDoesNotExist`.

getEntrySource Source #

Arguments

:: forall (m :: Type -> Type). (PrimMonad m, MonadThrow m, MonadResource m) |
=> EntrySelector | Selector that identifies archive entry
-> ZipArchive (ConduitT () ByteString m ()) |

Get an entry source.

Throws: `EntryDoesNotExist`.

Since: 0.1.3

sourceEntry Source #

Arguments

:: EntrySelector | Selector that identifies the archive entry
-> ConduitT ByteString Void (ResourceT IO) a | Sink where to stream entry contents
-> ZipArchive a | Contents of the entry (if found)

Stream contents of an archive entry to the given `Sink`.

Throws: `EntryDoesNotExist`.

saveEntry Source #

Arguments

:: EntrySelector | Selector that identifies the archive entry
-> FilePath | Where to save the file
-> ZipArchive () |

Save a specific archive entry as a file in the file system.

Throws: `EntryDoesNotExist`.

checkEntry Source #

Arguments

:: EntrySelector | Selector that identifies the archive entry
-> ZipArchive Bool | Is the entry intact?

Calculate CRC32 check sum and compare it with the value read from the archive. The function returns `True` when the check sums are the same—that is, the data is not corrupted.

Throws: `EntryDoesNotExist`.

unpackInto :: FilePath -> ZipArchive () Source #

Unpack the archive into the specified directory. The directory will be created if it does not exist.

getArchiveComment :: ZipArchive (Maybe Text) Source #

Get the archive comment.

getArchiveDescription :: ZipArchive ArchiveDescription Source #

Get the archive description record.

# Modifying archive

## Adding entries

addEntry Source #

Arguments

:: CompressionMethod | The compression method to use
-> ByteString | Entry contents
-> EntrySelector | Name of the entry to add
-> ZipArchive () |

Add a new entry to the archive given its contents in binary form.

sinkEntry Source #

Arguments

:: CompressionMethod | The compression method to use
-> ConduitT () ByteString (ResourceT IO) () | Source of entry contents
-> EntrySelector | Name of the entry to add
-> ZipArchive () |

Stream data from the specified source to an archive entry.

loadEntry Source #

Arguments

:: CompressionMethod | The compression method to use
-> EntrySelector | Name of the entry to add
-> FilePath | Path to the file to add
-> ZipArchive () |

Load an entry from a given file.

copyEntry Source #

Arguments

:: FilePath | Path to the archive to copy from
-> EntrySelector | Name of the entry (in the source archive) to copy
-> EntrySelector | Name of the entry to insert (in current archive)
-> ZipArchive () |

Copy an entry “as is” from another zip archive. If the entry does not exist in that archive, `EntryDoesNotExist` will be thrown.

packDirRecur Source #

Arguments

:: CompressionMethod | The compression method to use
-> (FilePath -> ZipArchive EntrySelector) | How to get the `EntrySelector` from a path relative to the root of the directory we pack
-> FilePath | Path to the directory to add
-> ZipArchive () |

Add an directory to the archive. Please note that due to the design of the library, empty sub-directories will not be added.

The action can throw `InvalidEntrySelector`.

packDirRecur' Source #

Arguments

:: CompressionMethod | The compression method to use
-> (FilePath -> ZipArchive EntrySelector) | How to get the `EntrySelector` from a path relative to the root of the directory we pack
-> (EntrySelector -> ZipArchive ()) | How to modify an entry after creation
-> FilePath | Path to the directory to add
-> ZipArchive () |

The same as `packDirRecur` but allows us to perform modifying actions on the created entities as we go.

Since: 1.5.0

## Modifying entries

renameEntry Source #

Arguments

:: EntrySelector | The original entry name
-> EntrySelector | The new entry name
-> ZipArchive () |

Rename an entry in the archive. If the entry does not exist, nothing will happen.

deleteEntry :: EntrySelector -> ZipArchive () Source #

Delete an entry from the archive, if it does not exist, nothing will happen.

recompress Source #

Arguments

:: CompressionMethod | The new compression method
-> EntrySelector | Name of the entry to re-compress
-> ZipArchive () |

Change compression method of an entry, if it does not exist, nothing will happen.

setEntryComment Source #

Arguments

:: Text | Text of the comment
-> EntrySelector | Name of the entry to comment on
-> ZipArchive () |

Set an entry comment, if that entry does not exist, nothing will happen. Note that if binary representation of the comment is longer than 65535 bytes, it will be truncated on writing.

deleteEntryComment :: EntrySelector -> ZipArchive () Source #

Delete an entry's comment, if that entry does not exist, nothing will happen.

setModTime Source #

Arguments

:: UTCTime | New modification time
-> EntrySelector | Name of the entry to modify
-> ZipArchive () |

Set the last modification date/time. The specified entry may be missing, in that case the action has no effect.

addExtraField Source #

Arguments

:: Word16 | Tag (header id) of the extra field to add
-> ByteString | Body of the field
-> EntrySelector | Name of the entry to modify
-> ZipArchive () |

Add an extra field. The specified entry may be missing, in that case this action has no effect.

deleteExtraField Source #

Arguments

:: Word16 | Tag (header id) of the extra field to delete
-> EntrySelector | Name of the entry to modify
-> ZipArchive () |

Delete an extra field by its type (tag). The specified entry may be missing, in that case this action has no effect.

setExternalFileAttrs Source #

Arguments

:: Word32 | External file attributes
-> EntrySelector | Name of the entry to modify
-> ZipArchive () |

Set external file attributes. This function can be used to set file permissions.

See also: Codec.Archive.Zip.Unix.

Since: 1.2.0

forEntries Source #

Arguments

:: (EntrySelector -> ZipArchive ()) | The action to perform
-> ZipArchive () |

Perform an action on every entry in the archive.

## Operations on archive as a whole

setArchiveComment :: Text -> ZipArchive () Source #

Set the comment of the entire archive.

deleteArchiveComment :: ZipArchive () Source #

Delete the archive's comment if it's present.

## Control over editing

undoEntryChanges :: EntrySelector -> ZipArchive () Source #

Undo the changes to a specific archive entry.

undoArchiveChanges :: ZipArchive () Source #

Undo the changes to the archive as a whole (archive's comment).

undoAll :: ZipArchive () Source #

Undo all changes made in this editing session.

commit :: ZipArchive () Source #

Archive contents are not modified instantly, but instead changes are collected as “pending actions” that should be committed, in order to efficiently modify the archive in one pass. The actions are committed automatically when the program leaves the `ZipArchive` monad (i.e. as part of `createArchive` or `withArchive`), or can be forced explicitly with the help of this function. Once committed, changes take place in the file system and cannot be undone.