storrent/metainfo/storage.go
2026-01-19 21:13:01 +09:00

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
}