module FuncTorrent.FileSystem
(startThread,
MsgChannel,
- initFS,
+ createMsgChannel,
Msg(..),
Piece(..),
pieceMapFromFile
import qualified Data.ByteString as BS
import Data.Map ((!))
-import System.IO (Handle, openFile, IOMode (ReadWriteMode))
+import System.IO (Handle, IOMode (ReadWriteMode), withFile)
+import System.Directory (doesFileExist)
import FuncTorrent.PieceManager (PieceDlState(..), PieceData(..), PieceMap, pieceNumToOffset)
-import FuncTorrent.Utils (readFileAtOffset, writeFileAtOffset, verifyHash)
+import FuncTorrent.Utils (createDummyFile, readFileAtOffset, writeFileAtOffset, verifyHash)
type PieceNum = Integer
data Piece = Piece PieceNum BS.ByteString
type MsgChannel = Chan Msg
--- init :: FileName -> IO (Handle, MsgChannel)
-initFS :: FilePath -> IO (Handle, MsgChannel)
-initFS filepath = do
- c <- newChan
- h <- openFile filepath ReadWriteMode
- return (h, c)
+createMsgChannel :: IO (Chan Msg)
+createMsgChannel = newChan
-startThread :: Handle -> MsgChannel -> PieceMap -> IO ThreadId
-startThread handle c pieceMap = do
+startThread :: PieceMap -> MsgChannel -> Handle -> IO ThreadId
+startThread pieceMap c handle = do
forkIO $ forever $ recvMsg >>= sendResponse
where
recvMsg = readChan c
bs' <- readFileAtOffset handle offset len'
return $ verifyHash bs' hash'
-pieceMapFromFile :: Handle -> PieceMap -> IO PieceMap
-pieceMapFromFile handle pieceMap = do
- traverseWithKey f pieceMap
+pieceMapFromFile :: FilePath -> Integer -> PieceMap -> IO PieceMap
+pieceMapFromFile filePath fileLen pieceMap = do
+ dfe <- doesFileExist filePath
+ if dfe
+ then traverseWithKey f pieceMap
+ else createDummyFile filePath (fromIntegral fileLen) >> return pieceMap
where
f k v = do
let offset = pieceNumToOffset pieceMap k
- isHashValid <- flip verifyHash (hash v) <$> readFileAtOffset handle offset (len v)
+ isHashValid <- flip verifyHash (hash v) <$> withFile filePath ReadWriteMode (\handle -> readFileAtOffset handle offset (len v))
if isHashValid
then return $ v { dlstate = Have }
else return v