/
metainfo-generation.go
100 lines (76 loc) · 1.78 KB
/
metainfo-generation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package bittorrent
import (
"io"
"io/ioutil"
"os"
"path/filepath"
"github.com/jbitor/bencoding"
)
type CreationOptions struct {
Path string
PieceLength int64
ForceMultiFile bool
}
func GenerateTorrentMetaInfo(options CreationOptions) (TorrentMeta, error) {
fileInfo, err := os.Stat(options.Path)
if err != nil {
return nil, err
}
multiFile := fileInfo.IsDir() || options.ForceMultiFile
pieces := make([]byte, 0)
fileList := bencoding.List{}
pieceHasher := newPieceHasher(options.PieceLength)
if multiFile {
err := filepath.Walk(options.Path, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
relPath, err := filepath.Rel(options.Path, path)
if err != nil {
return err
}
pathList := bencoding.List{}
for _, component := range filepath.SplitList(relPath) {
pathList = append(pathList, bencoding.String(component))
}
fileDict := TorrentFileMeta{
"path": pathList,
"length": bencoding.Int(info.Size()),
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
pieceHasher.Write(data)
fileList = append(fileList, fileDict)
return nil
})
if err != nil {
return nil, err
}
} else {
if fileInfo.Size() > 0 {
file, err := os.Open(options.Path)
if err != nil {
return nil, err
}
defer file.Close()
io.Copy(pieceHasher.Writer(), file)
}
}
pieces = pieceHasher.Pieces()
infoDict := TorrentMeta{
"name": bencoding.String(fileInfo.Name()),
"piece length": bencoding.Int(options.PieceLength),
"pieces": bencoding.String(pieces),
}
if multiFile {
infoDict["files"] = fileList
} else {
infoDict["length"] = bencoding.Int(fileInfo.Size())
}
return infoDict, nil
}