return l, true
}
}
+
+// Returns file segments, BitTorrent v2 aware.
+func TorrentOffsetFileSegments(info *metainfo.Info) (ret []segments.Extent) {
+ files := info.UpvertedFiles()
+ for _, fi := range files {
+ ret = append(ret, segments.Extent{fi.TorrentOffset, fi.Length})
+ }
+ return
+}
segments []Extent
}
+func NewIndexFromSegments(segments []Extent) Index {
+ return Index{segments}
+}
+
func (me Index) iterSegments() func() (Length, bool) {
return func() (Length, bool) {
if len(me.segments) == 0 {
}
}
+// Returns true if the callback returns false early, or extents are found in the index for all parts
+// of the given extent.
func (me Index) Locate(e Extent, output Callback) bool {
first := sort.Search(len(me.segments), func(i int) bool {
_e := me.segments[i]
package storage
import (
+ "github.com/anacrolix/torrent/segments"
"io"
"log"
"os"
verified := true
if c.Complete {
// If it's allegedly complete, check that its constituent files have the necessary length.
- for _, fi := range extentCompleteRequiredLengths(fs.p.Info, fs.p.Offset(), fs.p.Length()) {
- s, err := os.Stat(fs.files[fi.fileIndex].path)
- if err != nil || s.Size() < fi.length {
+ if !fs.segmentLocater.Locate(segments.Extent{
+ Start: fs.p.Offset(),
+ Length: fs.p.Length(),
+ }, func(i int, extent segments.Extent) bool {
+ file := fs.files[i]
+ s, err := os.Stat(file.path)
+ if err != nil || s.Size() < extent.Start+extent.Length {
verified = false
- break
+ return false
}
+ return true
+ }) {
+ panic("files do not cover piece extent")
}
}
}
t := &fileTorrentImpl{
files,
- segments.NewIndex(common.LengthIterFromUpvertedFiles(upvertedFiles)),
+ segments.NewIndexFromSegments(common.TorrentOffsetFileSegments(info)),
infoHash,
fs.opts.PieceCompletion,
}
if logPieceContents {
writers = append(writers, &examineBuf)
}
- _, err = storagePiece.WriteTo(io.MultiWriter(writers...))
+ var written int64
+ written, err = storagePiece.WriteTo(io.MultiWriter(writers...))
+ if err == nil && written != int64(p.length()) {
+ err = io.ErrShortWrite
+ }
if logPieceContents {
t.logger.WithDefaultLevel(log.Debug).Printf("hashed %q with copy err %v", examineBuf.Bytes(), err)
}
// http://ia600500.us.archive.org/1/items URLs in archive.org torrents.
return
}
- me.fileIndex = segments.NewIndex(common.LengthIterFromUpvertedFiles(info.UpvertedFiles()))
+ me.fileIndex = segments.NewIndexFromSegments(common.TorrentOffsetFileSegments(info))
me.info = info
me.Pieces.AddRange(0, uint64(info.NumPieces()))
}