summaryrefslogtreecommitdiff
path: root/examples/MkTorrent.hs
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-01-06 00:01:49 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-01-06 00:01:49 +0400
commita467181b6aa21b1e41d56e7772d481cbf0c37f39 (patch)
tree2f0ad59b193b1f790d38d94110dc9b83a6864901 /examples/MkTorrent.hs
parent29036b62a5da2505862c904bc069c7b0b94129e4 (diff)
Add check command to mktorrent utility
Diffstat (limited to 'examples/MkTorrent.hs')
-rw-r--r--examples/MkTorrent.hs73
1 files changed, 59 insertions, 14 deletions
diff --git a/examples/MkTorrent.hs b/examples/MkTorrent.hs
index 7bf8b513..49856f9b 100644
--- a/examples/MkTorrent.hs
+++ b/examples/MkTorrent.hs
@@ -5,10 +5,12 @@
5module Main (main) where 5module Main (main) where
6 6
7import Prelude as P 7import Prelude as P
8import Control.Concurrent.ParallelIO
8import Control.Exception 9import Control.Exception
9import Control.Lens hiding (argument) 10import Control.Lens hiding (argument)
10import Control.Monad 11import Control.Monad
11import Data.List as L 12import Data.List as L
13import Data.Maybe
12import Data.Monoid 14import Data.Monoid
13import Data.Text as T 15import Data.Text as T
14import qualified Data.Text.IO as T 16import qualified Data.Text.IO as T
@@ -24,8 +26,12 @@ import Text.PrettyPrint.Class
24 26
25import Paths_bittorrent (version) 27import Paths_bittorrent (version)
26import Data.Torrent 28import Data.Torrent
29import Data.Torrent.Bitfield as BF
30import Data.Torrent.Piece
31import Data.Torrent.Layout
27import Data.Torrent.Magnet hiding (Magnet (Magnet)) 32import Data.Torrent.Magnet hiding (Magnet (Magnet))
28import Data.Torrent.Magnet (Magnet) 33import Data.Torrent.Magnet (Magnet)
34import System.Torrent.Storage
29 35
30 36
31{----------------------------------------------------------------------- 37{-----------------------------------------------------------------------
@@ -138,27 +144,66 @@ amend (AmendOpts tpath) = do
138 toFile tpath $ a t 144 toFile tpath $ a t
139 145
140{----------------------------------------------------------------------- 146{-----------------------------------------------------------------------
141-- Check command 147-- Check command -- validate content files using torrent file
142-----------------------------------------------------------------------} 148-----------------------------------------------------------------------}
143 149
144{- 150data CheckOpts = CheckOpts
145checkOpts :: Parser CheckOpts 151 { checkTorrentPath :: FilePath -- ^ validation torrent file
146checkOpts = CheckOpts 152 , checkContentPath :: FilePath -- ^ root dir for content files
147 <$> torrentFile 153 } deriving Show
148 <*> argument Just
149 ( metavar "PATH"
150 <> value "."
151 <> help "Content directory or a single file" )
152 154
153checkInfo :: ParserInfo CheckOpts 155checkInfo :: ParserInfo CheckOpts
154checkInfo = info (helper <*> checkOpts) modifier 156checkInfo = info (helper <*> parser) modifier
155 where 157 where
156 modifier = progDesc "Validate integrity of torrent data" 158 modifier = progDesc "Validate integrity of torrent data"
159 parser = CheckOpts
160 <$> torrentFile
161 <*> argument Just
162 ( metavar "PATH"
163 <> value "."
164 <> help "Content directory or a single file"
165 )
166
167validatePiece :: Storage -> PieceInfo -> PieceIx -> IO (Maybe PieceIx)
168validatePiece s pinfo pix = do
169 valid <- verifyPiece s pinfo pix
170 if valid
171 then do infoM "check" $ "valid piece " ++ show pix
172 return (Just pix)
173 else do infoM "check" $ "invalid piece " ++ show pix
174 return Nothing
175
176validateStorage :: Storage -> PieceInfo -> IO Bitfield
177validateStorage s pinfo = do
178 infoM "check" "start storage validation"
179 let total = totalPieces s
180 pixs <- parallel $ L.map (validatePiece s pinfo) [0 .. total - 1]
181 infoM "check" "storage validation finished"
182 return $ fromList total $ catMaybes pixs
183
184-- TODO use local thread pool
185checkContent :: Storage -> PieceInfo -> IO ()
186checkContent s pinfo = do
187 invalids <- BF.complement <$> validateStorage s pinfo
188 if BF.null invalids
189 then noticeM "check" "all files are complete and valid"
190 else do
191 emergencyM "check" $ "there are some invalid pieces" ++ show invalids
192 exitFailure
193
194checkTorrent :: CheckOpts -> IO ()
195checkTorrent CheckOpts {..} = do
196 InfoDict {..} <- tInfoDict <$> fromFile checkTorrentPath
197 let layout = flatLayout checkContentPath idLayoutInfo
198 withStorage ReadOnly (piPieceLength idPieceInfo) layout $ \ s -> do
199 infoM "check" "files mapped"
200 checkContent s idPieceInfo
201 infoM "check" "unmapping files"
157 202
158{----------------------------------------------------------------------- 203{-----------------------------------------------------------------------
159-- Create command 204-- Create command
160-----------------------------------------------------------------------} 205-----------------------------------------------------------------------}
161 206{-
162createFlags :: Parser CreateFlags 207createFlags :: Parser CreateFlags
163createFlags = CreateFlags 208createFlags = CreateFlags
164 <$> optional (option 209 <$> optional (option
@@ -257,7 +302,7 @@ putTorrent opts @ ShowOpts {..} = do
257 302
258data Command 303data Command
259 = Amend AmendOpts 304 = Amend AmendOpts
260-- | Check CheckOpts 305 | Check CheckOpts
261-- | Create CreateOpts 306-- | Create CreateOpts
262 | Magnet MagnetOpts 307 | Magnet MagnetOpts
263 | Show ShowOpts 308 | Show ShowOpts
@@ -266,7 +311,7 @@ data Command
266commandOpts :: Parser Command 311commandOpts :: Parser Command
267commandOpts = subparser $ mconcat 312commandOpts = subparser $ mconcat
268 [ command "amend" (Amend <$> amendInfo) 313 [ command "amend" (Amend <$> amendInfo)
269-- , command "check" (Check <$> checkInfo) 314 , command "check" (Check <$> checkInfo)
270-- , command "create" (Create <$> createInfo) 315-- , command "create" (Create <$> createInfo)
271 , command "magnet" (Magnet <$> magnetInfo) 316 , command "magnet" (Magnet <$> magnetInfo)
272 , command "show" (Show <$> showInfo) 317 , command "show" (Show <$> showInfo)
@@ -349,7 +394,7 @@ parserInfo = info parser modifier
349 394
350run :: Command -> IO () 395run :: Command -> IO ()
351run (Amend opts) = amend opts 396run (Amend opts) = amend opts
352--run (Check opts) = checkTorrent opts 397run (Check opts) = checkTorrent opts
353--run (Create opts) = createTorrent opts 398--run (Create opts) = createTorrent opts
354run (Magnet opts) = magnet opts 399run (Magnet opts) = magnet opts
355run (Show opts) = putTorrent opts 400run (Show opts) = putTorrent opts