packages feed

halfs-2.0: System/Device/File.hs

{-# LANGUAGE BangPatterns #-}
module System.Device.File(
         newFileBlockDevice
       )
 where

import qualified Data.ByteString as BS
import Data.Word
import System.IO

import System.Device.BlockDevice

-- |Use an existing file (specified by the first argument) as a block device.
-- The second argument is the block size for the pseudo-disk.
newFileBlockDevice :: FilePath -> Word64 -> IO (Maybe (BlockDevice IO))
newFileBlockDevice fname secSize = do
  hndl          <- openFile fname ReadWriteMode
  sizeBytes     <- hFileSize hndl
  let numBlocks =  fromIntegral sizeBytes `div` secSize
  return $! Just BlockDevice {
    bdBlockSize  = secSize
  , bdNumBlocks  = numBlocks
  , bdReadBlock  = \ i -> do
                    hSeek hndl AbsoluteSeek (fromIntegral $ i * secSize)
                    v <- BS.hGet hndl secSizeInt
                    let v' = BS.take secSize64 $ v `BS.append` empty
                    return v'
  , bdWriteBlock = \ i !v -> do
                    let v' = BS.take secSize64 $ v `BS.append` empty
                    hSeek hndl AbsoluteSeek (fromIntegral $ i * secSize)
                    BS.hPut hndl v'
  , bdFlush      = hFlush hndl
  , bdShutdown   = hClose hndl
  }
 where 
  secSizeI   = fromIntegral secSize
  secSizeInt = fromIntegral secSize
  secSize64  = fromIntegral secSize
  empty      = BS.replicate secSizeI 0