module Debian.Dpkg.DB (
msdbInit
, setDbDir
, pkgList
, parseVersion
, c'parseversion
, c'dpkg_version_compare
) where
import Foreign.Ptr (Ptr,FunPtr,plusPtr)
import Foreign.Ptr (wordPtrToPtr,castPtrToFunPtr)
import Foreign.Storable
import Foreign.C.Types
import Foreign.C.String (CString,CStringLen,CWString,CWStringLen)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (peekArray,pokeArray)
import Data.Int
import Data.Word
import Foreign.Ptr (nullPtr)
import Foreign.C.String (withCString, peekCString)
import Foreign.Marshal.Utils (with)
import Control.Monad (liftM, join)
import Control.Monad.Loops (unfoldrM)
import qualified Data.ByteString as BS
import Debian.Dpkg.Types
foreign import ccall unsafe "modstatdb_open" c'modstatdb_open
:: CInt -> IO ()
foreign import ccall unsafe "&modstatdb_open" p'modstatdb_open
:: FunPtr (CInt -> IO ())
foreign import ccall unsafe "push_error_context" c'push_error_context
:: IO ()
foreign import ccall unsafe "&push_error_context" p'push_error_context
:: FunPtr (IO ())
foreign import ccall unsafe "dpkg_set_progname" c'dpkg_set_progname
:: CString -> IO ()
foreign import ccall unsafe "&dpkg_set_progname" p'dpkg_set_progname
:: FunPtr (CString -> IO ())
foreign import ccall unsafe "dpkg_db_set_dir" c'dpkg_db_set_dir
:: CString -> IO ()
foreign import ccall unsafe "&dpkg_db_set_dir" p'dpkg_db_set_dir
:: FunPtr (CString -> IO ())
foreign import ccall unsafe "pkg_db_iter_new" c'pkg_db_iter_new
:: IO (Ptr C'pkgiterator)
foreign import ccall unsafe "&pkg_db_iter_new" p'pkg_db_iter_new
:: FunPtr (IO (Ptr C'pkgiterator))
foreign import ccall unsafe "pkg_db_iter_next_pkg" c'pkg_db_iter_next_pkg
:: Ptr C'pkgiterator -> IO (Ptr C'pkginfo)
foreign import ccall unsafe "&pkg_db_iter_next_pkg" p'pkg_db_iter_next_pkg
:: FunPtr (Ptr C'pkgiterator -> IO (Ptr C'pkginfo))
msdbInit :: IO ()
msdbInit = do
c'push_error_context
c'modstatdb_open 0
withCString "haskell-dpkg" c'dpkg_set_progname
setDbDir :: String -> IO ()
setDbDir x = withCString x c'dpkg_db_set_dir
pkgDbIterNext :: Ptr C'pkgiterator -> IO (Maybe (Ptr C'pkginfo, Ptr C'pkgiterator))
pkgDbIterNext i = do
pptr <- c'pkg_db_iter_next_pkg i
if pptr == nullPtr
then
return Nothing
else
return $ Just (pptr, i)
pkgpList :: IO [Ptr C'pkginfo]
pkgpList = c'pkg_db_iter_new >>= unfoldrM (pkgDbIterNext)
pkgList :: IO [C'pkginfo]
pkgList = pkgpList >>= mapM peek
foreign import ccall unsafe "parseversion" c'parseversion
:: Ptr C'dpkg_version -> CString -> Ptr C'dpkg_error -> IO CInt
foreign import ccall unsafe "&parseversion" p'parseversion
:: FunPtr (Ptr C'dpkg_version -> CString -> Ptr C'dpkg_error -> IO CInt)
foreign import ccall unsafe "dpkg_version_compare" c'dpkg_version_compare
:: Ptr C'dpkg_version -> Ptr C'dpkg_version -> IO CInt
foreign import ccall unsafe "&dpkg_version_compare" p'dpkg_version_compare
:: FunPtr (Ptr C'dpkg_version -> Ptr C'dpkg_version -> IO CInt)
parseVersion :: BS.ByteString -> IO (Either String C'dpkg_version)
parseVersion verstr = BS.useAsCString verstr $ \vercstr -> alloca $ \vrptr -> alloca $ \deptr -> do
i <- c'parseversion vrptr vercstr deptr
vr <- peek vrptr
if i == 0
then
return $ Right vr
else
do
de <- peek deptr
errmsg <- peekCString (c'dpkg_error'str de)
if (c'dpkg_error'type de) == 1
then
return $ Right vr
else
return $ Left errmsg