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 }