{-# LINE 1 "Bio/Util/MMap.hsc" #-}
module Bio.Util.MMap ( mmapFile, createMmapFile ) where
import BasePrelude
import Foreign.C.Error ( getErrno, errnoToIOError )
import Foreign.C.Types
import System.Posix.Files ( fileSize, getFdStatus, setFdSize )
import System.Posix.IO ( openFd, closeFd, defaultFileFlags, OpenMode(ReadOnly,ReadWrite) )
import System.Posix.Types ( Fd(..), COff(..) )
mmapFile :: FilePath -> IO (Int, ForeignPtr a)
mmapFile fp =
bracket (openFd fp ReadOnly Nothing defaultFileFlags) closeFd $ \fd -> do
size <- fileSize <$> getFdStatus fd
if size <= 0
then (,) 0 <$> newForeignPtr_ nullPtr
else do
ptr <- mmap nullPtr (fromIntegral size) (1) (1) fd 0
{-# LINE 22 "Bio/Util/MMap.hsc" #-}
if ptrToIntPtr ptr == 18446744073709551615
{-# LINE 23 "Bio/Util/MMap.hsc" #-}
then do errno <- getErrno
ioError $ errnoToIOError "mmapFile" errno Nothing (Just fp)
else (,) (fromIntegral size) <$> newForeignPtrEnv my_munmap (intPtrToPtr $ fromIntegral size) ptr
createMmapFile :: FilePath -> CSize -> (Ptr a -> IO (Ptr a, b)) -> IO b
createMmapFile fp sz k =
bracket (openFd fp ReadWrite (Just 0x1b6) defaultFileFlags) closeFd $ \fd -> do
setFdSize fd (fromIntegral sz)
bracket (mmap nullPtr sz (3) (1) fd 0)
{-# LINE 35 "Bio/Util/MMap.hsc" #-}
(flip munmap sz) $ \p -> do
(p',r) <- k p
setFdSize fd (fromIntegral $ minusPtr p' p)
return r
foreign import ccall unsafe "&my_munmap" my_munmap :: FunPtr (Ptr () -> Ptr a -> IO ())
foreign import ccall unsafe "sys/mman.h mmap" mmap :: Ptr a -> CSize -> CInt -> CInt -> Fd -> COff -> IO (Ptr a)
foreign import ccall unsafe "sys/mman.h munmap" munmap :: Ptr a -> CSize -> IO ()