diff options
Diffstat (limited to 'vendor/github.com')
10 files changed, 390 insertions, 149 deletions
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go index d69eab52f..4f0ffac1c 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/build.go +++ b/vendor/github.com/containers/buildah/imagebuildah/build.go @@ -293,7 +293,7 @@ func (b *Executor) Preserve(path string) error { // Try and resolve the symlink (if one exists) // Set archivedPath and path based on whether a symlink is found or not - if symLink, err := ResolveSymLink(b.mountPoint, path); err == nil { + if symLink, err := resolveSymlink(b.mountPoint, path); err == nil { archivedPath = filepath.Join(b.mountPoint, symLink) path = symLink } else { diff --git a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go index 6feedf6a5..86bf7653b 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go +++ b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go @@ -24,9 +24,7 @@ func init() { reexec.Register(symlinkModifiedTime, resolveSymlinkTimeModified) } -// main() for grandparent subprocess. Its main job is to shuttle stdio back -// and forth, managing a pseudo-terminal if we want one, for our child, the -// parent subprocess. +// main() for resolveSymlink()'s subprocess. func resolveChrootedSymlinks() { status := 0 flag.Parse() @@ -57,9 +55,9 @@ func resolveChrootedSymlinks() { os.Exit(status) } -// ResolveSymLink (in the grandparent process) resolves any symlink in filename +// resolveSymlink uses a child subprocess to resolve any symlinks in filename // in the context of rootdir. -func ResolveSymLink(rootdir, filename string) (string, error) { +func resolveSymlink(rootdir, filename string) (string, error) { // The child process expects a chroot and one path that // will be consulted relative to the chroot directory and evaluated // for any symbolic links present. @@ -253,7 +251,7 @@ func hasSymlink(path string) (bool, string, error) { } // if the symlink points to a relative path, prepend the path till now to the resolved path if !filepath.IsAbs(targetDir) { - targetDir = filepath.Join(path, targetDir) + targetDir = filepath.Join(filepath.Dir(path), targetDir) } // run filepath.Clean to remove the ".." from relative paths return true, filepath.Clean(targetDir), nil diff --git a/vendor/github.com/containers/buildah/pkg/formats/formats.go b/vendor/github.com/containers/buildah/pkg/formats/formats.go new file mode 100644 index 000000000..37f9b8a20 --- /dev/null +++ b/vendor/github.com/containers/buildah/pkg/formats/formats.go @@ -0,0 +1,171 @@ +package formats + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + "strings" + "text/tabwriter" + "text/template" + + "github.com/ghodss/yaml" + "github.com/pkg/errors" + "golang.org/x/crypto/ssh/terminal" +) + +const ( + // JSONString const to save on duplicate variable names + JSONString = "json" + // IDString const to save on duplicates for Go templates + IDString = "{{.ID}}" + + parsingErrorStr = "Template parsing error" +) + +// Writer interface for outputs +type Writer interface { + Out() error +} + +// JSONStructArray for JSON output +type JSONStructArray struct { + Output []interface{} +} + +// StdoutTemplateArray for Go template output +type StdoutTemplateArray struct { + Output []interface{} + Template string + Fields map[string]string +} + +// JSONStruct for JSON output +type JSONStruct struct { + Output interface{} +} + +// StdoutTemplate for Go template output +type StdoutTemplate struct { + Output interface{} + Template string + Fields map[string]string +} + +// YAMLStruct for YAML output +type YAMLStruct struct { + Output interface{} +} + +func setJSONFormatEncoder(isTerminal bool, w io.Writer) *json.Encoder { + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + if isTerminal { + enc.SetEscapeHTML(false) + } + return enc +} + +// Out method for JSON Arrays +func (j JSONStructArray) Out() error { + buf := bytes.NewBuffer(nil) + enc := setJSONFormatEncoder(terminal.IsTerminal(int(os.Stdout.Fd())), buf) + if err := enc.Encode(j.Output); err != nil { + return err + } + data := buf.Bytes() + + // JSON returns a byte array with a literal null [110 117 108 108] in it + // if it is passed empty data. We used bytes.Compare to see if that is + // the case. + if diff := bytes.Compare(data, []byte("null")); diff == 0 { + data = []byte("[]") + } + + // If the we did get NULL back, we should spit out {} which is + // at least valid JSON for the consumer. + fmt.Printf("%s", data) + humanNewLine() + return nil +} + +// Out method for Go templates +func (t StdoutTemplateArray) Out() error { + w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) + if strings.HasPrefix(t.Template, "table") { + // replace any spaces with tabs in template so that tabwriter can align it + t.Template = strings.Replace(strings.TrimSpace(t.Template[5:]), " ", "\t", -1) + headerTmpl, err := template.New("header").Funcs(headerFunctions).Parse(t.Template) + if err != nil { + return errors.Wrapf(err, parsingErrorStr) + } + err = headerTmpl.Execute(w, t.Fields) + if err != nil { + return err + } + fmt.Fprintln(w, "") + } + t.Template = strings.Replace(t.Template, " ", "\t", -1) + tmpl, err := template.New("image").Funcs(basicFunctions).Parse(t.Template) + if err != nil { + return errors.Wrapf(err, parsingErrorStr) + } + for i, raw := range t.Output { + basicTmpl := tmpl.Funcs(basicFunctions) + if err := basicTmpl.Execute(w, raw); err != nil { + return errors.Wrapf(err, parsingErrorStr) + } + if i != len(t.Output)-1 { + fmt.Fprintln(w, "") + continue + } + } + fmt.Fprintln(w, "") + return w.Flush() +} + +// Out method for JSON struct +func (j JSONStruct) Out() error { + data, err := json.MarshalIndent(j.Output, "", " ") + if err != nil { + return err + } + fmt.Printf("%s", data) + humanNewLine() + return nil +} + +//Out method for Go templates +func (t StdoutTemplate) Out() error { + tmpl, err := template.New("image").Parse(t.Template) + if err != nil { + return errors.Wrapf(err, "template parsing error") + } + err = tmpl.Execute(os.Stdout, t.Output) + if err != nil { + return err + } + humanNewLine() + return nil +} + +// Out method for YAML +func (y YAMLStruct) Out() error { + var buf []byte + var err error + buf, err = yaml.Marshal(y.Output) + if err != nil { + return err + } + fmt.Printf("%s", string(buf)) + humanNewLine() + return nil +} + +// humanNewLine prints a new line at the end of the output only if stdout is the terminal +func humanNewLine() { + if terminal.IsTerminal(int(os.Stdout.Fd())) { + fmt.Println() + } +} diff --git a/vendor/github.com/containers/buildah/pkg/formats/templates.go b/vendor/github.com/containers/buildah/pkg/formats/templates.go new file mode 100644 index 000000000..c2582552a --- /dev/null +++ b/vendor/github.com/containers/buildah/pkg/formats/templates.go @@ -0,0 +1,78 @@ +package formats + +import ( + "bytes" + "encoding/json" + "strings" + "text/template" +) + +// basicFunctions are the set of initial +// functions provided to every template. +var basicFunctions = template.FuncMap{ + "json": func(v interface{}) string { + buf := &bytes.Buffer{} + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + _ = enc.Encode(v) + // Remove the trailing new line added by the encoder + return strings.TrimSpace(buf.String()) + }, + "split": strings.Split, + "join": strings.Join, + "title": strings.Title, + "lower": strings.ToLower, + "upper": strings.ToUpper, + "pad": padWithSpace, + "truncate": truncateWithLength, +} + +// HeaderFunctions are used to created headers of a table. +// This is a replacement of basicFunctions for header generation +// because we want the header to remain intact. +// Some functions like `split` are irrelevant so not added. +var headerFunctions = template.FuncMap{ + "json": func(v string) string { + return v + }, + "title": func(v string) string { + return v + }, + "lower": func(v string) string { + return v + }, + "upper": func(v string) string { + return v + }, + "truncate": func(v string, l int) string { + return v + }, +} + +// Parse creates a new anonymous template with the basic functions +// and parses the given format. +func Parse(format string) (*template.Template, error) { + return NewParse("", format) +} + +// NewParse creates a new tagged template with the basic functions +// and parses the given format. +func NewParse(tag, format string) (*template.Template, error) { + return template.New(tag).Funcs(basicFunctions).Parse(format) +} + +// padWithSpace adds whitespace to the input if the input is non-empty +func padWithSpace(source string, prefix, suffix int) string { + if source == "" { + return source + } + return strings.Repeat(" ", prefix) + source + strings.Repeat(" ", suffix) +} + +// truncateWithLength truncates the source string up to the length provided by the input +func truncateWithLength(source string, length int) string { + if len(source) < length { + return source + } + return source[:length] +} diff --git a/vendor/github.com/containers/buildah/run.go b/vendor/github.com/containers/buildah/run.go index 4d6d28380..f56ce30b1 100644 --- a/vendor/github.com/containers/buildah/run.go +++ b/vendor/github.com/containers/buildah/run.go @@ -1,7 +1,6 @@ package buildah import ( - "bufio" "bytes" "encoding/json" "fmt" @@ -272,36 +271,6 @@ func addRlimits(ulimit []string, g *generate.Generator) error { return nil } -func addHosts(hosts []string, w io.Writer) error { - buf := bufio.NewWriter(w) - for _, host := range hosts { - values := strings.SplitN(host, ":", 2) - if len(values) != 2 { - return errors.Errorf("unable to parse host entry %q: incorrect format", host) - } - if values[0] == "" { - return errors.Errorf("hostname in host entry %q is empty", host) - } - if values[1] == "" { - return errors.Errorf("IP address in host entry %q is empty", host) - } - fmt.Fprintf(buf, "%s\t%s\n", values[1], values[0]) - } - return buf.Flush() -} - -func addHostsToFile(hosts []string, filename string) error { - if len(hosts) == 0 { - return nil - } - file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend) - if err != nil { - return errors.Wrapf(err, "error creating hosts file %q", filename) - } - defer file.Close() - return addHosts(hosts, file) -} - func addCommonOptsToSpec(commonOpts *CommonBuildOptions, g *generate.Generator) error { // Resources - CPU if commonOpts.CPUPeriod != 0 { @@ -638,6 +607,59 @@ func (b *Builder) addNetworkConfig(rdir, hostPath string, chownOpts *idtools.IDP return cfile, nil } +// generateHosts creates a containers hosts file +func (b *Builder) generateHosts(rdir, hostname string, addHosts []string, chownOpts *idtools.IDPair) (string, error) { + hostPath := "/etc/hosts" + stat, err := os.Stat(hostPath) + if err != nil { + return "", errors.Wrapf(err, "error statting %q for container %q", hostPath, b.ContainerID) + } + + hosts := bytes.NewBufferString("# Generated by Buildah\n") + orig, err := ioutil.ReadFile(hostPath) + if err != nil { + return "", errors.Wrapf(err, "unable to read %s", hostPath) + } + hosts.Write(orig) + for _, host := range addHosts { + // verify the host format + values := strings.SplitN(host, ":", 2) + if len(values) != 2 { + return "", errors.Errorf("unable to parse host entry %q: incorrect format", host) + } + if values[0] == "" { + return "", errors.Errorf("hostname in host entry %q is empty", host) + } + if values[1] == "" { + return "", errors.Errorf("IP address in host entry %q is empty", host) + } + hosts.Write([]byte(fmt.Sprintf("%s\t%s\n", values[1], values[0]))) + } + + if hostname != "" { + hosts.Write([]byte(fmt.Sprintf("127.0.0.1 %s\n", hostname))) + hosts.Write([]byte(fmt.Sprintf("::1 %s\n", hostname))) + } + cfile := filepath.Join(rdir, filepath.Base(hostPath)) + if err = ioutils.AtomicWriteFile(cfile, hosts.Bytes(), stat.Mode().Perm()); err != nil { + return "", errors.Wrapf(err, "error writing /etc/hosts into the container") + } + uid := int(stat.Sys().(*syscall.Stat_t).Uid) + gid := int(stat.Sys().(*syscall.Stat_t).Gid) + if chownOpts != nil { + uid = chownOpts.UID + gid = chownOpts.GID + } + if err = os.Chown(cfile, uid, gid); err != nil { + return "", errors.Wrapf(err, "error chowning file %q for container %q", cfile, b.ContainerID) + } + if err := label.Relabel(cfile, b.MountLabel, false); err != nil { + return "", errors.Wrapf(err, "error relabeling %q in container %q", cfile, b.ContainerID) + } + + return cfile, nil +} + func setupMaskedPaths(g *generate.Generator) { for _, mp := range []string{ "/proc/acpi", @@ -1081,15 +1103,11 @@ func (b *Builder) Run(command []string, options RunOptions) error { volumes := b.Volumes() if !contains(volumes, "/etc/hosts") { - hostFile, err := b.addNetworkConfig(path, "/etc/hosts", rootIDPair) + hostFile, err := b.generateHosts(path, spec.Hostname, b.CommonBuildOpts.AddHost, rootIDPair) if err != nil { return err } bindFiles["/etc/hosts"] = hostFile - - if err := addHostsToFile(b.CommonBuildOpts.AddHost, hostFile); err != nil { - return err - } } if !contains(volumes, "/etc/resolv.conf") { diff --git a/vendor/github.com/containers/psgo/internal/dev/tty.go b/vendor/github.com/containers/psgo/internal/dev/tty.go index cc7d0a422..b7d6f28ac 100644 --- a/vendor/github.com/containers/psgo/internal/dev/tty.go +++ b/vendor/github.com/containers/psgo/internal/dev/tty.go @@ -31,12 +31,9 @@ type TTY struct { Path string } -// cache TTYs to avoid redundant lookups -var devices *[]TTY - // FindTTY return the corresponding TTY to the ttyNr or nil of non could be // found. -func FindTTY(ttyNr uint64) (*TTY, error) { +func FindTTY(ttyNr uint64, devices *[]TTY) (*TTY, error) { // (man 5 proc) The minor device number is contained in the combination // of bits 31 to 20 and 7 to 0; the major device number is in bits 15 // to 8. @@ -44,7 +41,7 @@ func FindTTY(ttyNr uint64) (*TTY, error) { min := (ttyNr & 0xFF) | ((ttyNr >> 20) & 0xFFF) if devices == nil { - devs, err := getTTYs() + devs, err := TTYs() if err != nil { return nil, err } @@ -70,8 +67,8 @@ func minDevNum(rdev uint64) uint64 { return (rdev & 0xff) | ((rdev >> 12) & 0xfff00) } -// getTTYs parses /dev for tty and pts devices. -func getTTYs() (*[]TTY, error) { +// TTYs parses /dev for tty and pts devices. +func TTYs() (*[]TTY, error) { devDir, err := os.Open("/dev/") if err != nil { return nil, err diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go index 68e2acff6..29d059361 100644 --- a/vendor/github.com/containers/psgo/internal/proc/status.go +++ b/vendor/github.com/containers/psgo/internal/proc/status.go @@ -21,7 +21,6 @@ import ( "os/exec" "strings" - "github.com/containers/psgo/internal/types" "github.com/pkg/errors" ) @@ -207,11 +206,11 @@ func readStatusDefault(pid string) ([]string, error) { } // ParseStatus parses the /proc/$pid/status file and returns a *Status. -func ParseStatus(ctx *types.PsContext, pid string) (*Status, error) { +func ParseStatus(pid string, joinUserNS bool) (*Status, error) { var lines []string var err error - if ctx.JoinUserNS { + if joinUserNS { lines, err = readStatusUserNS(pid) } else { lines, err = readStatusDefault(pid) diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go index 0afbf721d..2aebfe9cc 100644 --- a/vendor/github.com/containers/psgo/internal/process/process.go +++ b/vendor/github.com/containers/psgo/internal/process/process.go @@ -21,7 +21,6 @@ import ( "github.com/containers/psgo/internal/host" "github.com/containers/psgo/internal/proc" - "github.com/containers/psgo/internal/types" "github.com/opencontainers/runc/libcontainer/user" "github.com/pkg/errors" ) @@ -76,13 +75,13 @@ func LookupUID(uid string) (string, error) { // New returns a new Process with the specified pid and parses the relevant // data from /proc and /dev. -func New(ctx *types.PsContext, pid string) (*Process, error) { +func New(pid string, joinUserNS bool) (*Process, error) { p := Process{Pid: pid} if err := p.parseStat(); err != nil { return nil, err } - if err := p.parseStatus(ctx); err != nil { + if err := p.parseStatus(joinUserNS); err != nil { return nil, err } if err := p.parseCmdLine(); err != nil { @@ -103,10 +102,10 @@ func New(ctx *types.PsContext, pid string) (*Process, error) { } // FromPIDs creates a new Process for each pid. -func FromPIDs(ctx *types.PsContext, pids []string) ([]*Process, error) { +func FromPIDs(pids []string, joinUserNS bool) ([]*Process, error) { processes := []*Process{} for _, pid := range pids { - p, err := New(ctx, pid) + p, err := New(pid, joinUserNS) if err != nil { if os.IsNotExist(errors.Cause(err)) { // proc parsing is racy @@ -131,8 +130,8 @@ func (p *Process) parseStat() error { } // parseStatus parses /proc/$pid/status. -func (p *Process) parseStatus(ctx *types.PsContext) error { - s, err := proc.ParseStatus(ctx, p.Pid) +func (p *Process) parseStatus(joinUserNS bool) error { + s, err := proc.ParseStatus(p.Pid, joinUserNS) if err != nil { return err } diff --git a/vendor/github.com/containers/psgo/internal/types/types.go b/vendor/github.com/containers/psgo/internal/types/types.go deleted file mode 100644 index 1f6fe0eaa..000000000 --- a/vendor/github.com/containers/psgo/internal/types/types.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2018 psgo authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -// PsContext controls some internals of the psgo library. -type PsContext struct { - // JoinUserNS will force /proc and /dev parsing from within each PIDs - // user namespace. - JoinUserNS bool -} diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go index 47a50264f..e0f102735 100644 --- a/vendor/github.com/containers/psgo/psgo.go +++ b/vendor/github.com/containers/psgo/psgo.go @@ -39,14 +39,22 @@ import ( "github.com/containers/psgo/internal/dev" "github.com/containers/psgo/internal/proc" "github.com/containers/psgo/internal/process" - "github.com/containers/psgo/internal/types" "github.com/pkg/errors" "golang.org/x/sys/unix" ) +type psContext struct { + // Processes in the container. + containersProcesses []*process.Process + // Processes on the host. Used to map those to the ones running in the container. + hostProcesses []*process.Process + // tty and pty devices. + ttys *[]dev.TTY +} + // processFunc is used to map a given aixFormatDescriptor to a corresponding // function extracting the desired data from a process. -type processFunc func(*process.Process) (string, error) +type processFunc func(*process.Process, *psContext) (string, error) // aixFormatDescriptor as mentioned in the ps(1) manpage. A given descriptor // can either be specified via its code (e.g., "%C") or its normal representation @@ -99,13 +107,6 @@ var ( // ErrUnkownDescriptor is returned when an unknown descriptor is parsed. ErrUnkownDescriptor = errors.New("unknown descriptor") - // hostProcesses are the processes on the host. It should only be used - // in the context of containers and is meant to display data of the - // container processes from the host's (i.e., calling process) view. - // Currently, all host processes contain only the required data from - // /proc/$pid/status. - hostProcesses []*process.Process - aixFormatDescriptors = []aixFormatDescriptor{ { code: "%C", @@ -282,11 +283,16 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string, return nil, err } + ctx := new(psContext) + // extract data from host processes only on-demand / when at least one // of the specified descriptors requires host data for _, d := range aixDescriptors { if d.onHost { - setHostProcesses(pid) + ctx.hostProcesses, err = hostProcesses(pid) + if err != nil { + return nil, err + } break } } @@ -330,18 +336,17 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string, return } - ctx := types.PsContext{ - // join the user NS if the pid's user NS is different - // to the caller's user NS. - JoinUserNS: currentUserNs != pidUserNs, - } - processes, err := process.FromPIDs(&ctx, pids) + // join the user NS if the pid's user NS is different + // to the caller's user NS. + joinUserNS := currentUserNs != pidUserNs + + ctx.containersProcesses, err = process.FromPIDs(pids, joinUserNS) if err != nil { dataErr = err return } - data, dataErr = processDescriptors(aixDescriptors, processes) + data, dataErr = processDescriptors(aixDescriptors, ctx) }() wg.Wait() @@ -417,43 +422,41 @@ func ProcessInfoByPids(pids []string, descriptors []string) ([][]string, error) return nil, err } - ctx := types.PsContext{JoinUserNS: false} - processes, err := process.FromPIDs(&ctx, pids) + ctx := new(psContext) + ctx.containersProcesses, err = process.FromPIDs(pids, false) if err != nil { return nil, err } - return processDescriptors(aixDescriptors, processes) + return processDescriptors(aixDescriptors, ctx) } -// setHostProcesses sets `hostProcesses`. -func setHostProcesses(pid string) error { +// hostProcesses returns all processes running in the current namespace. +func hostProcesses(pid string) ([]*process.Process, error) { // get processes pids, err := proc.GetPIDsFromCgroup(pid) if err != nil { - return err + return nil, err } - ctx := types.PsContext{JoinUserNS: false} - processes, err := process.FromPIDs(&ctx, pids) + processes, err := process.FromPIDs(pids, false) if err != nil { - return err + return nil, err } // set the additional host data for _, p := range processes { if err := p.SetHostData(); err != nil { - return err + return nil, err } } - hostProcesses = processes - return nil + return processes, nil } // processDescriptors calls each `procFn` of all formatDescriptors on each // process and returns an array of tab-separated strings. -func processDescriptors(formatDescriptors []aixFormatDescriptor, processes []*process.Process) ([][]string, error) { +func processDescriptors(formatDescriptors []aixFormatDescriptor, ctx *psContext) ([][]string, error) { data := [][]string{} // create header header := []string{} @@ -463,10 +466,10 @@ func processDescriptors(formatDescriptors []aixFormatDescriptor, processes []*pr data = append(data, header) // dispatch all descriptor functions on each process - for _, proc := range processes { + for _, proc := range ctx.containersProcesses { pData := []string{} for _, desc := range formatDescriptors { - dataStr, err := desc.procFn(proc) + dataStr, err := desc.procFn(proc, ctx) if err != nil { return nil, err } @@ -480,8 +483,8 @@ func processDescriptors(formatDescriptors []aixFormatDescriptor, processes []*pr // findHostProcess returns the corresponding process from `hostProcesses` or // nil if non is found. -func findHostProcess(p *process.Process) *process.Process { - for _, hp := range hostProcesses { +func findHostProcess(p *process.Process, ctx *psContext) *process.Process { + for _, hp := range ctx.hostProcesses { // We expect the host process to be in another namespace, so // /proc/$pid/status.NSpid must have at least two entries. if len(hp.Status.NSpid) < 2 { @@ -499,78 +502,78 @@ func findHostProcess(p *process.Process) *process.Process { // processGROUP returns the effective group ID of the process. This will be // the textual group ID, if it can be optained, or a decimal representation // otherwise. -func processGROUP(p *process.Process) (string, error) { +func processGROUP(p *process.Process, ctx *psContext) (string, error) { return process.LookupGID(p.Status.Gids[1]) } // processRGROUP returns the real group ID of the process. This will be // the textual group ID, if it can be optained, or a decimal representation // otherwise. -func processRGROUP(p *process.Process) (string, error) { +func processRGROUP(p *process.Process, ctx *psContext) (string, error) { return process.LookupGID(p.Status.Gids[0]) } // processPPID returns the parent process ID of process p. -func processPPID(p *process.Process) (string, error) { +func processPPID(p *process.Process, ctx *psContext) (string, error) { return p.Status.PPid, nil } // processUSER returns the effective user name of the process. This will be // the textual user ID, if it can be optained, or a decimal representation // otherwise. -func processUSER(p *process.Process) (string, error) { +func processUSER(p *process.Process, ctx *psContext) (string, error) { return process.LookupUID(p.Status.Uids[1]) } // processRUSER returns the effective user name of the process. This will be // the textual user ID, if it can be optained, or a decimal representation // otherwise. -func processRUSER(p *process.Process) (string, error) { +func processRUSER(p *process.Process, ctx *psContext) (string, error) { return process.LookupUID(p.Status.Uids[0]) } // processName returns the name of process p in the format "[$name]". -func processName(p *process.Process) (string, error) { +func processName(p *process.Process, ctx *psContext) (string, error) { return fmt.Sprintf("[%s]", p.Status.Name), nil } // processARGS returns the command of p with all its arguments. -func processARGS(p *process.Process) (string, error) { +func processARGS(p *process.Process, ctx *psContext) (string, error) { // ps (1) returns "[$name]" if command/args are empty if p.CmdLine[0] == "" { - return processName(p) + return processName(p, ctx) } return strings.Join(p.CmdLine, " "), nil } // processCOMM returns the command name (i.e., executable name) of process p. -func processCOMM(p *process.Process) (string, error) { +func processCOMM(p *process.Process, ctx *psContext) (string, error) { // ps (1) returns "[$name]" if command/args are empty if p.CmdLine[0] == "" { - return processName(p) + return processName(p, ctx) } spl := strings.Split(p.CmdLine[0], "/") return spl[len(spl)-1], nil } // processNICE returns the nice value of process p. -func processNICE(p *process.Process) (string, error) { +func processNICE(p *process.Process, ctx *psContext) (string, error) { return p.Stat.Nice, nil } // processPID returns the process ID of process p. -func processPID(p *process.Process) (string, error) { +func processPID(p *process.Process, ctx *psContext) (string, error) { return p.Pid, nil } // processPGID returns the process group ID of process p. -func processPGID(p *process.Process) (string, error) { +func processPGID(p *process.Process, ctx *psContext) (string, error) { return p.Stat.Pgrp, nil } // processPCPU returns how many percent of the CPU time process p uses as // a three digit float as string. -func processPCPU(p *process.Process) (string, error) { +func processPCPU(p *process.Process, ctx *psContext) (string, error) { elapsed, err := p.ElapsedTime() if err != nil { return "", err @@ -585,7 +588,7 @@ func processPCPU(p *process.Process) (string, error) { } // processETIME returns the elapsed time since the process was started. -func processETIME(p *process.Process) (string, error) { +func processETIME(p *process.Process, ctx *psContext) (string, error) { elapsed, err := p.ElapsedTime() if err != nil { return "", nil @@ -594,7 +597,7 @@ func processETIME(p *process.Process) (string, error) { } // processTIME returns the cumulative CPU time of process p. -func processTIME(p *process.Process) (string, error) { +func processTIME(p *process.Process, ctx *psContext) (string, error) { cpu, err := p.CPUTime() if err != nil { return "", err @@ -603,13 +606,13 @@ func processTIME(p *process.Process) (string, error) { } // processTTY returns the controlling tty (terminal) of process p. -func processTTY(p *process.Process) (string, error) { +func processTTY(p *process.Process, ctx *psContext) (string, error) { ttyNr, err := strconv.ParseUint(p.Stat.TtyNr, 10, 64) if err != nil { return "", nil } - tty, err := dev.FindTTY(ttyNr) + tty, err := dev.FindTTY(ttyNr, ctx.ttys) if err != nil { return "", nil } @@ -623,7 +626,7 @@ func processTTY(p *process.Process) (string, error) { // processVSZ returns the virtual memory size of process p in KiB (1024-byte // units). -func processVSZ(p *process.Process) (string, error) { +func processVSZ(p *process.Process, ctx *psContext) (string, error) { vmsize, err := strconv.Atoi(p.Stat.Vsize) if err != nil { return "", err @@ -653,41 +656,41 @@ func parseCAP(cap string) (string, error) { // processCAPAMB returns the set of ambient capabilties associated with // process p. If all capabilties are set, "full" is returned. If no // capability is enabled, "none" is returned. -func processCAPAMB(p *process.Process) (string, error) { +func processCAPAMB(p *process.Process, ctx *psContext) (string, error) { return parseCAP(p.Status.CapAmb) } // processCAPINH returns the set of inheritable capabilties associated with // process p. If all capabilties are set, "full" is returned. If no // capability is enabled, "none" is returned. -func processCAPINH(p *process.Process) (string, error) { +func processCAPINH(p *process.Process, ctx *psContext) (string, error) { return parseCAP(p.Status.CapInh) } // processCAPPRM returns the set of permitted capabilties associated with // process p. If all capabilties are set, "full" is returned. If no // capability is enabled, "none" is returned. -func processCAPPRM(p *process.Process) (string, error) { +func processCAPPRM(p *process.Process, ctx *psContext) (string, error) { return parseCAP(p.Status.CapPrm) } // processCAPEFF returns the set of effective capabilties associated with // process p. If all capabilties are set, "full" is returned. If no // capability is enabled, "none" is returned. -func processCAPEFF(p *process.Process) (string, error) { +func processCAPEFF(p *process.Process, ctx *psContext) (string, error) { return parseCAP(p.Status.CapEff) } // processCAPBND returns the set of bounding capabilties associated with // process p. If all capabilties are set, "full" is returned. If no // capability is enabled, "none" is returned. -func processCAPBND(p *process.Process) (string, error) { +func processCAPBND(p *process.Process, ctx *psContext) (string, error) { return parseCAP(p.Status.CapBnd) } // processSECCOMP returns the seccomp mode of the process (i.e., disabled, // strict or filter) or "?" if /proc/$pid/status.seccomp has a unknown value. -func processSECCOMP(p *process.Process) (string, error) { +func processSECCOMP(p *process.Process, ctx *psContext) (string, error) { switch p.Status.Seccomp { case "0": return "disabled", nil @@ -702,14 +705,14 @@ func processSECCOMP(p *process.Process) (string, error) { // processLABEL returns the process label of process p or "?" if the system // doesn't support labeling. -func processLABEL(p *process.Process) (string, error) { +func processLABEL(p *process.Process, ctx *psContext) (string, error) { return p.Label, nil } // processHPID returns the PID of the corresponding host process of the // (container) or "?" if no corresponding process could be found. -func processHPID(p *process.Process) (string, error) { - if hp := findHostProcess(p); hp != nil { +func processHPID(p *process.Process, ctx *psContext) (string, error) { + if hp := findHostProcess(p, ctx); hp != nil { return hp.Pid, nil } return "?", nil @@ -717,8 +720,8 @@ func processHPID(p *process.Process) (string, error) { // processHUSER returns the effective user ID of the corresponding host process // of the (container) or "?" if no corresponding process could be found. -func processHUSER(p *process.Process) (string, error) { - if hp := findHostProcess(p); hp != nil { +func processHUSER(p *process.Process, ctx *psContext) (string, error) { + if hp := findHostProcess(p, ctx); hp != nil { return hp.Huser, nil } return "?", nil @@ -727,14 +730,14 @@ func processHUSER(p *process.Process) (string, error) { // processHGROUP returns the effective group ID of the corresponding host // process of the (container) or "?" if no corresponding process could be // found. -func processHGROUP(p *process.Process) (string, error) { - if hp := findHostProcess(p); hp != nil { +func processHGROUP(p *process.Process, ctx *psContext) (string, error) { + if hp := findHostProcess(p, ctx); hp != nil { return hp.Hgroup, nil } return "?", nil } // processState returns the process state of process p. -func processState(p *process.Process) (string, error) { +func processState(p *process.Process, ctx *psContext) (string, error) { return p.Status.State, nil } |