github.com/anacrolix/torrent@v1.61.0/cmd/torrent2/main.go (about) 1 // This is an alternate to cmd/torrent which has become bloated with awful argument parsing. Since 2 // this is my most complicated binary, I will try to build something that satisfies only what I need 3 // here. 4 package main 5 6 import ( 7 "errors" 8 "fmt" 9 "io" 10 "os" 11 12 "github.com/anacrolix/bargle/v2" 13 "github.com/anacrolix/log" 14 15 "github.com/anacrolix/torrent/merkle" 16 "github.com/anacrolix/torrent/metainfo" 17 ) 18 19 func assertOk(err error) { 20 if err != nil { 21 panic(err) 22 } 23 } 24 25 func bail(str string) { 26 panic(str) 27 } 28 29 func main() { 30 err := mainErr() 31 if err != nil { 32 fmt.Fprintf(os.Stderr, "%v\n", err) 33 os.Exit(1) 34 } 35 } 36 37 func mainErr() error { 38 p := bargle.NewParser() 39 defer p.DoHelpIfHelping() 40 runMap := func(m map[string]func()) { 41 for key, value := range m { 42 if p.Parse(bargle.Keyword(key)) { 43 value() 44 return 45 } 46 } 47 p.Fail() 48 } 49 parseFileName := func() (ret string) { 50 if p.Parse(bargle.Positional("file", bargle.BuiltinUnmarshaler(&ret))) { 51 return 52 } 53 p.SetError(errors.New("file not specified")) 54 panic(p.Fail()) 55 } 56 runMap(map[string]func(){ 57 "metainfo": func() { 58 runMap(map[string]func(){ 59 "validate-v2": func() { 60 mi, err := metainfo.LoadFromFile(parseFileName()) 61 assertOk(err) 62 info, err := mi.UnmarshalInfo() 63 assertOk(err) 64 if !info.HasV2() { 65 bail("not a v2 torrent") 66 } 67 err = metainfo.ValidatePieceLayers(mi.PieceLayers, &info.FileTree, info.PieceLength) 68 assertOk(err) 69 }, 70 "pprint": func() { 71 mi, err := metainfo.LoadFromFile(parseFileName()) 72 assertOk(err) 73 info, err := mi.UnmarshalInfo() 74 assertOk(err) 75 fmt.Printf("name: %q\n", info.Name) 76 fmt.Printf("# files:\n") 77 files := info.UpvertedFiles() 78 pieceIndex := 0 79 for _, f := range files { 80 numPieces := int((f.Length + info.PieceLength - 1) / info.PieceLength) 81 endIndex := pieceIndex + numPieces 82 hash := "no v2 pieces root" 83 for a := range f.PiecesRoot.Iter { 84 hash = a.HexString() 85 } 86 fmt.Printf( 87 "%s: %v: pieces (%v-%v)\n", 88 hash, 89 func() any { 90 if info.IsDir() { 91 return fmt.Sprintf("%q", f.BestPath()) 92 } 93 return "(single file torrent)" 94 }(), 95 pieceIndex, 96 endIndex-1, 97 ) 98 pieceIndex = endIndex 99 } 100 }, 101 }) 102 }, 103 "merkle": func() { 104 h := merkle.NewHash() 105 n, err := io.Copy(h, os.Stdin) 106 log.Printf("copied %v bytes", n) 107 if err != nil { 108 panic(err) 109 } 110 fmt.Printf("%x\n", h.Sum(nil)) 111 }, 112 }) 113 p.FailIfArgsRemain() 114 return p.Err() 115 }