]> git.rkrishnan.org Git - functorrent.git/blobdiff - src/FuncTorrent/FileSystem.hs
FileSystem: encapsulate more filesystem functionality into the module
[functorrent.git] / src / FuncTorrent / FileSystem.hs
index 1b190ca88936b197ab3563e1fc8a1e8238629575..e064b713c68607bd05941e22e5bce8ae64d86ddb 100644 (file)
@@ -1,7 +1,7 @@
 module FuncTorrent.FileSystem
        (startThread,
         MsgChannel,
-        initFS,
+        createMsgChannel,
         Msg(..),
         Piece(..),
         pieceMapFromFile
@@ -16,10 +16,11 @@ import           Data.Map (traverseWithKey)
 
 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
@@ -30,15 +31,11 @@ data Msg = ReadPiece PieceNum Integer (MVar Piece)
 
 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
@@ -65,13 +62,16 @@ startThread handle c pieceMap = do
       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