--import System.Posix.Fsync -- not needed with raw devices


-- | Opens the specified raw device as a LocalStoreFile, runs the provided function and closes the device.
-- Do not make concurrent calls on the same device, place concurrency in the passed function.
withRawDeviceStoreFile :: FilePath -> (LocalStoreFile -> IO a) -> ExceptT String IO a
withRawDeviceStoreFile path user =
  ExceptT $ bracket (openFd path ReadWrite Nothing $ defaultFileFlags {exclusive = True, append = True}) closeFd $
  \fd -> runExceptT $
         do fs <- lift $ getFdStatus fd
            bool (throwError "Not a raw device") (lift $ withRawFile (RawDevice fd fs 9) user) $ isCharacterDevice fs

-- | Like nesting multiple calls to 'withRawDeviceStoreFile'.
withRawDeviceStoreFile :: FilePath -> (LocalStoreFile -> IO a) -> ExceptT String IO a
withRawDeviceStoreFile path user =
  ExceptT $ bracket (openFd path ReadWrite Nothing $ defaultFileFlags {exclusive = True, append = True}) closeFd $
  \fd -> runExceptT $
         do fs <- lift $ getFdStatus fd
            bool (throwError "Not a raw device") (lift $ withRawFile (RawDevice fd fs 9) user) $ isCharacterDevice fs

-- | Like nesting multiple calls to 'withRawDeviceStoreFile'.
withRawDeviceStoreFile path user =
  ExceptT $ bracket (openFd path ReadWrite Nothing $ defaultFileFlags {exclusive = True, append = True}) closeFd $
  \fd -> runExceptT $
         do fs <- lift $ getFdStatus fd
            bool (throwError "Not a raw device") (lift $ withRawFile (RawDevice fd fs 9) user) $ isCharacterDevice fs

-- | Like nesting multiple calls to 'withRawDeviceStoreFile'.