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 }