2
0
mirror of synced 2025-02-24 14:48:27 +00:00
Milos Gajdos e6e0b227da Multiple file metainfo mode support in cmd tools
torrent-create and torrent-verify did not work correctly when a single
file is present in metainfo torrent file. torrent-create now fails if
the path passed as an argument does not exist. I've als modified
dht.go which now handles the case when an empty string is passed in
DHT bootstrap nodes slice. Finally in span.go I've sneaked in cheekily
a change which defines a type more like idiomatic Go (I have an OCD :-))
2015-05-16 13:23:33 +01:00

92 lines
2.4 KiB
Go

package main
import (
"bytes"
"crypto/sha1"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"launchpad.net/gommap"
"github.com/anacrolix/torrent/metainfo"
"github.com/anacrolix/torrent/mmap_span"
)
var (
torrentPath = flag.String("torrent", "/path/to/the.torrent", "path of the torrent file")
dataPath = flag.String("path", "/torrent/data", "path of the torrent data")
summary = flag.Bool("summary", false, "display summary at the end")
)
func verifySummary(sMap map[bool][]int) {
fmt.Println("----------------")
fmt.Println(" TORRENT-VERIFY ")
fmt.Println("----------------")
fmt.Printf("Number of correct pieces: %d\n", len(sMap[true]))
fmt.Printf("Number of wrong pieces: %d\n", len(sMap[false]))
}
func fileToMmap(filename string, length int64, devZero *os.File, mMapSpan *mmap_span.MMapSpan) {
osFile, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
mmapFd := osFile.Fd()
goMMap, err := gommap.MapRegion(mmapFd, 0, length, gommap.PROT_READ, gommap.MAP_PRIVATE)
if err != nil {
log.Fatal(err)
}
if int64(len(goMMap)) != length {
log.Printf("file mmap has wrong size: %#v", filename)
}
osFile.Close()
mMapSpan.Append(goMMap)
}
func main() {
flag.Parse()
summaryMap := make(map[bool][]int)
metaInfo, err := metainfo.LoadFromFile(*torrentPath)
if err != nil {
log.Fatal(err)
}
devZero, err := os.Open("/dev/zero")
if err != nil {
log.Print(err)
}
defer devZero.Close()
mMapSpan := &mmap_span.MMapSpan{}
if len(metaInfo.Info.Files) > 0 {
for _, file := range metaInfo.Info.Files {
filename := filepath.Join(append([]string{*dataPath, metaInfo.Info.Name}, file.Path...)...)
fileToMmap(filename, file.Length, devZero, mMapSpan)
}
log.Println(len(metaInfo.Info.Files))
} else {
fileToMmap(*dataPath, metaInfo.Info.Length, devZero, mMapSpan)
}
log.Println(mMapSpan.Size())
log.Println(len(metaInfo.Info.Pieces))
var pieceValid bool
for piece := 0; piece < (len(metaInfo.Info.Pieces)+sha1.Size-1)/sha1.Size; piece++ {
expectedHash := metaInfo.Info.Pieces[sha1.Size*piece : sha1.Size*(piece+1)]
if len(expectedHash) == 0 {
break
}
hash := sha1.New()
_, err := mMapSpan.WriteSectionTo(hash, int64(piece)*metaInfo.Info.PieceLength, metaInfo.Info.PieceLength)
if err != nil {
log.Fatal(err)
}
pieceValid = bytes.Equal(hash.Sum(nil), expectedHash)
summaryMap[pieceValid] = append(summaryMap[pieceValid], piece)
fmt.Println(piece, pieceValid)
}
if *summary {
verifySummary(summaryMap)
}
}