mirror of
https://github.com/containers/podman.git
synced 2025-08-24 01:50:58 +08:00
Initial checkin from CRI-O repo
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
This commit is contained in:
140
utils/utils.go
Normal file
140
utils/utils.go
Normal file
@ -0,0 +1,140 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
systemdDbus "github.com/coreos/go-systemd/dbus"
|
||||
"github.com/godbus/dbus"
|
||||
)
|
||||
|
||||
// ExecCmd executes a command with args and returns its output as a string along
|
||||
// with an error, if any
|
||||
func ExecCmd(name string, args ...string) (string, error) {
|
||||
cmd := exec.Command(name, args...)
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("`%v %v` failed: %v %v (%v)", name, strings.Join(args, " "), stderr.String(), stdout.String(), err)
|
||||
}
|
||||
|
||||
return stdout.String(), nil
|
||||
}
|
||||
|
||||
// ExecCmdWithStdStreams execute a command with the specified standard streams.
|
||||
func ExecCmdWithStdStreams(stdin io.Reader, stdout, stderr io.Writer, name string, args ...string) error {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdin = stdin
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("`%v %v` failed: %v", name, strings.Join(args, " "), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StatusToExitCode converts wait status code to an exit code
|
||||
func StatusToExitCode(status int) int {
|
||||
return ((status) & 0xff00) >> 8
|
||||
}
|
||||
|
||||
// RunUnderSystemdScope adds the specified pid to a systemd scope
|
||||
func RunUnderSystemdScope(pid int, slice string, unitName string) error {
|
||||
var properties []systemdDbus.Property
|
||||
conn, err := systemdDbus.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
properties = append(properties, systemdDbus.PropSlice(slice))
|
||||
properties = append(properties, newProp("PIDs", []uint32{uint32(pid)}))
|
||||
properties = append(properties, newProp("Delegate", true))
|
||||
properties = append(properties, newProp("DefaultDependencies", false))
|
||||
ch := make(chan string)
|
||||
_, err = conn.StartTransientUnit(unitName, "replace", properties, ch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Block until job is started
|
||||
<-ch
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newProp(name string, units interface{}) systemdDbus.Property {
|
||||
return systemdDbus.Property{
|
||||
Name: name,
|
||||
Value: dbus.MakeVariant(units),
|
||||
}
|
||||
}
|
||||
|
||||
// DetachError is special error which returned in case of container detach.
|
||||
type DetachError struct{}
|
||||
|
||||
func (DetachError) Error() string {
|
||||
return "detached from container"
|
||||
}
|
||||
|
||||
// CopyDetachable is similar to io.Copy but support a detach key sequence to break out.
|
||||
func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
|
||||
if len(keys) == 0 {
|
||||
// Default keys : ctrl-p ctrl-q
|
||||
keys = []byte{16, 17}
|
||||
}
|
||||
|
||||
buf := make([]byte, 32*1024)
|
||||
for {
|
||||
nr, er := src.Read(buf)
|
||||
if nr > 0 {
|
||||
preservBuf := []byte{}
|
||||
for i, key := range keys {
|
||||
preservBuf = append(preservBuf, buf[0:nr]...)
|
||||
if nr != 1 || buf[0] != key {
|
||||
break
|
||||
}
|
||||
if i == len(keys)-1 {
|
||||
// src.Close()
|
||||
return 0, DetachError{}
|
||||
}
|
||||
nr, er = src.Read(buf)
|
||||
}
|
||||
var nw int
|
||||
var ew error
|
||||
if len(preservBuf) > 0 {
|
||||
nw, ew = dst.Write(preservBuf)
|
||||
nr = len(preservBuf)
|
||||
} else {
|
||||
nw, ew = dst.Write(buf[0:nr])
|
||||
}
|
||||
if nw > 0 {
|
||||
written += int64(nw)
|
||||
}
|
||||
if ew != nil {
|
||||
err = ew
|
||||
break
|
||||
}
|
||||
if nr != nw {
|
||||
err = io.ErrShortWrite
|
||||
break
|
||||
}
|
||||
}
|
||||
if er != nil {
|
||||
if er != io.EOF {
|
||||
err = er
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return written, err
|
||||
}
|
Reference in New Issue
Block a user