github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/os/shell.go (about)

     1  package os
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"os/exec"
     8  	"path"
     9  
    10  	log "github.com/sirupsen/logrus"
    11  	"path/filepath"
    12  )
    13  
    14  func RunLogCommand(name string, args ...string) error {
    15  	log.WithFields(log.Fields{"cmd": name, "args": args}).Debug("running " + name)
    16  
    17  	out, err := exec.Command(name, args...).CombinedOutput()
    18  	if err != nil {
    19  		log.WithFields(log.Fields{"out": string(out)}).Error(name + " failed")
    20  
    21  	}
    22  	return err
    23  }
    24  
    25  func GetDirSize(dir string) (int64, error) {
    26  
    27  	stat, err := os.Stat(dir)
    28  	if err != nil {
    29  		return 0, err
    30  	}
    31  
    32  	if !stat.IsDir() {
    33  		return stat.Size(), nil
    34  	} else {
    35  		entries, err := listDir(dir)
    36  		if err != nil {
    37  			return 0, err
    38  		}
    39  		var sum int64 = 0
    40  		for _, obj := range entries {
    41  			curSize, err := GetDirSize(path.Join(dir, obj.Name()))
    42  			if err != nil {
    43  				return 0, err
    44  			}
    45  			sum += curSize
    46  		}
    47  		return sum, nil
    48  
    49  	}
    50  
    51  }
    52  
    53  func listDir(path string) ([]os.FileInfo, error) {
    54  	directory, err := os.Open(path)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	defer directory.Close()
    59  	return directory.Readdir(-1)
    60  }
    61  
    62  // https://www.socketloop.com/tutorials/golang-copy-directory-including-sub-directories-files
    63  
    64  func CopyDir(source string, dest string) (err error) {
    65  	// get properties of source dir
    66  	sourceinfo, err := os.Stat(source)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	// create dest dir
    72  
    73  	err = os.MkdirAll(dest, sourceinfo.Mode())
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	directory, _ := os.Open(source)
    79  
    80  	objects, err := directory.Readdir(-1)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	for _, obj := range objects {
    86  
    87  		sourcefilepointer := path.Join(source, obj.Name())
    88  
    89  		destinationfilepointer := path.Join(dest, obj.Name())
    90  
    91  		sfi, err := os.Stat(sourcefilepointer)
    92  		if err != nil {
    93  			return err
    94  		}
    95  		if sfi.IsDir() {
    96  			// create sub-directories - recursively
    97  			err = CopyDir(sourcefilepointer, destinationfilepointer)
    98  			if err != nil {
    99  				return err
   100  			}
   101  		} else {
   102  			// perform copy
   103  			err = CopyFile(sourcefilepointer, destinationfilepointer)
   104  			if err != nil {
   105  				return err
   106  			}
   107  		}
   108  	}
   109  
   110  	return
   111  }
   112  
   113  /// http://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file-in-golang/21067803#21067803
   114  
   115  // CopyFile copies a file from src to dst. If src and dst files exist, and are
   116  // the same, then return success. Otherise, attempt to create a hard link
   117  // between the two files. If that fail, copy the file contents from src to dst.
   118  func CopyFile(src, dst string) error {
   119  	sfi, err := os.Stat(src)
   120  	if err != nil {
   121  		return err
   122  	}
   123  	if !sfi.Mode().IsRegular() {
   124  		// cannot copy non-regular files (e.g., directories,
   125  		// symlinks, devices, etc.)
   126  		return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
   127  	}
   128  	dfi, err := os.Stat(dst)
   129  	if err != nil {
   130  		if !os.IsNotExist(err) {
   131  			return err
   132  		}
   133  	} else {
   134  		if !(dfi.Mode().IsRegular()) {
   135  			return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
   136  		}
   137  		if os.SameFile(sfi, dfi) {
   138  			return nil
   139  		}
   140  	}
   141  	if err = os.Link(src, dst); err == nil {
   142  		return nil
   143  	}
   144  	err = copyFileContents(src, dst)
   145  	return err
   146  }
   147  
   148  // copyFileContents copies the contents of the file named src to the file named
   149  // by dst. The file will be created if it does not already exist. If the
   150  // destination file exists, all it's contents will be replaced by the contents
   151  // of the source file.
   152  func copyFileContents(src, dst string) (err error) {
   153  	in, err := os.Open(src)
   154  	if err != nil {
   155  		return
   156  	}
   157  	defer in.Close()
   158  	out, err := os.Create(dst)
   159  	if err != nil {
   160  		return
   161  	}
   162  	defer func() {
   163  		cerr := out.Close()
   164  		if err == nil {
   165  			err = cerr
   166  		}
   167  	}()
   168  	if _, err = io.Copy(out, in); err != nil {
   169  		return
   170  	}
   171  	err = out.Sync()
   172  	return
   173  }
   174  
   175  // http://stackoverflow.com/questions/32482673/golang-how-to-get-directory-total-size
   176  func DirSize(path string) (int64, error) {
   177  	var size int64
   178  	err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
   179  		if !info.IsDir() {
   180  			size += info.Size()
   181  		}
   182  		log.Debugf("total size %v after adding file %s", (int64(size)>>20)+10, info.Name())
   183  		return err
   184  	})
   185  	return size, err
   186  }