module Codec.Archive.LibZip.LegacyZeroZero
(
Zip,ZipFile,OpenFlag(..),FileFlag(..),ZipError(..)
,Word8
,withZip,getFiles,getFileSize
,readZipFile,readZipFile'
,readZipFileHead,readZipFileHead'
,open,close,get_num_files,get_name
,fopen,fopen_index,fclose,fread
,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 :: String
-> [OpenFlag]
-> IO Zip
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 -> 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
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 :: 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
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)
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)
fclose :: ZipFile -> IO ()
fclose zf =
errorOrNothing =<< c'zip_fclose zf
where errorOrNothing 0 = return ()
errorOrNothing e = E.throwIO (errFromCInt e)
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
withZip :: String
-> [OpenFlag]
-> (Zip -> IO a)
-> IO a
withZip filename flags action = do
z <- open filename flags
result <- action z
close z
return result
getFiles :: Zip -> [FileFlag] -> IO [String]
getFiles z flags = do
n <- get_num_files z
mapM (\i -> get_name z i flags) [0..(n1)]
getFileSize :: Zip
-> String
-> [FileFlag]
-> 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
readZipFile :: Zip
-> String
-> [FileFlag]
-> IO B.ByteString
readZipFile z fname flags = return . B.pack =<< readZipFile' z fname flags
readZipFile' :: Zip
-> String
-> [FileFlag]
-> IO [Word8]
readZipFile' z fname flags = do
sz <- getFileSize z fname flags
readZipFileHead' z fname flags sz
readZipFileHead' :: Zip
-> String
-> [FileFlag]
-> Int
-> IO [Word8]
readZipFileHead' z fname flags n = do
f <- fopen z fname flags
bytes <- fread f n
fclose f
return bytes
readZipFileHead :: Zip
-> String
-> [FileFlag]
-> Int
-> IO B.ByteString
readZipFileHead z fname flags n = return . B.pack =<< readZipFileHead' z fname flags n
isFile :: String -> Bool
isFile filename = (lastMay filename /= Just '/')
isDir :: String -> Bool
isDir = not . isFile
lastMay :: [a] -> Maybe a
lastMay [] = Nothing
lastMay xs = Just $ last xs
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