summaryrefslogtreecommitdiff
path: root/vendor/github.com/containers/psgo/ps/stat.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/containers/psgo/ps/stat.go')
-rw-r--r--vendor/github.com/containers/psgo/ps/stat.go193
1 files changed, 193 insertions, 0 deletions
diff --git a/vendor/github.com/containers/psgo/ps/stat.go b/vendor/github.com/containers/psgo/ps/stat.go
new file mode 100644
index 000000000..0488d4616
--- /dev/null
+++ b/vendor/github.com/containers/psgo/ps/stat.go
@@ -0,0 +1,193 @@
+package ps
+
+import (
+ "bufio"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strconv"
+ "strings"
+)
+
+/*
+#include <unistd.h>
+*/
+import "C"
+
+// getClockTicks returns sysconf(SC_CLK_TCK).
+func getClockTicks() int64 {
+ return int64(C.sysconf(C._SC_CLK_TCK))
+}
+
+// bootTime parses /proc/uptime returns the time.Time of system boot.
+func getBootTime() (int64, error) {
+ f, err := os.Open("/proc/stat")
+ if err != nil {
+ return 0, err
+ }
+
+ btimeStr := ""
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ fields := strings.Fields(scanner.Text())
+ if len(fields) < 2 {
+ continue
+ }
+ if fields[0] == "btime" {
+ btimeStr = fields[1]
+ }
+ }
+
+ if len(btimeStr) == 0 {
+ return 0, fmt.Errorf("couldn't extract boot time from /proc/stat")
+ }
+
+ btimeSec, err := strconv.ParseInt(btimeStr, 10, 64)
+ if err != nil {
+ return 0, fmt.Errorf("error parsing boot time from /proc/stat: %s", err)
+ }
+
+ return btimeSec, nil
+}
+
+// stat is a direct translation of a `/proc/[pid]/stat` file as described in
+// the proc(5) manpage. Please note that it is not a full translation as not
+// all fields are in the scope of this library and higher indices are
+// Kernel-version dependent.
+type stat struct {
+ // (1) The process ID
+ pid string
+ // (2) The filename of the executable, in parentheses. This is visible
+ // whether or not the executable is swapped out.
+ comm string
+ // (3) The process state (e.g., running, sleeping, zombie, dead).
+ // Refer to proc(5) for further deatils.
+ state string
+ // (4) The PID of the parent of this process.
+ ppid string
+ // (5) The process group ID of the process.
+ pgrp string
+ // (6) The session ID of the process.
+ session string
+ // (7) The controlling terminal of the process. (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.)
+ ttyNr string
+ // (8) The ID of the foreground process group of the controlling
+ // terminal of the process.
+ tpgid string
+ // (9) The kernel flags word of the process. For bit meanings, see the
+ // PF_* defines in the Linux kernel source file
+ // include/linux/sched.h. Details depend on the kernel version.
+ flags string
+ // (10) The number of minor faults the process has made which have not
+ // required loading a memory page from disk.
+ minflt string
+ // (11) The number of minor faults that the process's waited-for
+ // children have made.
+ cminflt string
+ // (12) The number of major faults the process has made which have
+ // required loading a memory page from disk.
+ majflt string
+ // (13) The number of major faults that the process's waited-for
+ // children have made.
+ cmajflt string
+ // (14) Amount of time that this process has been scheduled in user
+ // mode, measured in clock ticks (divide by
+ // sysconf(_SC_CLK_TCK)). This includes guest time, guest_time
+ // (time spent running a virtual CPU, see below), so that applications
+ // that are not aware of the guest time field do not lose that time
+ // from their calculations.
+ utime string
+ // (15) Amount of time that this process has been scheduled in kernel
+ // mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
+ stime string
+ // (16) Amount of time that this process's waited-for children have
+ // been scheduled in user mode, measured in clock ticks (divide by
+ // sysconf(_SC_CLK_TCK)). (See also times(2).) This includes guest
+ // time, cguest_time (time spent running a virtual CPU, see below).
+ cutime string
+ // (17) Amount of time that this process's waited-for children have
+ // been scheduled in kernel mode, measured in clock ticks (divide by
+ // sysconf(_SC_CLK_TCK)).
+ cstime string
+ // (18) (Explanation for Linux 2.6+) For processes running a real-time
+ // scheduling policy (policy below; see sched_setscheduler(2)), this is
+ // the negated scheduling pri- ority, minus one; that is, a number
+ // in the range -2 to -100, corresponding to real-time priorities 1 to
+ // 99. For processes running under a non-real-time scheduling
+ // policy, this is the raw nice value (setpriority(2)) as represented
+ // in the kernel. The kernel stores nice values as numbers in the
+ // range 0 (high) to 39 (low), corresponding to the user-visible nice
+ // range of -20 to 19.
+ priority string
+ // (19) The nice value (see setpriority(2)), a value in the range 19
+ // (low priority) to -20 (high priority).
+ nice string
+ // (20) Number of threads in this process (since Linux 2.6). Before
+ // kernel 2.6, this field was hard coded to 0 as a placeholder for an
+ // earlier removed field.
+ numThreads string
+ // (21) The time in jiffies before the next SIGALRM is sent to the
+ // process due to an interval timer. Since kernel 2.6.17, this
+ // field is no longer maintained, and is hard coded as 0.
+ itrealvalue string
+ // (22) The time the process started after system boot. In kernels
+ // before Linux 2.6, this value was expressed in jiffies. Since
+ // Linux 2.6, the value is expressed in clock ticks (divide by
+ // sysconf(_SC_CLK_TCK)).
+ starttime string
+ // (23) Virtual memory size in bytes.
+ vsize string
+}
+
+// readStat is used for mocking in unit tests.
+var readStat = func(path string) ([]string, error) {
+ data, err := ioutil.ReadFile(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ err = errNoSuchPID
+ }
+ return nil, err
+ }
+
+ return strings.Fields(string(data)), nil
+}
+
+// parseStat parses the /proc/$pid/stat file and returns a stat.
+func parseStat(path string) (*stat, error) {
+ fields, err := readStat(path)
+ if err != nil {
+ return nil, err
+ }
+
+ fieldAt := func(i int) string {
+ return fields[i-1]
+ }
+
+ return &stat{
+ pid: fieldAt(1),
+ comm: fieldAt(2),
+ state: fieldAt(3),
+ ppid: fieldAt(4),
+ pgrp: fieldAt(5),
+ session: fieldAt(6),
+ ttyNr: fieldAt(7),
+ tpgid: fieldAt(8),
+ flags: fieldAt(9),
+ minflt: fieldAt(10),
+ cminflt: fieldAt(11),
+ majflt: fieldAt(12),
+ cmajflt: fieldAt(13),
+ utime: fieldAt(14),
+ stime: fieldAt(15),
+ cutime: fieldAt(16),
+ cstime: fieldAt(17),
+ priority: fieldAt(18),
+ nice: fieldAt(19),
+ numThreads: fieldAt(20),
+ itrealvalue: fieldAt(21),
+ starttime: fieldAt(22),
+ vsize: fieldAt(23),
+ }, nil
+}