github.com/hairyhenderson/templater@v3.5.0+incompatible/file/file.go (about)

     1  // Package file contains functions for working with files and directories on the local filesystem
     2  package file
     3  
     4  import (
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/spf13/afero"
    13  )
    14  
    15  // for overriding in tests
    16  var fs = afero.NewOsFs()
    17  
    18  // Read -
    19  func Read(filename string) (string, error) {
    20  	inFile, err := fs.OpenFile(filename, os.O_RDONLY, 0)
    21  	if err != nil {
    22  		return "", errors.Wrapf(err, "failed to open %s", filename)
    23  	}
    24  	// nolint: errcheck
    25  	defer inFile.Close()
    26  	bytes, err := ioutil.ReadAll(inFile)
    27  	if err != nil {
    28  		err = errors.Wrapf(err, "read failed for %s", filename)
    29  		return "", err
    30  	}
    31  	return string(bytes), nil
    32  }
    33  
    34  // ReadDir -
    35  func ReadDir(path string) ([]string, error) {
    36  	f, err := fs.Open(path)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	i, err := f.Stat()
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	if i.IsDir() {
    45  		return f.Readdirnames(0)
    46  	}
    47  	return nil, errors.New("file is not a directory")
    48  }
    49  
    50  // Write a
    51  func Write(filename string, content []byte) error {
    52  	err := assertPathInWD(filename)
    53  	if err != nil {
    54  		return errors.Wrapf(err, "failed to open %s", filename)
    55  	}
    56  
    57  	fi, err := os.Stat(filename)
    58  	if err != nil && !os.IsNotExist(err) {
    59  		return errors.Wrapf(err, "failed to stat %s", filename)
    60  	}
    61  	mode := os.FileMode(0644)
    62  	if fi != nil {
    63  		mode = fi.Mode()
    64  	}
    65  	err = fs.MkdirAll(filepath.Dir(filename), 0755)
    66  	if err != nil {
    67  		return errors.Wrapf(err, "failed to make dirs for %s", filename)
    68  	}
    69  	inFile, err := fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
    70  	if err != nil {
    71  		return errors.Wrapf(err, "failed to open %s", filename)
    72  	}
    73  	n, err := inFile.Write(content)
    74  	if err != nil {
    75  		return errors.Wrapf(err, "failed to write %s", filename)
    76  	}
    77  	if n != len(content) {
    78  		return errors.Wrapf(err, "short write on %s (%d bytes)", filename, n)
    79  	}
    80  	return nil
    81  }
    82  
    83  func assertPathInWD(filename string) error {
    84  	wd, err := os.Getwd()
    85  	if err != nil {
    86  		return err
    87  	}
    88  	f, err := filepath.Abs(filename)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	r, err := filepath.Rel(wd, f)
    93  	if err != nil {
    94  		return err
    95  	}
    96  	if strings.HasPrefix(r, "..") {
    97  		return errors.Errorf("path %s not contained by working directory %s (rel: %s)", filename, wd, r)
    98  	}
    99  	return nil
   100  }