]> Sergey Matveev's repositories - btrtrc.git/blob - data/file/file.go
Ditch Data.WriteSectionTo, and fix cmd/torrent-verify
[btrtrc.git] / data / file / file.go
1 package file
2
3 import (
4         "io"
5         "os"
6         "path/filepath"
7
8         "github.com/anacrolix/torrent/metainfo"
9 )
10
11 type data struct {
12         info      *metainfo.Info
13         loc       string
14         completed []bool
15 }
16
17 func TorrentData(md *metainfo.Info, location string) data {
18         return data{md, location, make([]bool, md.NumPieces())}
19 }
20
21 func (me data) Close() {}
22
23 func (me data) PieceComplete(piece int) bool {
24         return me.completed[piece]
25 }
26
27 func (me data) PieceCompleted(piece int) error {
28         me.completed[piece] = true
29         return nil
30 }
31
32 func (me data) ReadAt(p []byte, off int64) (n int, err error) {
33         for _, fi := range me.info.UpvertedFiles() {
34                 if off >= fi.Length {
35                         off -= fi.Length
36                         continue
37                 }
38                 n1 := len(p)
39                 if int64(n1) > fi.Length-off {
40                         n1 = int(fi.Length - off)
41                 }
42                 var f *os.File
43                 f, err = os.Open(me.fileInfoName(fi))
44                 if os.IsNotExist(err) {
45                         err = io.ErrUnexpectedEOF
46                 }
47                 if err != nil {
48                         return
49                 }
50                 n1, err = f.ReadAt(p[:n1], off)
51                 f.Close()
52                 if err != nil {
53                         return
54                 }
55                 n += n1
56                 off = 0
57                 p = p[n1:]
58                 if len(p) == 0 {
59                         return
60                 }
61         }
62         err = io.EOF
63         return
64 }
65
66 func (me data) WriteAt(p []byte, off int64) (n int, err error) {
67         for _, fi := range me.info.UpvertedFiles() {
68                 if off >= fi.Length {
69                         off -= fi.Length
70                         continue
71                 }
72                 n1 := len(p)
73                 if int64(n1) > fi.Length-off {
74                         n1 = int(fi.Length - off)
75                 }
76                 name := me.fileInfoName(fi)
77                 os.MkdirAll(filepath.Dir(name), 0770)
78                 var f *os.File
79                 f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0660)
80                 if err != nil {
81                         return
82                 }
83                 n1, err = f.WriteAt(p[:n1], off)
84                 f.Close()
85                 if err != nil {
86                         return
87                 }
88                 n += n1
89                 off = 0
90                 p = p[n1:]
91                 if len(p) == 0 {
92                         break
93                 }
94         }
95         return
96 }
97
98 func (me data) fileInfoName(fi metainfo.FileInfo) string {
99         return filepath.Join(append([]string{me.loc, me.info.Name}, fi.Path...)...)
100 }