github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/utils/utils.go (about) 1 package utils 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "os/exec" 9 "strconv" 10 "strings" 11 12 "github.com/containers/podman/v2/libpod/define" 13 "github.com/containers/storage/pkg/archive" 14 "github.com/pkg/errors" 15 "github.com/sirupsen/logrus" 16 ) 17 18 // ExecCmd executes a command with args and returns its output as a string along 19 // with an error, if any 20 func ExecCmd(name string, args ...string) (string, error) { 21 cmd := exec.Command(name, args...) 22 var stdout bytes.Buffer 23 var stderr bytes.Buffer 24 cmd.Stdout = &stdout 25 cmd.Stderr = &stderr 26 27 err := cmd.Run() 28 if err != nil { 29 return "", fmt.Errorf("`%v %v` failed: %v %v (%v)", name, strings.Join(args, " "), stderr.String(), stdout.String(), err) 30 } 31 32 return stdout.String(), nil 33 } 34 35 // ExecCmdWithStdStreams execute a command with the specified standard streams. 36 func ExecCmdWithStdStreams(stdin io.Reader, stdout, stderr io.Writer, env []string, name string, args ...string) error { 37 cmd := exec.Command(name, args...) 38 cmd.Stdin = stdin 39 cmd.Stdout = stdout 40 cmd.Stderr = stderr 41 if env != nil { 42 cmd.Env = env 43 } 44 45 err := cmd.Run() 46 if err != nil { 47 return fmt.Errorf("`%v %v` failed: %v", name, strings.Join(args, " "), err) 48 } 49 50 return nil 51 } 52 53 // ErrDetach is an error indicating that the user manually detached from the 54 // container. 55 var ErrDetach = define.ErrDetach 56 57 // CopyDetachable is similar to io.Copy but support a detach key sequence to break out. 58 func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) { 59 buf := make([]byte, 32*1024) 60 for { 61 nr, er := src.Read(buf) 62 if nr > 0 { 63 preservBuf := []byte{} 64 for i, key := range keys { 65 preservBuf = append(preservBuf, buf[0:nr]...) 66 if nr != 1 || buf[0] != key { 67 break 68 } 69 if i == len(keys)-1 { 70 return 0, ErrDetach 71 } 72 nr, er = src.Read(buf) 73 } 74 var nw int 75 var ew error 76 if len(preservBuf) > 0 { 77 nw, ew = dst.Write(preservBuf) 78 nr = len(preservBuf) 79 } else { 80 nw, ew = dst.Write(buf[0:nr]) 81 } 82 if nw > 0 { 83 written += int64(nw) 84 } 85 if ew != nil { 86 err = ew 87 break 88 } 89 if nr != nw { 90 err = io.ErrShortWrite 91 break 92 } 93 } 94 if er != nil { 95 if er != io.EOF { 96 err = er 97 } 98 break 99 } 100 } 101 return written, err 102 } 103 104 // UntarToFileSystem untars an os.file of a tarball to a destination in the filesystem 105 func UntarToFileSystem(dest string, tarball *os.File, options *archive.TarOptions) error { 106 logrus.Debugf("untarring %s", tarball.Name()) 107 return archive.Untar(tarball, dest, options) 108 } 109 110 // TarToFilesystem creates a tarball from source and writes to an os.file 111 // provided 112 func TarToFilesystem(source string, tarball *os.File) error { 113 tb, err := Tar(source) 114 if err != nil { 115 return err 116 } 117 _, err = io.Copy(tarball, tb) 118 if err != nil { 119 return err 120 } 121 logrus.Debugf("wrote tarball file %s", tarball.Name()) 122 return nil 123 } 124 125 // Tar creates a tarball from source and returns a readcloser of it 126 func Tar(source string) (io.ReadCloser, error) { 127 logrus.Debugf("creating tarball of %s", source) 128 return archive.Tar(source, archive.Uncompressed) 129 } 130 131 // RemoveScientificNotationFromFloat returns a float without any 132 // scientific notation if the number has any. 133 // golang does not handle conversion of float64s that have scientific 134 // notation in them and otherwise stinks. please replace this if you have 135 // a better implementation. 136 func RemoveScientificNotationFromFloat(x float64) (float64, error) { 137 bigNum := strconv.FormatFloat(x, 'g', -1, 64) 138 breakPoint := strings.IndexAny(bigNum, "Ee") 139 if breakPoint > 0 { 140 bigNum = bigNum[:breakPoint] 141 } 142 result, err := strconv.ParseFloat(bigNum, 64) 143 if err != nil { 144 return x, errors.Wrapf(err, "unable to remove scientific number from calculations") 145 } 146 return result, nil 147 }