github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/renter/proto/filesection.go (about) 1 package proto 2 3 import ( 4 "os" 5 ) 6 7 // fileSection is a helper struct that is used to split a file up in multiple 8 // sections. This guarantees that each part of the file can only write to and 9 // read from its corresponding section. 10 type fileSection struct { 11 f *os.File 12 start int64 13 end int64 14 } 15 16 // newFileSection creates a new fileSection from a file and the provided bounds 17 // of the section. 18 func newFileSection(f *os.File, start, end int64) *fileSection { 19 if start < 0 { 20 panic("filesection can't start at an index < 0") 21 } 22 if end < start && end != remainingFile { 23 panic("the end of a filesection can't be before the start") 24 } 25 return &fileSection{ 26 f: f, 27 start: start, 28 end: end, 29 } 30 } 31 32 // Close calls Close on the fileSection's underlying file. 33 func (f *fileSection) Close() error { 34 return f.f.Close() 35 } 36 37 // Size uses the underlying file's stats to return the size of the sector. 38 func (f *fileSection) Size() (int64, error) { 39 info, err := f.f.Stat() 40 if err != nil { 41 return 0, err 42 } 43 size := info.Size() - f.start 44 if size < 0 { 45 size = 0 46 } 47 if size > f.end-f.start && f.end != remainingFile { 48 size = f.end - f.start 49 } 50 return size, nil 51 } 52 53 // ReadAt calls the fileSection's underlying file's ReadAt method if the read 54 // happens within the bounds of the section. Otherwise it returns io.EOF. 55 func (f *fileSection) ReadAt(b []byte, off int64) (int, error) { 56 if off < 0 { 57 panic("can't read from an offset before the section start") 58 } 59 if f.start+off+int64(len(b)) > f.end && f.end != remainingFile { 60 panic("can't read from an offset after the section end") 61 } 62 return f.f.ReadAt(b, f.start+off) 63 } 64 65 // Sync calls Sync on the fileSection's underlying file. 66 func (f *fileSection) Sync() error { 67 return f.f.Sync() 68 } 69 70 // Truncate calls Truncate on the fileSection's underlying file. 71 func (f *fileSection) Truncate(size int64) error { 72 if f.end != remainingFile { 73 panic("can't truncate a file that has a end != remainingFile") 74 } 75 if f.start+size < f.start { 76 panic("can't truncate file to be smaller than the section start") 77 } 78 return f.f.Truncate(f.start + size) 79 } 80 81 // WriteAt calls the fileSection's underlying file's WriteAt method if the 82 // write happens within the bounds of the section. Otherwise it returns io.EOF. 83 func (f *fileSection) WriteAt(b []byte, off int64) (int, error) { 84 if off < 0 { 85 panic("can't read from an offset before the section start") 86 } 87 if f.start+off+int64(len(b)) > f.end && f.end != remainingFile { 88 panic("can't read from an offset after the section end") 89 } 90 return f.f.WriteAt(b, off+f.start) 91 }