{-# LANGUAGE ForeignFunctionInterface #-} module System.PIO.Linux ( FilePath, FileDescriptor, IOMode(..), fdOpen, fdClose, fdPutBuf, fdGetBuf, ) where import Foreign.Ptr(Ptr) import Foreign.C.String(CString,withCString) import Prelude hiding (FilePath) import Foreign.C.Error(throwErrno) -- | File and directory names are values of type String type FilePath = String -- | File descriptor numbers are values of type Int type FileDescriptor = Int foreign import ccall "o_rdonly" o_rdonly :: Int foreign import ccall "o_wronly" o_wronly :: Int foreign import ccall "o_rdwr" o_rdwr :: Int foreign import ccall "open" linux_open :: CString -> Int -> IO Int foreign import ccall "close" linux_close :: Int -> IO Int foreign import ccall "write" linux_write :: Int -> Ptr a -> Int -> IO Int foreign import ccall "read" linux_read :: Int -> Ptr a -> Int -> IO Int data IOMode = ReadMode | WriteMode | ReadWriteMode instance Enum IOMode where toEnum n | n == o_rdonly = ReadMode | n == o_wronly = WriteMode | n == o_rdwr = ReadWriteMode | otherwise = error "toEnum: convert error" fromEnum ReadMode = o_rdonly fromEnum WriteMode = o_wronly fromEnum ReadWriteMode = o_rdwr -- | Computation 'fdOpen' @file@ @mode@ allocates and returns a new, open -- descriptor to manage the file @file@. It manages input if @mode@ -- is 'ReadMode', output if @mode@ is 'WriteMode', -- and both input and output if mode is 'ReadWriteMode'. fdOpen :: FilePath -> IOMode -> IO FileDescriptor fdOpen path mode = withCString path $ \cpath -> linux_open cpath (fromEnum mode) >>= \fd -> case fd of -1 -> throwErrno "fdOpen" otherwise -> return fd -- | Computation 'fdClose' @fd@ makes descriptor @fd@ closed. fdClose :: FileDescriptor -> IO () fdClose fd = linux_close fd >>= \rc -> case rc of -1 -> throwErrno "fdClose" otherwise -> return () -- | 'fdPutBuf' @fd@ @buf@ @count@ writes @count@ 8-bit bytes from the -- buffer @buf@ to the descriptor @fd@. fdPutBuf :: FileDescriptor -> Ptr a -> Int -> IO () fdPutBuf fd buf bufLen = linux_write fd buf bufLen >>= \rc -> case rc of -1 -> throwErrno "fdPutBuf" otherwise -> return () -- | 'fdGetBuf' @fd@ @buf@ @count@ reads data from the descriptor @fd@ -- into the buffer @buf@ until either EOF is reached or -- @count@ 8-bit bytes have been read. fdGetBuf :: FileDescriptor -> Ptr a -> Int -> IO () fdGetBuf fd buf bufLen = linux_read fd buf bufLen >>= \rc -> case rc of -1 -> throwErrno "fdGetBuf" otherwise -> return ()