LibZip 0.2.0.4 → 0.10
raw patch · 10 files changed
+117/−328 lines, 10 filesdep ~bindings-libzipPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: bindings-libzip
API changes (from Hackage documentation)
- Codec.Archive.LibZip.LegacyZeroZero: CheckConsFlag :: OpenFlag
- Codec.Archive.LibZip.LegacyZeroZero: CreateFlag :: OpenFlag
- Codec.Archive.LibZip.LegacyZeroZero: ErrCHANGED :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrCLOSE :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrCOMPNOTSUPP :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrCRC :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrDELETED :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrEOF :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrEXISTS :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrINCONS :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrINTERNAL :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrINVAL :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrMEMORY :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrMULTIDISK :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrNOENT :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrNOZIP :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrOK :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrOPEN :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrREAD :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrREMOVE :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrRENAME :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrSEEK :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrTMPOPEN :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrWRITE :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrZIPCLOSED :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ErrZLIB :: ZipError
- Codec.Archive.LibZip.LegacyZeroZero: ExclFlag :: OpenFlag
- Codec.Archive.LibZip.LegacyZeroZero: FileCOMPRESSED :: FileFlag
- Codec.Archive.LibZip.LegacyZeroZero: FileNOCASE :: FileFlag
- Codec.Archive.LibZip.LegacyZeroZero: FileNODIR :: FileFlag
- Codec.Archive.LibZip.LegacyZeroZero: FileRECOMPRESS :: FileFlag
- Codec.Archive.LibZip.LegacyZeroZero: FileUNCHANGED :: FileFlag
- Codec.Archive.LibZip.LegacyZeroZero: catchZipError :: IO a -> (ZipError -> IO a) -> IO a
- Codec.Archive.LibZip.LegacyZeroZero: close :: Zip -> IO ()
- Codec.Archive.LibZip.LegacyZeroZero: data FileFlag
- Codec.Archive.LibZip.LegacyZeroZero: data OpenFlag
- Codec.Archive.LibZip.LegacyZeroZero: data Word8 :: *
- Codec.Archive.LibZip.LegacyZeroZero: data ZipError
- Codec.Archive.LibZip.LegacyZeroZero: fclose :: ZipFile -> IO ()
- Codec.Archive.LibZip.LegacyZeroZero: fopen :: Zip -> String -> [FileFlag] -> IO ZipFile
- Codec.Archive.LibZip.LegacyZeroZero: fopen_index :: Zip -> Int -> [FileFlag] -> IO ZipFile
- Codec.Archive.LibZip.LegacyZeroZero: fread :: ZipFile -> Int -> IO [Word8]
- Codec.Archive.LibZip.LegacyZeroZero: getFileSize :: Zip -> String -> [FileFlag] -> IO Int
- Codec.Archive.LibZip.LegacyZeroZero: getFiles :: Zip -> [FileFlag] -> IO [String]
- Codec.Archive.LibZip.LegacyZeroZero: get_name :: Zip -> Int -> [FileFlag] -> IO String
- Codec.Archive.LibZip.LegacyZeroZero: get_num_files :: Zip -> IO Int
- Codec.Archive.LibZip.LegacyZeroZero: isDir :: String -> Bool
- Codec.Archive.LibZip.LegacyZeroZero: isFile :: String -> Bool
- Codec.Archive.LibZip.LegacyZeroZero: open :: String -> [OpenFlag] -> IO Zip
- Codec.Archive.LibZip.LegacyZeroZero: readZipFile :: Zip -> String -> [FileFlag] -> IO ByteString
- Codec.Archive.LibZip.LegacyZeroZero: readZipFile' :: Zip -> String -> [FileFlag] -> IO [Word8]
- Codec.Archive.LibZip.LegacyZeroZero: readZipFileHead :: Zip -> String -> [FileFlag] -> Int -> IO ByteString
- Codec.Archive.LibZip.LegacyZeroZero: readZipFileHead' :: Zip -> String -> [FileFlag] -> Int -> IO [Word8]
- Codec.Archive.LibZip.LegacyZeroZero: type Zip = Ptr C'zip
- Codec.Archive.LibZip.LegacyZeroZero: type ZipFile = Ptr C'zip_file
- Codec.Archive.LibZip.LegacyZeroZero: withZip :: String -> [OpenFlag] -> (Zip -> IO a) -> IO a
+ Codec.Archive.LibZip: ErrENCRNOTSUPP :: ZipError
+ Codec.Archive.LibZip: ErrNOPASSWD :: ZipError
+ Codec.Archive.LibZip: ErrRDONLY :: ZipError
+ Codec.Archive.LibZip: ErrWRONGPASSWD :: ZipError
+ Codec.Archive.LibZip: FileENCRYPTED :: FileFlag
+ Codec.Archive.LibZip: zs'flags :: ZipStat -> Word32
+ Codec.Archive.LibZip: zs'valid :: ZipStat -> Word64
+ Codec.Archive.LibZip.Types: ArchiveRDONLY :: ArchiveFlag
+ Codec.Archive.LibZip.Types: ArchiveTORRENT :: ArchiveFlag
+ Codec.Archive.LibZip.Types: CodecENCODE :: CodecFlag
+ Codec.Archive.LibZip.Types: ErrENCRNOTSUPP :: ZipError
+ Codec.Archive.LibZip.Types: ErrNOPASSWD :: ZipError
+ Codec.Archive.LibZip.Types: ErrRDONLY :: ZipError
+ Codec.Archive.LibZip.Types: ErrWRONGPASSWD :: ZipError
+ Codec.Archive.LibZip.Types: FileENCRYPTED :: FileFlag
+ Codec.Archive.LibZip.Types: data ArchiveFlag
+ Codec.Archive.LibZip.Types: data CodecFlag
+ Codec.Archive.LibZip.Types: instance Enum ArchiveFlag
+ Codec.Archive.LibZip.Types: instance Enum CodecFlag
+ Codec.Archive.LibZip.Types: instance Eq ArchiveFlag
+ Codec.Archive.LibZip.Types: instance Eq CodecFlag
+ Codec.Archive.LibZip.Types: instance Show ArchiveFlag
+ Codec.Archive.LibZip.Types: instance Show CodecFlag
+ Codec.Archive.LibZip.Types: zs'flags :: ZipStat -> Word32
+ Codec.Archive.LibZip.Types: zs'valid :: ZipStat -> Word64
- Codec.Archive.LibZip: PureSource :: st -> Int -> Maybe UTCTime -> (Int -> st -> Maybe (Int, [a], st)) -> PureSource a st
+ Codec.Archive.LibZip: PureSource :: st -> szt -> Maybe UTCTime -> (szt -> st -> Maybe (szt, [a], st)) -> PureSource a st szt
- Codec.Archive.LibZip: ZipStat :: String -> Int -> Word -> UTCTime -> Int -> Int -> ZipCompMethod -> ZipEncryptionMethod -> ZipStat
+ Codec.Archive.LibZip: ZipStat :: Word64 -> String -> Integer -> Integer -> Integer -> UTCTime -> Word -> ZipCompMethod -> ZipEncryptionMethod -> Word32 -> ZipStat
- Codec.Archive.LibZip: data PureSource a st
+ Codec.Archive.LibZip: data PureSource a st szt
- Codec.Archive.LibZip: deleteFileIx :: Int -> Archive ()
+ Codec.Archive.LibZip: deleteFileIx :: Integer -> Archive ()
- Codec.Archive.LibZip: fileContentsIx :: Enum a => [FileFlag] -> Int -> Archive [a]
+ Codec.Archive.LibZip: fileContentsIx :: Enum a => [FileFlag] -> Integer -> Archive [a]
- Codec.Archive.LibZip: fileName :: [FileFlag] -> Int -> Archive FilePath
+ Codec.Archive.LibZip: fileName :: [FileFlag] -> Integer -> Archive FilePath
- Codec.Archive.LibZip: fileSize :: [FileFlag] -> FilePath -> Archive Int
+ Codec.Archive.LibZip: fileSize :: [FileFlag] -> FilePath -> Archive Integer
- Codec.Archive.LibZip: fileSizeIx :: [FileFlag] -> Int -> Archive Int
+ Codec.Archive.LibZip: fileSizeIx :: [FileFlag] -> Integer -> Archive Integer
- Codec.Archive.LibZip: fileStatIx :: [FileFlag] -> Int -> Archive ZipStat
+ Codec.Archive.LibZip: fileStatIx :: [FileFlag] -> Integer -> Archive ZipStat
- Codec.Archive.LibZip: fromFileIx :: [FileFlag] -> Int -> Entry a -> Archive a
+ Codec.Archive.LibZip: fromFileIx :: [FileFlag] -> Integer -> Entry a -> Archive a
- Codec.Archive.LibZip: getFileCommentIx :: [FileFlag] -> Int -> Archive (Maybe String)
+ Codec.Archive.LibZip: getFileCommentIx :: [FileFlag] -> Integer -> Archive (Maybe String)
- Codec.Archive.LibZip: nameLocate :: [FileFlag] -> FilePath -> Archive (Maybe Int)
+ Codec.Archive.LibZip: nameLocate :: [FileFlag] -> FilePath -> Archive (Maybe Integer)
- Codec.Archive.LibZip: numFiles :: Archive Int
+ Codec.Archive.LibZip: numFiles :: [FileFlag] -> Archive Integer
- Codec.Archive.LibZip: readBytes :: Enum a => Int -> Entry [a]
+ Codec.Archive.LibZip: readBytes :: Enum a => Integer -> Entry [a]
- Codec.Archive.LibZip: readSrc :: PureSource a st -> Int -> st -> Maybe (Int, [a], st)
+ Codec.Archive.LibZip: readSrc :: PureSource a st szt -> szt -> st -> Maybe (szt, [a], st)
- Codec.Archive.LibZip: removeFileCommentIx :: Int -> Archive ()
+ Codec.Archive.LibZip: removeFileCommentIx :: Integer -> Archive ()
- Codec.Archive.LibZip: renameFileIx :: Int -> FilePath -> Archive ()
+ Codec.Archive.LibZip: renameFileIx :: Integer -> FilePath -> Archive ()
- Codec.Archive.LibZip: replaceFileIx :: Int -> ZipSource -> Archive ()
+ Codec.Archive.LibZip: replaceFileIx :: Integer -> ZipSource -> Archive ()
- Codec.Archive.LibZip: setFileCommentIx :: Int -> String -> Archive ()
+ Codec.Archive.LibZip: setFileCommentIx :: Integer -> String -> Archive ()
- Codec.Archive.LibZip: skipBytes :: Int -> Entry ()
+ Codec.Archive.LibZip: skipBytes :: Integer -> Entry ()
- Codec.Archive.LibZip: sourceFile :: FilePath -> Int -> Int -> Archive ZipSource
+ Codec.Archive.LibZip: sourceFile :: FilePath -> Integer -> Integer -> Archive ZipSource
- Codec.Archive.LibZip: sourcePure :: (Enum a, Storable a, Storable st) => PureSource a st -> Archive ZipSource
+ Codec.Archive.LibZip: sourcePure :: (Enum a, Storable a, Storable st, Integral szt) => PureSource a st szt -> Archive ZipSource
- Codec.Archive.LibZip: sourceZip :: [FileFlag] -> Zip -> Int -> Int -> Int -> Archive ZipSource
+ Codec.Archive.LibZip: sourceZip :: [FileFlag] -> Zip -> Integer -> Integer -> Integer -> Archive ZipSource
- Codec.Archive.LibZip: srcMTime :: PureSource a st -> Maybe UTCTime
+ Codec.Archive.LibZip: srcMTime :: PureSource a st szt -> Maybe UTCTime
- Codec.Archive.LibZip: srcSize :: PureSource a st -> Int
+ Codec.Archive.LibZip: srcSize :: PureSource a st szt -> szt
- Codec.Archive.LibZip: srcState :: PureSource a st -> st
+ Codec.Archive.LibZip: srcState :: PureSource a st szt -> st
- Codec.Archive.LibZip: type Entry a = StateT (ZipFile, Int, [FileFlag]) (StateT Zip IO) a
+ Codec.Archive.LibZip: type Entry a = StateT (ZipFile, Integer, [FileFlag]) (StateT Zip IO) a
- Codec.Archive.LibZip: unchangeFileIx :: Int -> Archive ()
+ Codec.Archive.LibZip: unchangeFileIx :: Integer -> Archive ()
- Codec.Archive.LibZip: zs'comp_size :: ZipStat -> Int
+ Codec.Archive.LibZip: zs'comp_size :: ZipStat -> Integer
- Codec.Archive.LibZip: zs'index :: ZipStat -> Int
+ Codec.Archive.LibZip: zs'index :: ZipStat -> Integer
- Codec.Archive.LibZip: zs'size :: ZipStat -> Int
+ Codec.Archive.LibZip: zs'size :: ZipStat -> Integer
- Codec.Archive.LibZip.Types: ZipStat :: String -> Int -> Word -> UTCTime -> Int -> Int -> ZipCompMethod -> ZipEncryptionMethod -> ZipStat
+ Codec.Archive.LibZip.Types: ZipStat :: Word64 -> String -> Integer -> Integer -> Integer -> UTCTime -> Word -> ZipCompMethod -> ZipEncryptionMethod -> Word32 -> ZipStat
- Codec.Archive.LibZip.Types: zs'comp_size :: ZipStat -> Int
+ Codec.Archive.LibZip.Types: zs'comp_size :: ZipStat -> Integer
- Codec.Archive.LibZip.Types: zs'index :: ZipStat -> Int
+ Codec.Archive.LibZip.Types: zs'index :: ZipStat -> Integer
- Codec.Archive.LibZip.Types: zs'size :: ZipStat -> Int
+ Codec.Archive.LibZip.Types: zs'size :: ZipStat -> Integer
Files
- Codec/Archive/LibZip.hs +48/−42
- Codec/Archive/LibZip/LegacyZeroZero.hsc +0/−183
- Codec/Archive/LibZip/Types.hs +57/−9
- LibZip.cabal +5/−6
- Tests/Common.hs +1/−1
- Tests/LegacyTests.hs +0/−42
- Tests/MonadicTests.hs +2/−1
- examples/hzip.hs +3/−3
- examples/legacyUnzip.hs +0/−38
- runTests.hs +1/−3
Codec/Archive/LibZip.hs view
@@ -101,11 +101,12 @@ import Data.Time.Clock (UTCTime, getCurrentTime) import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds) import Data.Word (Word8)+import Control.Monad (when) import Control.Monad.State.Strict (StateT(..), MonadState(..), MonadTrans(..), lift, liftM) import Foreign.C.Error (Errno(..), eINVAL) import Foreign.C.String (withCString, withCStringLen, peekCString)-import Foreign.C.Types (CInt, CSize)+import Foreign.C.Types (CInt, CULLong) import Foreign.Marshal.Alloc (alloca) import Foreign.Marshal.Array (allocaArray, peekArray, withArrayLen, pokeArray) import Foreign.Marshal.Utils (with)@@ -123,8 +124,8 @@ -- | Monadic computation to read from open archive entries. -- See 'fromFile' and 'fromFileIx'. type Entry a = StateT- (ZipFile,Int,[FileFlag]) -- (file, position index, access flags)- (StateT Zip IO) -- archive monad+ (ZipFile,Integer,[FileFlag]) -- (file, position index, access flags)+ (StateT Zip IO) -- archive monad a --@@ -152,14 +153,14 @@ else return r -- | Get the number of entries in the archive.-numFiles :: Archive Int-numFiles = do+numFiles :: [FileFlag] -> Archive Integer+numFiles flags = do z <- getZip- lift $ fromIntegral `liftM` c'zip_get_num_files z+ lift $ fromIntegral `liftM` c'zip_get_num_entries z (combine flags) -- | Get name of an entry in the archive by its index. fileName :: [FileFlag] -- ^ 'FileUNCHANGED' flag can be used.- -> Int -- ^ Position index of a file in the archive.+ -> Integer -- ^ Position index of a file in the archive. -> Archive FilePath -- ^ Name of the file in the archive. fileName flags i = do z <- getZip@@ -170,7 +171,7 @@ -- | Locate an entry (get its index) in the archive by its name. nameLocate :: [FileFlag] -- ^ Filename lookup mode. -> FilePath -- ^ Name of the file in the archive.- -> Archive (Maybe Int) -- ^ 'Just' position index if found.+ -> Archive (Maybe Integer) -- ^ 'Just' position index if found. nameLocate flags name = do z <- getZip lift $@@ -184,19 +185,19 @@ fileNames :: [FileFlag] -- ^ 'FileUNCHANGED' flag is accepted. -> Archive [FilePath] fileNames flags = do- n <- numFiles+ n <- numFiles flags mapM (fileName flags) [0..n-1] -- | Get size of a file in the archive. fileSize :: [FileFlag] -- ^ Filename lookup mode, 'FileUNCHANGED' can be used. -> FilePath -- ^ Name of the file in the archive.- -> Archive Int -- ^ File size.+ -> Archive Integer -- ^ File size. fileSize flags name = fileStat flags name >>= return . zs'size -- | Get size of a file in the archive (by index). fileSizeIx :: [FileFlag] -- ^ 'FileUNCHANGED' is accepted.- -> Int -- ^ Position index of a file in the archive.- -> Archive Int -- ^ File size.+ -> Integer -- ^ Position index of a file in the archive.+ -> Archive Integer -- ^ File size. fileSizeIx flags i = fileStatIx flags i >>= return . zs'size -- | Get information about a file in the archive.@@ -214,7 +215,7 @@ -- | Get information about a file in the archive (by index). fileStatIx :: [FileFlag] -- ^ 'FileUNCHANGED' can be used.- -> Int -- ^ Position index of a file in the archive.+ -> Integer -- ^ Position index of a file in the archive. -> Archive ZipStat -- ^ Information about the file. fileStatIx flags i = do z <- getZip@@ -232,7 +233,7 @@ maybe (lift $ E.throwIO ErrNOENT) deleteFileIx mbi -- | Delete file (referenced by position index) from the archive.-deleteFileIx :: Int -- ^ Position index of a file in the archive.+deleteFileIx :: Integer -- ^ Position index of a file in the archive. -> Archive () deleteFileIx i = do z <- getZip@@ -251,7 +252,7 @@ maybe (lift $ E.throwIO ErrNOENT) (\i -> renameFileIx i newname) mbi -- | Rename file (referenced by position index) in the archive.-renameFileIx :: Int -- ^ Position index of a file in the archive.+renameFileIx :: Integer -- ^ Position index of a file in the archive. -> FilePath -- ^ New name. -> Archive () renameFileIx i newname = do@@ -294,7 +295,7 @@ (\i -> replaceFileIx i src >> return ()) mbi -- | Replace a file in the archive (referenced by position index).-replaceFileIx :: Int -- ^ Position index of a file in the archive.+replaceFileIx :: Integer -- ^ Position index of a file in the archive. -> ZipSource -- ^ Source where the new file data is obtained from -> Archive () replaceFileIx i src = do@@ -320,8 +321,8 @@ -- | Create a data source from a file. sourceFile :: FilePath -- ^ File to open.- -> Int -- ^ Offset from the beginning of the file.- -> Int -- ^ The number of bytes to read. If @0@ or @-1@,+ -> Integer -- ^ Offset from the beginning of the file.+ -> Integer -- ^ The number of bytes to read. If @0@ or @-1@, -- the read till the end of file. -> Archive ZipSource sourceFile name offset len = do@@ -335,9 +336,9 @@ -- | Create a data source from a file in the zip archive. sourceZip :: [FileFlag] -- ^ 'FileUNCHANGED' and 'FileRECOMPRESS' can be used. -> Zip -- ^ Source archive.- -> Int -- ^ Position index of a file in the source archive.- -> Int -- ^ Offset from the beginning of the file.- -> Int -- ^ The number of bytes to read. If @0@ or @-1@,+ -> Integer -- ^ Position index of a file in the source archive.+ -> Integer -- ^ Offset from the beginning of the file.+ -> Integer -- ^ The number of bytes to read. If @0@ or @-1@, -- then read till the end of file. -> Archive ZipSource sourceZip flags srcz srcidx offset len = do@@ -351,8 +352,8 @@ -- | Create a data source from a 'PureSource'. -- Note: input of @[a]@ is converted to @[Word8]@ internally.-sourcePure :: (Enum a, Storable a, Storable st)- => PureSource a st -> Archive ZipSource+sourcePure :: (Enum a, Storable a, Storable st, Integral szt)+ => PureSource a st szt -> Archive ZipSource sourcePure pureSrc = do z <- getZip lift $ do@@ -366,18 +367,20 @@ -- | Wrapper for a user-provided pure function to be used with 'sourcePure'. -- Data size should be known in advance ('srcSize'). -- The function should support reading by chunks ('readSrc').-data PureSource a st = PureSource {- srcState :: st -- ^ Initial state of the source.- , srcSize :: Int -- ^ Total size of the data.- , srcMTime :: Maybe UTCTime -- ^ Modification time (current time if Nothing).- , readSrc :: Int -> st -> Maybe (Int, [a], st) -- ^ Read a chunk of the data,- -- return @Just@ the size of data read, the data themselves and- -- the new state of the source, or @Nothing@ on error.+data PureSource a st szt = PureSource {+ srcState :: st -- ^ Initial state of the source.+ , srcSize :: szt -- ^ Total size of the data.+ , srcMTime :: Maybe UTCTime+ -- ^ Modification time (current time if Nothing).+ , readSrc :: szt -> st -> Maybe (szt, [a], st)+ -- ^ Read a chunk of the data, return @Just@ the size+ -- of data read, the data themselves and the new state+ -- of the source, or @Nothing@ on error. } -runPureSource :: (Enum a, Storable a, Storable st)- => PureSource a st- -> (Ptr () -> Ptr () -> CSize -> C'zip_source_cmd -> IO CSize)+runPureSource :: (Enum a, Storable a, Storable st, Integral szt) =>+ PureSource a st szt+ -> (Ptr () -> Ptr () -> CULLong -> C'zip_source_cmd -> IO CULLong) runPureSource src pState pData len cmd | cmd == c'ZIP_SOURCE_OPEN = return 0 | cmd == c'ZIP_SOURCE_READ = do@@ -451,7 +454,7 @@ -- | Get comment for a file in the archive (referenced by position index). getFileCommentIx :: [FileFlag] -- ^ FileUNCHANGED can be used.- -> Int -- ^ Position index of the file.+ -> Integer -- ^ Position index of the file. -> Archive (Maybe String) getFileCommentIx flags i = do z <- getZip@@ -473,7 +476,7 @@ maybe (lift $ E.throwIO ErrNOENT) (flip setFileCommentIx comment) mbi -- | Set comment for a file in the archive (referenced by position index).-setFileCommentIx :: Int -- ^ Position index of a file in the archive.+setFileCommentIx :: Integer -- ^ Position index of a file in the archive. -> String -- ^ New file comment. -> Archive () setFileCommentIx i comment = do@@ -493,7 +496,7 @@ maybe (lift $ E.throwIO ErrNOENT) removeFileCommentIx mbi -- | Remove comment for a file in the archive (referenced by position index).-removeFileCommentIx :: Int -- ^ Position index of a file in the archive.+removeFileCommentIx :: Integer -- ^ Position index of a file in the archive. -> Archive () removeFileCommentIx i = do z <- getZip@@ -511,7 +514,7 @@ maybe (lift $ E.throw ErrNOENT) unchangeFileIx mbi -- | Undo changes to a file in the archive (referenced by position index).-unchangeFileIx :: Int -- ^ Position index of a file in the archive.+unchangeFileIx :: Integer -- ^ Position index of a file in the archive. -> Archive () unchangeFileIx i = do z <- getZip@@ -576,7 +579,7 @@ -- an 'Archive' action (see also 'withArchive'). 'fromFileIx' can be replaced -- with 'fileContentsIx' to read an entire file at once. fromFileIx :: [FileFlag] -- ^ 'FileCOMPRESSED' and 'FileUNCHANGED' can be used.- -> Int -- ^ Position index of a file in the archive.+ -> Integer -- ^ Position index of a file in the archive. -> Entry a -- ^ Action with the file. -> Archive a fromFileIx flags i action = do@@ -594,11 +597,14 @@ -- | Read at most @n@ bytes from the file. readBytes :: (Enum a)- => Int -- ^ The number of bytes to read.+ => Integer -- ^ The number of bytes to read. -> Entry [a] -- ^ Bytes read. readBytes n = do+ lift . lift $+ when (n > toInteger (maxBound::Int))+ (E.throwIO ErrMEMORY) -- allocaArray can't allocate > (maxBound::Int) (zf,_,_) <- get- lift . lift $ allocaArray n $ \buf -> do+ lift . lift $ allocaArray (fromIntegral n) $ \buf -> do nread <- c'zip_fread zf (castPtr buf) (fromIntegral n) if nread < 0 then@@ -608,7 +614,7 @@ return . map (toEnum . fromEnum) $ bs -- | Skip @n@ bytes from the open file. Note: this is not faster than reading.-skipBytes :: Int -> Entry ()+skipBytes :: Integer -> Entry () skipBytes n = (readBytes n :: Entry [Word8]) >> return () -- | Read entire file contents.@@ -631,7 +637,7 @@ -- 'readContents' from within 'Archive' monad. fileContentsIx :: (Enum a) => [FileFlag]- -> Int+ -> Integer -> Archive [a] fileContentsIx flags i = fromFileIx flags i readContents
− Codec/Archive/LibZip/LegacyZeroZero.hsc
@@ -1,183 +0,0 @@--- | This module is a backwards compatible replacement for @Codec.Archive.LibZip@ module of LibZip 0.0.x. This API is deprecated, please don't use it in new code.-module Codec.Archive.LibZip.LegacyZeroZero- {-# DEPRECATED "Please upgrade to monadic Codec.Archive.LibZip" #-}- (- -- * Types- Zip,ZipFile,OpenFlag(..),FileFlag(..),ZipError(..)- ,Word8- -- * High-level interface- ,withZip,getFiles,getFileSize- ,readZipFile,readZipFile'- ,readZipFileHead,readZipFileHead'- -- * Low-level bindings- ,open,close,get_num_files,get_name- ,fopen,fopen_index,fclose,fread- -- * Utilities- ,catchZipError,isFile,isDir- ) where--import Control.Monad (liftM)-import Data.Word (Word8)-import Foreign.C.String (withCString,peekCString)-import Foreign.Marshal.Alloc (alloca)-import Foreign.Marshal.Array (allocaArray, peekArray)-import Foreign.Ptr (Ptr, nullPtr, castPtr)-import Foreign.Storable (peek)-import qualified Control.Exception as E-import qualified Data.ByteString as B--import Bindings.LibZip-import Codec.Archive.LibZip.Types-import Codec.Archive.LibZip.Errors---- | Open zip archive specified by /path/ and return its handler on success.-open :: String -- ^ /path/ of the file to open- -> [OpenFlag] -- ^ open mode- -> IO Zip -- ^ handler of the open zip archive-open path flags =- withCString path $ \path' ->- alloca $ \errp -> do- z <- c'zip_open path' (combine flags) errp- if z /= nullPtr- then return z- else peek errp >>= E.throwIO . errFromCInt---- | Close zip archive.-close :: Zip -> IO ()-close z | z == nullPtr = E.throwIO ErrINVAL-close z = do- r <- c'zip_close z- if r == 0- then return ()- else E.throwIO =<< get_error z---- | Return the number of files in the archive.-get_num_files :: Zip -> IO Int-get_num_files z | z == nullPtr = E.throwIO ErrINVAL-get_num_files z = fromIntegral `liftM` c'zip_get_num_files z---- | Get name of file by index.-get_name :: Zip -> Int -> [FileFlag] -> IO String-get_name z _ _ | z == nullPtr = E.throwIO ErrINVAL-get_name z i flags = do- n <- c'zip_get_name z (fromIntegral i) (combine flags)- if n /= nullPtr- then peekCString n- else E.throwIO =<< get_error z---- | Open file in zip archive for reading.-fopen :: Zip -> String -> [FileFlag] -> IO ZipFile-fopen z _ _ | z == nullPtr = E.throwIO ErrINVAL-fopen z fn flags = withCString fn $ \fn' ->- returnNotNull z =<< c'zip_fopen z fn' (combine flags)---- | Open n-th file in zip archive for reading.-fopen_index :: Zip -> Int -> [FileFlag] -> IO ZipFile-fopen_index z _ _ | z == nullPtr = E.throwIO ErrINVAL-fopen_index z i flags =- returnNotNull z =<< c'zip_fopen_index z (fromIntegral i) (combine flags)---- | Close file in zip archive.-fclose :: ZipFile -> IO ()-fclose zf =- errorOrNothing =<< c'zip_fclose zf- where errorOrNothing 0 = return ()- errorOrNothing e = E.throwIO (errFromCInt e)---- | Read from file in zip archive.-fread :: ZipFile -> Int -> IO [Word8]-fread zf count =- allocaArray count $ \buf -> do- rcount <- c'zip_fread zf (castPtr buf) (fromIntegral count)- if rcount < 0- then E.throwIO ErrREAD- else peekArray (fromIntegral rcount) buf---- High level Haskell wrappers---- | Open zip archive, do something, and close the archive.-withZip :: String -- ^ /path/ of the file to open- -> [OpenFlag] -- ^ open mode- -> (Zip -> IO a) -- ^ action to do on zip arhive- -> IO a-withZip filename flags action = do- z <- open filename flags- result <- action z- close z- return result---- | Get names of the files in archive.-getFiles :: Zip -> [FileFlag] -> IO [String]-getFiles z flags = do- n <- get_num_files z- mapM (\i -> get_name z i flags) [0..(n-1)]---- | Get size of the file in archive.-getFileSize :: Zip -- ^ zip archive- -> String -- ^ name of the file in the archive- -> [FileFlag] -- ^ file name mode- -> IO Int-getFileSize z name flags =- withCString name $ \name' ->- alloca $ \stat -> do- ret <- c'zip_stat z name' (combine flags) stat- if ret /= 0- then E.throwIO =<< get_error z- else return . fromIntegral . c'zip_stat'size =<< peek stat---- | Read uncompressed file from the archive. Produce a strict ByteString.-readZipFile :: Zip -- ^ zip archive- -> String -- ^ name of the file in the archive- -> [FileFlag] -- ^ file name mode- -> IO B.ByteString-readZipFile z fname flags = return . B.pack =<< readZipFile' z fname flags---- | Read uncompressed file from the archive. Produce a list of 'Word8'.-readZipFile' :: Zip -- ^ zip archive- -> String -- ^ name of the file in the archive- -> [FileFlag] -- ^ file name mode- -> IO [Word8]-readZipFile' z fname flags = do- sz <- getFileSize z fname flags- readZipFileHead' z fname flags sz---- | Read beginning of the uncompressed file from the archive. Produce a list of 'Word8'.-readZipFileHead' :: Zip -- ^ zip archive- -> String -- ^ name of the file in the archive- -> [FileFlag] -- ^ file name mode- -> Int -- ^ how many bytes to read- -> IO [Word8]-readZipFileHead' z fname flags n = do- f <- fopen z fname flags- bytes <- fread f n- fclose f- return bytes---- | Read beginning of the uncompressed file from the archive. Produce a strict ByteString.-readZipFileHead :: Zip -- ^ zip archive- -> String -- ^ name of the file in the archive- -> [FileFlag] -- ^ file name mode- -> Int -- ^ how many bytes to read- -> IO B.ByteString-readZipFileHead z fname flags n = return . B.pack =<< readZipFileHead' z fname flags n----- | Return True if path is a file name, not a directory name (does not end with '/').-isFile :: String -> Bool-isFile filename = (lastMay filename /= Just '/')---- | Return True if path is a directory name (ends with '/').-isDir :: String -> Bool-isDir = not . isFile--lastMay :: [a] -> Maybe a-lastMay [] = Nothing-lastMay xs = Just $ last xs---- Return the second argument or throw the last libzip error.-returnNotNull :: Zip -> Ptr a -> IO (Ptr a)-returnNotNull z _ | z == nullPtr = E.throwIO ErrINVAL-returnNotNull z ptr =- if ptr /= nullPtr- then return ptr- else E.throwIO =<< get_error z
Codec/Archive/LibZip/Types.hs view
@@ -8,6 +8,8 @@ , toZipStat , OpenFlag(..) , FileFlag(..)+ , ArchiveFlag(..)+ , CodecFlag(..) , ZipError(..) , ZipCompMethod(..) , ZipEncryptionMethod(..)@@ -18,7 +20,7 @@ import Data.Time (UTCTime) import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Data.Typeable (Typeable)-import Data.Word (Word)+import Data.Word (Word, Word32, Word64) import Foreign.C.String (peekCString) import Foreign.C.Types () import Foreign.Ptr (Ptr, nullPtr)@@ -37,19 +39,22 @@ -- | File statistics expressed in native Haskell types. data ZipStat = ZipStat {- zs'name :: String- , zs'index :: Int- , zs'crc :: Word+ zs'valid :: Word64+ , zs'name :: String+ , zs'index :: Integer+ , zs'size :: Integer+ , zs'comp_size :: Integer , zs'mtime :: UTCTime- , zs'size :: Int- , zs'comp_size :: Int+ , zs'crc :: Word , zs'comp_method :: ZipCompMethod , zs'encryption_method :: ZipEncryptionMethod+ , zs'flags :: Word32 } deriving (Show, Eq) -- | Convert marshalled stat record. toZipStat :: C'zip_stat -> IO ZipStat toZipStat s = do+ let valid = fromIntegral $ c'zip_stat'valid s let np = c'zip_stat'name s name <- if (np /= nullPtr) then peekCString np else return "" let idx = fromIntegral $ c'zip_stat'index s@@ -59,7 +64,9 @@ let comp_size = fromIntegral $ c'zip_stat'comp_size s let comp_meth = toEnum . fromIntegral $ c'zip_stat'comp_method s let enc_meth = toEnum . fromIntegral $ c'zip_stat'encryption_method s- return $ ZipStat name idx crc mtime size comp_size comp_meth enc_meth+ let flags = toEnum . fromIntegral $ c'zip_stat'flags s+ return $ ZipStat valid name idx size comp_size mtime crc+ comp_meth enc_meth flags -- | Flags for opening an archive.@@ -86,6 +93,7 @@ | FileCOMPRESSED -- ^ Read the compressed data. | FileUNCHANGED -- ^ Read the original data, ignore changes. | FileRECOMPRESS -- ^ Force recompression of data.+ | FileENCRYPTED -- ^ Read encrypted data (implies FileCOMPRESSED). deriving (Show,Eq) instance Enum FileFlag where@@ -94,13 +102,39 @@ fromEnum FileNODIR = c'ZIP_FL_NODIR fromEnum FileRECOMPRESS = c'ZIP_FL_RECOMPRESS fromEnum FileUNCHANGED = c'ZIP_FL_UNCHANGED+ fromEnum FileENCRYPTED = c'ZIP_FL_ENCRYPTED toEnum x | x == c'ZIP_FL_COMPRESSED = FileCOMPRESSED toEnum x | x == c'ZIP_FL_NOCASE = FileNOCASE toEnum x | x == c'ZIP_FL_NODIR = FileNODIR toEnum x | x == c'ZIP_FL_RECOMPRESS = FileRECOMPRESS toEnum x | x == c'ZIP_FL_UNCHANGED = FileUNCHANGED+ toEnum x | x == c'ZIP_FL_ENCRYPTED = FileENCRYPTED toEnum _ = undefined ++-- | @libzip@ archive global flags+data ArchiveFlag+ = ArchiveTORRENT+ | ArchiveRDONLY+ deriving (Show, Eq)++instance Enum ArchiveFlag where+ fromEnum ArchiveTORRENT = c'ZIP_AFL_TORRENT+ fromEnum ArchiveRDONLY = c'ZIP_AFL_RDONLY+ toEnum x | x == c'ZIP_AFL_TORRENT = ArchiveTORRENT+ toEnum x | x == c'ZIP_AFL_RDONLY = ArchiveRDONLY+ toEnum _ = undefined+++-- | @libzip@ flags for compression and encryption sources+data CodecFlag = CodecENCODE deriving (Show, Eq)++instance Enum CodecFlag where+ fromEnum CodecENCODE = c'ZIP_CODEC_ENCODE+ toEnum x | x == c'ZIP_CODEC_ENCODE = CodecENCODE+ toEnum _ = undefined++ -- | @libzip@ error codes. data ZipError = ErrOK -- ^ No error.@@ -127,6 +161,10 @@ | ErrINCONS -- ^ Zip archive inconsistent. | ErrREMOVE -- ^ Can't remove file. | ErrDELETED -- ^ Entry has been deleted.+ | ErrENCRNOTSUPP -- ^ Encryption method not supported.+ | ErrRDONLY -- ^ Read-only archive.+ | ErrNOPASSWD -- ^ No password provided.+ | ErrWRONGPASSWD -- ^ Wrong password provided. deriving (Eq, Typeable) instance Enum ZipError where@@ -154,6 +192,10 @@ fromEnum ErrWRITE = c'ZIP_ER_WRITE fromEnum ErrZIPCLOSED = c'ZIP_ER_ZIPCLOSED fromEnum ErrZLIB = c'ZIP_ER_ZLIB+ fromEnum ErrENCRNOTSUPP = c'ZIP_ER_ENCRNOTSUPP+ fromEnum ErrRDONLY = c'ZIP_ER_RDONLY+ fromEnum ErrNOPASSWD = c'ZIP_ER_NOPASSWD+ fromEnum ErrWRONGPASSWD = c'ZIP_ER_WRONGPASSWD toEnum x | x == c'ZIP_ER_CHANGED = ErrCHANGED toEnum x | x == c'ZIP_ER_CLOSE = ErrCLOSE toEnum x | x == c'ZIP_ER_COMPNOTSUPP = ErrCOMPNOTSUPP@@ -178,6 +220,10 @@ toEnum x | x == c'ZIP_ER_WRITE = ErrWRITE toEnum x | x == c'ZIP_ER_ZIPCLOSED = ErrZIPCLOSED toEnum x | x == c'ZIP_ER_ZLIB = ErrZLIB+ toEnum x | x == c'ZIP_ER_ENCRNOTSUPP = ErrENCRNOTSUPP+ toEnum x | x == c'ZIP_ER_RDONLY = ErrRDONLY+ toEnum x | x == c'ZIP_ER_NOPASSWD = ErrNOPASSWD+ toEnum x | x == c'ZIP_ER_WRONGPASSWD = ErrWRONGPASSWD toEnum _ = undefined instance E.Exception ZipError@@ -207,6 +253,10 @@ show ErrINCONS = "Zip archive inconsistent" show ErrREMOVE = "Can't remove file" show ErrDELETED = "Entry has been deleted"+ show ErrENCRNOTSUPP = "Encryption method not supported"+ show ErrRDONLY = "Read-only archive" + show ErrNOPASSWD = "No password provided"+ show ErrWRONGPASSWD = "Wrong password provided" -- | Compression methods. data ZipCompMethod@@ -281,8 +331,6 @@ toEnum x | x == c'ZIP_EM_TRAD_PKWARE = EncryptTRAD_PKWARE toEnum x | x == c'ZIP_EM_UNKNOWN = EncryptUNKNOWN toEnum _ = undefined---- | combine :: (Enum a, Num b) => [a] -> b combine fs = fromIntegral . foldr (.|.) 0 $ map fromEnum fs
LibZip.cabal view
@@ -1,5 +1,5 @@ Name: LibZip-Version: 0.2.0.4+Version: 0.10 License: BSD3 License-File: LICENSE Author: Sergey Astanin@@ -15,23 +15,22 @@ Build-Type: Simple Cabal-Version: >= 1.2.3-Tested-With: GHC == 7.0.1, GHC == 7.2.1, GHC == 7.4.1+Tested-With: GHC == 7.0.3, GHC == 7.2.2, GHC == 7.4.1 Extra-Source-Files:- examples/legacyUnzip.hs, examples/hzip.hs- , runTests.hs, Tests/Common.hs, Tests/LegacyTests.hs+ examples/hzip.hs+ , runTests.hs, Tests/Common.hs , Tests/MonadicTests.hs, Tests/test.zip Library Exposed-Modules: Codec.Archive.LibZip Codec.Archive.LibZip.Types- Codec.Archive.LibZip.LegacyZeroZero Other-Modules: Codec.Archive.LibZip.Errors Build-Depends: base >= 4.0 && < 4.6- , bindings-libzip >= 0.1 && < 0.2+ , bindings-libzip >= 0.10 && < 0.11 , bytestring , filepath , time
Tests/Common.hs view
@@ -9,7 +9,7 @@ testzip = "Tests/test.zip" testfiles = [ "hello/", "hello/world.txt" ] lastfile = last testfiles-lastfilesize = 71 :: Int+lastfilesize = 71 :: Integer world_txt = "And God saw everything that he had made,\ \ and behold, it was very good.\n"
− Tests/LegacyTests.hs
@@ -1,42 +0,0 @@-module Tests.LegacyTests- ( legacyTests- ) where--import Codec.Archive.LibZip.LegacyZeroZero--import Tests.Common--import qualified Data.ByteString as B-import Test.HUnit--legacyTests = TestList- [ "read list of files" ~: do- files <- withZip testzip [] $ \z -> getFiles z [] :: IO [String]- files @?= testfiles- , "read file size" ~: do- sz <- withZip testzip [] $ \z -> getFileSize z lastfile []- sz @?= lastfilesize- , "case-insensitive file names" ~: do- sz <- withZip testzip [] $ \z ->- getFileSize z (map2 toUpper toLower $ lastfile) [FileNOCASE]- sz @?= lastfilesize- , "open error if exists (with ExclFlag)" ~: do- err <- catchZipError- (withZip testzip [ExclFlag] $ \_ -> return ErrOK)- (return . id)- err @?= ErrEXISTS- , "read file" ~: do- txt <- withZip testzip [] $ \z -> readZipFile z lastfile []- txt @?= toByteString world_txt- , "open file by index" ~: do- txt <- withZip testzip [] $ \z -> do- f <- fopen_index z 1 [] -- index 0 is of the parent dir- bytes <- fread f (length world_txt)- return $ B.pack bytes- txt @?= toByteString world_txt- ]---toByteString :: String -> B.ByteString-toByteString s = B.pack $ map (fromIntegral . fromEnum) s-
Tests/MonadicTests.hs view
@@ -38,7 +38,8 @@ txt <- withArchive [] testzip $ fileContents [] lastfile txt @?= world_txt , "read file by index" ~: do- txt <- withArchive [] testzip $ fileContentsIx [] (length testfiles - 1)+ let i = toInteger (length testfiles - 1)+ txt <- withArchive [] testzip $ fileContentsIx [] i txt @?= world_txt , "skipBytes/readBytes" ~: do txt <- withArchive [] testzip $
examples/hzip.hs view
@@ -36,7 +36,7 @@ list :: FilePath -> IO () list archive = do stats <- withArchive [] archive $ do- n <- numFiles+ n <- numFiles [] mapM (fileStatIx []) [0..(n-1)] mapM_ printEntry stats where@@ -85,11 +85,11 @@ extract :: FilePath -> FilePath -> [FilePath] -> IO () extract outdir archive onlyFiles = withArchive [] archive $ do- n <- numFiles+ n <- numFiles [] mapM_ (extractEntry outdir onlyFiles) [0..(n-1)] -- silently overwrites existing files-extractEntry :: FilePath -> [FilePath] -> Int -> Archive ()+extractEntry :: FilePath -> [FilePath] -> Integer -> Archive () extractEntry outdir onlyFiles i = do name <- fileName [] i let fspath = joinPath [outdir, name]
− examples/legacyUnzip.hs
@@ -1,38 +0,0 @@--- A simple unzip utility.------ This is an example of using legacy LibZip-0.0 API.----module Main where--import qualified Data.ByteString as B-import Control.Monad (forM_,when)-import System.Directory (createDirectoryIfMissing)-import System.Environment (getArgs)-import System.FilePath (takeDirectory)--import Codec.Archive.LibZip--usage = "unzip [-l] file.zip [files]"--main = do- args <- getArgs- let onlyList = "-l" `elem` args- let args' = filter (/= "-l") args- case args' of- [] -> putStrLn usage- (filename:files) -> do- catchZipError $- withZip filename [] $ \z -> do- files' <- getFiles z []- forM_ files' $ \f -> do- when (f `elem` files || null files) $- if onlyList- then putStrLn f- else saveFile f =<< readZipFile z f []- $ \e -> putStrLn $ "Error in " ++ filename ++ ": " ++ show e--saveFile f contents = do- if isDir f- then createDirectoryIfMissing True $ takeDirectory f- else B.writeFile f contents-
runTests.hs view
@@ -1,12 +1,10 @@-import Tests.LegacyTests (legacyTests) import Tests.MonadicTests (monadicTests) import System.Exit import Test.HUnit allTests = TestList- [ "Legacy API" ~: legacyTests- , "Monadic API" ~: monadicTests+ [ "Monadic API" ~: monadicTests ] main = do