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  }