github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/siatest/localfile.go (about)

     1  package siatest
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"SiaPrime/crypto"
    11  	"gitlab.com/NebulousLabs/errors"
    12  	"gitlab.com/NebulousLabs/fastrand"
    13  )
    14  
    15  type (
    16  	// LocalFile is a helper struct that represents a file uploaded to the Sia
    17  	// network.
    18  	LocalFile struct {
    19  		path     string
    20  		size     int
    21  		checksum crypto.Hash
    22  	}
    23  )
    24  
    25  // NewFile creates and returns a new LocalFile. It will write size random bytes
    26  // to the file and give the file a random name.
    27  func (tn *TestNode) NewFile(size int) (*LocalFile, error) {
    28  	fileName := fmt.Sprintf("%dbytes %s", size, hex.EncodeToString(fastrand.Bytes(4)))
    29  	path := filepath.Join(tn.filesDir(), fileName)
    30  	bytes := fastrand.Bytes(size)
    31  	err := ioutil.WriteFile(path, bytes, 0600)
    32  	return &LocalFile{
    33  		path:     path,
    34  		size:     size,
    35  		checksum: crypto.HashBytes(bytes),
    36  	}, err
    37  }
    38  
    39  // Delete removes the LocalFile from disk.
    40  func (lf *LocalFile) Delete() error {
    41  	return os.Remove(lf.path)
    42  }
    43  
    44  // Move moves the file to a new random location.
    45  func (lf *LocalFile) Move() error {
    46  	// Get the new path
    47  	fileName := fmt.Sprintf("%dbytes-%s", lf.size, hex.EncodeToString(fastrand.Bytes(4)))
    48  	dir, _ := filepath.Split(lf.path)
    49  	path := filepath.Join(dir, fileName)
    50  
    51  	// Move the file
    52  	if err := os.Rename(lf.path, path); err != nil {
    53  		return err
    54  	}
    55  	lf.path = path
    56  	return nil
    57  }
    58  
    59  // checkIntegrity compares the in-memory checksum to the checksum of the data
    60  // on disk
    61  func (lf *LocalFile) checkIntegrity() error {
    62  	data, err := ioutil.ReadFile(lf.path)
    63  	if lf.size == 0 {
    64  		data = fastrand.Bytes(lf.size)
    65  	}
    66  	if err != nil {
    67  		return errors.AddContext(err, "failed to read file from disk")
    68  	}
    69  	if crypto.HashBytes(data) != lf.checksum {
    70  		return errors.New("checksums don't match")
    71  	}
    72  	return nil
    73  }
    74  
    75  // fileName returns the file name of the file on disk
    76  func (lf *LocalFile) fileName() string {
    77  	return filepath.Base(lf.path)
    78  }
    79  
    80  // partialChecksum returns the checksum of a part of the file.
    81  func (lf *LocalFile) partialChecksum(from, to uint64) (crypto.Hash, error) {
    82  	data, err := ioutil.ReadFile(lf.path)
    83  	if err != nil {
    84  		return crypto.Hash{}, errors.AddContext(err, "failed to read file from disk")
    85  	}
    86  	return crypto.HashBytes(data[from:to]), nil
    87  }