69 lines
1.5 KiB
Go
69 lines
1.5 KiB
Go
package metainfo
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
func (info *Info) Write(dir string, i int, data []byte) error {
|
|
off := int64(i) * info.PieceSize
|
|
if info.Size > 0 {
|
|
return writeAt(filepath.Join(dir, info.Name), off, data)
|
|
}
|
|
for _, seg := range info.Segments(off, int64(len(data))) {
|
|
f := info.Files[seg.File]
|
|
path := filepath.Join(dir, info.Name, filepath.Join(f.Path...))
|
|
if err := writeAt(path, seg.Offset, data[:seg.Size]); err != nil {
|
|
return err
|
|
}
|
|
data = data[seg.Size:]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (info *Info) Read(dir string, i int, size int64) []byte {
|
|
off := int64(i) * info.PieceSize
|
|
if info.Size > 0 {
|
|
return readAt(filepath.Join(dir, info.Name), off, size)
|
|
}
|
|
data := make([]byte, size)
|
|
pos := int64(0)
|
|
for _, seg := range info.Segments(off, size) {
|
|
f := info.Files[seg.File]
|
|
path := filepath.Join(dir, info.Name, filepath.Join(f.Path...))
|
|
chunk := readAt(path, seg.Offset, seg.Size)
|
|
if chunk == nil {
|
|
return nil
|
|
}
|
|
copy(data[pos:], chunk)
|
|
pos += seg.Size
|
|
}
|
|
return data
|
|
}
|
|
|
|
func writeAt(path string, off int64, data []byte) error {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
|
return err
|
|
}
|
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
_, err = f.WriteAt(data, off)
|
|
return err
|
|
}
|
|
|
|
func readAt(path string, off, size int64) []byte {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer f.Close()
|
|
data := make([]byte, size)
|
|
if _, err := f.ReadAt(data, off); err != nil {
|
|
return nil
|
|
}
|
|
return data
|
|
}
|