Update gopsutil & x/sys libraries (#10889)
This commit is contained in:
parent
85c1ae1002
commit
d22c6f9a7a
4
go.mod
4
go.mod
|
@ -139,7 +139,7 @@ require (
|
|||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da
|
||||
github.com/sasha-s/go-deadlock v0.2.0
|
||||
github.com/sethvargo/go-limiter v0.3.0
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible
|
||||
github.com/shirou/gopsutil v3.21.1+incompatible
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/tidwall/pretty v1.0.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.7 // indirect
|
||||
|
@ -153,7 +153,7 @@ require (
|
|||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
|
||||
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
golang.org/x/tools v0.0.0-20200521155704-91d71f6c2f04
|
||||
google.golang.org/api v0.29.0
|
||||
google.golang.org/grpc v1.29.1
|
||||
|
|
6
go.sum
6
go.sum
|
@ -1047,8 +1047,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt
|
|||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sethvargo/go-limiter v0.3.0 h1:yRMc+Qs2yqw6YJp6UxrO2iUs6DOSq4zcnljbB7/rMns=
|
||||
github.com/sethvargo/go-limiter v0.3.0/go.mod h1:C0kbSFbiriE5k2FFOe18M1YZbAR2Fiwf72uGu0CXCcU=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible h1:msXs2frUV+O/JLva9EDLpuJ84PrFsdCTCQex8PUdtkQ=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil v3.21.1+incompatible h1:2LwXWdbjXwyDgq26Yy/OT4xozlpmssQfy/rtfhWb0bY=
|
||||
github.com/shirou/gopsutil v3.21.1+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
|
@ -1365,6 +1365,8 @@ golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -313,19 +313,25 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
|||
return ret, nil
|
||||
}
|
||||
// physical cores
|
||||
// https://github.com/giampaolo/psutil/blob/122174a10b75c9beebe15f6c07dcf3afbe3b120d/psutil/_pslinux.py#L621-L629
|
||||
// https://github.com/giampaolo/psutil/blob/8415355c8badc9c94418b19bdf26e622f06f0cce/psutil/_pslinux.py#L615-L628
|
||||
var threadSiblingsLists = make(map[string]bool)
|
||||
if files, err := filepath.Glob(common.HostSys("devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list")); err == nil {
|
||||
for _, file := range files {
|
||||
lines, err := common.ReadLines(file)
|
||||
if err != nil || len(lines) != 1 {
|
||||
continue
|
||||
// These 2 files are the same but */core_cpus_list is newer while */thread_siblings_list is deprecated and may disappear in the future.
|
||||
// https://www.kernel.org/doc/Documentation/admin-guide/cputopology.rst
|
||||
// https://github.com/giampaolo/psutil/pull/1727#issuecomment-707624964
|
||||
// https://lkml.org/lkml/2019/2/26/41
|
||||
for _, glob := range []string{"devices/system/cpu/cpu[0-9]*/topology/core_cpus_list", "devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list"} {
|
||||
if files, err := filepath.Glob(common.HostSys(glob)); err == nil {
|
||||
for _, file := range files {
|
||||
lines, err := common.ReadLines(file)
|
||||
if err != nil || len(lines) != 1 {
|
||||
continue
|
||||
}
|
||||
threadSiblingsLists[lines[0]] = true
|
||||
}
|
||||
ret := len(threadSiblingsLists)
|
||||
if ret != 0 {
|
||||
return ret, nil
|
||||
}
|
||||
threadSiblingsLists[lines[0]] = true
|
||||
}
|
||||
ret := len(threadSiblingsLists)
|
||||
if ret != 0 {
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
// https://github.com/giampaolo/psutil/blob/122174a10b75c9beebe15f6c07dcf3afbe3b120d/psutil/_pslinux.py#L631-L652
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package disk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
|
@ -59,3 +60,23 @@ func (d IOCountersStat) String() string {
|
|||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// Usage returns a file system usage. path is a filesystem path such
|
||||
// as "/", not device file path like "/dev/vda1". If you want to use
|
||||
// a return value of disk.Partitions, use "Mountpoint" not "Device".
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
return UsageWithContext(context.Background(), path)
|
||||
}
|
||||
|
||||
// Partitions returns disk partitions. If all is false, returns
|
||||
// physical devices only (e.g. hard disks, cd-rom drives, USB keys)
|
||||
// and ignore all others (e.g. memory partitions such as /dev/shm)
|
||||
//
|
||||
// 'all' argument is ignored for BSD, see: https://github.com/giampaolo/psutil/issues/906
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
|
|
@ -4,16 +4,13 @@ package disk
|
|||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
// PartitionsWithContext returns disk partition.
|
||||
// 'all' argument is ignored, see: https://github.com/giampaolo/psutil/issues/906
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
|
||||
|
@ -64,16 +61,11 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
opts += ",nodev"
|
||||
}
|
||||
d := PartitionStat{
|
||||
Device: common.IntToString(stat.Mntfromname[:]),
|
||||
Mountpoint: common.IntToString(stat.Mntonname[:]),
|
||||
Fstype: common.IntToString(stat.Fstypename[:]),
|
||||
Device: common.ByteToString(stat.Mntfromname[:]),
|
||||
Mountpoint: common.ByteToString(stat.Mntonname[:]),
|
||||
Fstype: common.ByteToString(stat.Fstypename[:]),
|
||||
Opts: opts,
|
||||
}
|
||||
if all == false {
|
||||
if !path.IsAbs(d.Device) || !common.PathExists(d.Device) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, d)
|
||||
}
|
||||
|
@ -82,5 +74,5 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
}
|
||||
|
||||
func getFsType(stat unix.Statfs_t) string {
|
||||
return common.IntToString(stat.Fstypename[:])
|
||||
return common.ByteToString(stat.Fstypename[:])
|
||||
}
|
||||
|
|
|
@ -17,10 +17,6 @@ import (
|
|||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
var buf [C.NDRIVE]C.DriveStats
|
||||
n, err := C.readdrivestat(&buf[0], C.int(len(buf)))
|
||||
|
|
|
@ -9,10 +9,6 @@ import (
|
|||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
|
|
@ -8,26 +8,14 @@ import (
|
|||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
return []PartitionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
return UsageWithContext(context.Background(), path)
|
||||
}
|
||||
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
@ -14,10 +13,8 @@ import (
|
|||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
// PartitionsWithContext returns disk partition.
|
||||
// 'all' argument is ignored, see: https://github.com/giampaolo/psutil/issues/906
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
|
||||
|
@ -89,11 +86,6 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
Fstype: common.ByteToString(stat.Fstypename[:]),
|
||||
Opts: opts,
|
||||
}
|
||||
if all == false {
|
||||
if !path.IsAbs(d.Device) || !common.PathExists(d.Device) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, d)
|
||||
}
|
||||
|
@ -101,10 +93,6 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
// statinfo->devinfo->devstat
|
||||
// /usr/include/devinfo.h
|
||||
|
|
|
@ -218,13 +218,6 @@ var fsTypeMap = map[int64]string{
|
|||
ZFS_SUPER_MAGIC: "zfs", /* 0x2FC12FC1 local */
|
||||
}
|
||||
|
||||
// Partitions returns disk partitions. If all is false, returns
|
||||
// physical devices only (e.g. hard disks, cd-rom drives, USB keys)
|
||||
// and ignore all others (e.g. memory partitions such as /dev/shm)
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
useMounts := false
|
||||
|
||||
|
@ -283,6 +276,14 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
mountPoint := fields[4]
|
||||
mountOpts := fields[5]
|
||||
|
||||
if rootDir := fields[3]; rootDir != "" && rootDir != "/" {
|
||||
if len(mountOpts) == 0 {
|
||||
mountOpts = "bind"
|
||||
} else {
|
||||
mountOpts = "bind," + mountOpts
|
||||
}
|
||||
}
|
||||
|
||||
fields = strings.Fields(parts[1])
|
||||
fstype := fields[0]
|
||||
device := fields[1]
|
||||
|
@ -346,10 +347,6 @@ func getFileSystems() ([]string, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
filename := common.HostProc("diskstats")
|
||||
lines, err := common.ReadLines(filename)
|
||||
|
|
|
@ -6,16 +6,11 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"path"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
|
||||
|
@ -66,11 +61,6 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
Fstype: common.IntToString(stat.F_fstypename[:]),
|
||||
Opts: opts,
|
||||
}
|
||||
if all == false {
|
||||
if !path.IsAbs(d.Device) || !common.PathExists(d.Device) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, d)
|
||||
}
|
||||
|
@ -78,10 +68,6 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
ret := make(map[string]IOCountersStat)
|
||||
|
||||
|
@ -134,10 +120,6 @@ func parseDiskstats(buf []byte) (Diskstats, error) {
|
|||
return ds, nil
|
||||
}
|
||||
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
return UsageWithContext(context.Background(), path)
|
||||
}
|
||||
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
stat := unix.Statfs_t{}
|
||||
err := unix.Statfs(path, &stat)
|
||||
|
|
|
@ -38,10 +38,6 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
ret := make([]PartitionStat, 0, _DEFAULT_NUM_MOUNTS)
|
||||
|
||||
|
@ -83,18 +79,10 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
return ret, err
|
||||
}
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
return UsageWithContext(context.Background(), path)
|
||||
}
|
||||
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
statvfs := unix.Statvfs_t{}
|
||||
if err := unix.Statvfs(path, &statvfs); err != nil {
|
||||
|
|
|
@ -9,13 +9,6 @@ import (
|
|||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Usage returns a file system usage. path is a filesystem path such
|
||||
// as "/", not device file path like "/dev/vda1". If you want to use
|
||||
// a return value of disk.Partitions, use "Mountpoint" not "Device".
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
return UsageWithContext(context.Background(), path)
|
||||
}
|
||||
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
stat := unix.Statfs_t{}
|
||||
err := unix.Statfs(path, &stat)
|
||||
|
|
|
@ -43,10 +43,6 @@ type diskPerformance struct {
|
|||
alignmentPadding uint32 // necessary for 32bit support, see https://github.com/elastic/beats/pull/16553
|
||||
}
|
||||
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
return UsageWithContext(context.Background(), path)
|
||||
}
|
||||
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
lpFreeBytesAvailable := int64(0)
|
||||
lpTotalNumberOfBytes := int64(0)
|
||||
|
@ -73,10 +69,6 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
return PartitionsWithContext(context.Background(), all)
|
||||
}
|
||||
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
lpBuffer := make([]byte, 254)
|
||||
|
@ -139,10 +131,6 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
// https://github.com/giampaolo/psutil/blob/544e9daa4f66a9f80d7bf6c7886d693ee42f0a13/psutil/arch/windows/disk.c#L83
|
||||
drivemap := make(map[string]IOCountersStat, 0)
|
||||
|
@ -155,7 +143,7 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
}
|
||||
for _, v := range lpBuffer[:lpBufferLen] {
|
||||
if 'A' <= v && v <= 'Z' {
|
||||
path := string(v) + ":"
|
||||
path := string(rune(v)) + ":"
|
||||
typepath, _ := windows.UTF16PtrFromString(path)
|
||||
typeret := windows.GetDriveType(typepath)
|
||||
if typeret == 0 {
|
||||
|
|
|
@ -326,7 +326,6 @@ func GetEnv(key string, dfault string, combineWith ...string) string {
|
|||
copy(all[1:], combineWith)
|
||||
return filepath.Join(all...)
|
||||
}
|
||||
panic("invalid switch case")
|
||||
}
|
||||
|
||||
func HostProc(combineWith ...string) string {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -110,16 +111,24 @@ func Virtualization() (string, string, error) {
|
|||
return VirtualizationWithContext(context.Background())
|
||||
}
|
||||
|
||||
var virtualizationCache map[string]string
|
||||
// required variables for concurrency safe virtualization caching
|
||||
var (
|
||||
cachedVirtMap map[string]string
|
||||
cachedVirtMutex sync.RWMutex
|
||||
cachedVirtOnce sync.Once
|
||||
)
|
||||
|
||||
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
var system, role string
|
||||
|
||||
// if cached already, return from cache
|
||||
if virtualizationCache != nil {
|
||||
return virtualizationCache["system"], virtualizationCache["role"], nil
|
||||
cachedVirtMutex.RLock() // unlock won't be deferred so concurrent reads don't wait for long
|
||||
if cachedVirtMap != nil {
|
||||
cachedSystem, cachedRole := cachedVirtMap["system"], cachedVirtMap["role"]
|
||||
cachedVirtMutex.RUnlock()
|
||||
return cachedSystem, cachedRole, nil
|
||||
}
|
||||
|
||||
var system string
|
||||
var role string
|
||||
cachedVirtMutex.RUnlock()
|
||||
|
||||
filename := HostProc("xen")
|
||||
if PathExists(filename) {
|
||||
|
@ -238,13 +247,17 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
|||
role = "host"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// before returning for the first time, cache the system and role
|
||||
virtualizationCache = map[string]string{
|
||||
"system": system,
|
||||
"role": role,
|
||||
}
|
||||
|
||||
cachedVirtOnce.Do(func() {
|
||||
cachedVirtMutex.Lock()
|
||||
defer cachedVirtMutex.Unlock()
|
||||
cachedVirtMap = map[string]string{
|
||||
"system": system,
|
||||
"role": role,
|
||||
}
|
||||
})
|
||||
|
||||
return system, role, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ package common
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
@ -69,13 +70,13 @@ var (
|
|||
ProcNtWow64QueryInformationProcess64 = ModNt.NewProc("NtWow64QueryInformationProcess64")
|
||||
ProcNtWow64ReadVirtualMemory64 = ModNt.NewProc("NtWow64ReadVirtualMemory64")
|
||||
|
||||
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
|
||||
PdhAddCounter = ModPdh.NewProc("PdhAddCounterW")
|
||||
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
|
||||
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
|
||||
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
|
||||
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
|
||||
PdhAddCounter = ModPdh.NewProc("PdhAddCounterW")
|
||||
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
|
||||
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
|
||||
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
|
||||
|
||||
procQueryDosDeviceW = Modkernel32.NewProc("QueryDosDeviceW")
|
||||
procQueryDosDeviceW = Modkernel32.NewProc("QueryDosDeviceW")
|
||||
)
|
||||
|
||||
type FILETIME struct {
|
||||
|
@ -93,7 +94,7 @@ func BytePtrToString(p *uint8) string {
|
|||
return string(a[:i])
|
||||
}
|
||||
|
||||
// CounterInfo
|
||||
// CounterInfo struct is used to track a windows performance counter
|
||||
// copied from https://github.com/mackerelio/mackerel-agent/
|
||||
type CounterInfo struct {
|
||||
PostName string
|
||||
|
@ -101,7 +102,7 @@ type CounterInfo struct {
|
|||
Counter windows.Handle
|
||||
}
|
||||
|
||||
// CreateQuery XXX
|
||||
// CreateQuery with a PdhOpenQuery call
|
||||
// copied from https://github.com/mackerelio/mackerel-agent/
|
||||
func CreateQuery() (windows.Handle, error) {
|
||||
var query windows.Handle
|
||||
|
@ -112,7 +113,7 @@ func CreateQuery() (windows.Handle, error) {
|
|||
return query, nil
|
||||
}
|
||||
|
||||
// CreateCounter XXX
|
||||
// CreateCounter with a PdhAddCounter call
|
||||
func CreateCounter(query windows.Handle, pname, cname string) (*CounterInfo, error) {
|
||||
var counter windows.Handle
|
||||
r, _, err := PdhAddCounter.Call(
|
||||
|
@ -130,6 +131,62 @@ func CreateCounter(query windows.Handle, pname, cname string) (*CounterInfo, err
|
|||
}, nil
|
||||
}
|
||||
|
||||
// GetCounterValue get counter value from handle
|
||||
// adapted from https://github.com/mackerelio/mackerel-agent/
|
||||
func GetCounterValue(counter windows.Handle) (float64, error) {
|
||||
var value PDH_FMT_COUNTERVALUE_DOUBLE
|
||||
r, _, err := PdhGetFormattedCounterValue.Call(uintptr(counter), PDH_FMT_DOUBLE, uintptr(0), uintptr(unsafe.Pointer(&value)))
|
||||
if r != 0 && r != PDH_INVALID_DATA {
|
||||
return 0.0, err
|
||||
}
|
||||
return value.DoubleValue, nil
|
||||
}
|
||||
|
||||
type Win32PerformanceCounter struct {
|
||||
PostName string
|
||||
CounterName string
|
||||
Query windows.Handle
|
||||
Counter windows.Handle
|
||||
}
|
||||
|
||||
func NewWin32PerformanceCounter(postName, counterName string) (*Win32PerformanceCounter, error) {
|
||||
query, err := CreateQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var counter = Win32PerformanceCounter{
|
||||
Query: query,
|
||||
PostName: postName,
|
||||
CounterName: counterName,
|
||||
}
|
||||
r, _, err := PdhAddCounter.Call(
|
||||
uintptr(counter.Query),
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(counter.CounterName))),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&counter.Counter)),
|
||||
)
|
||||
if r != 0 {
|
||||
return nil, err
|
||||
}
|
||||
return &counter, nil
|
||||
}
|
||||
|
||||
func (w *Win32PerformanceCounter) GetValue() (float64, error) {
|
||||
r, _, err := PdhCollectQueryData.Call(uintptr(w.Query))
|
||||
if r != 0 && err != nil {
|
||||
if r == PDH_NO_DATA {
|
||||
return 0.0, fmt.Errorf("%w: this counter has not data", err)
|
||||
}
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
return GetCounterValue(w.Counter)
|
||||
}
|
||||
|
||||
func ProcessorQueueLengthCounter() (*Win32PerformanceCounter, error) {
|
||||
return NewWin32PerformanceCounter("processor_queue_length", `\System\Processor Queue Length`)
|
||||
}
|
||||
|
||||
// WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
|
||||
func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
|
||||
if _, ok := ctx.Deadline(); !ok {
|
||||
|
|
|
@ -73,86 +73,226 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu
|
|||
value := strings.TrimSpace(fields[1])
|
||||
value = strings.Replace(value, " kB", "", -1)
|
||||
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx,err
|
||||
}
|
||||
switch key {
|
||||
case "MemTotal":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Total = t * 1024
|
||||
case "MemFree":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Free = t * 1024
|
||||
case "MemAvailable":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
memavail = true
|
||||
ret.Available = t * 1024
|
||||
case "Buffers":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Buffers = t * 1024
|
||||
case "Cached":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Cached = t * 1024
|
||||
case "Active":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Active = t * 1024
|
||||
case "Inactive":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Inactive = t * 1024
|
||||
case "Active(anon)":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
retEx.ActiveAnon = t * 1024
|
||||
case "Inactive(anon)":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
retEx.InactiveAnon = t * 1024
|
||||
case "Active(file)":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
activeFile = true
|
||||
retEx.ActiveFile = t * 1024
|
||||
case "Inactive(file)":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
inactiveFile = true
|
||||
retEx.InactiveFile = t * 1024
|
||||
case "Unevictable":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
retEx.Unevictable = t * 1024
|
||||
case "Writeback":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Writeback = t * 1024
|
||||
case "WritebackTmp":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.WritebackTmp = t * 1024
|
||||
case "Dirty":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Dirty = t * 1024
|
||||
case "Shmem":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Shared = t * 1024
|
||||
case "Slab":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Slab = t * 1024
|
||||
case "SReclaimable":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
sReclaimable = true
|
||||
ret.SReclaimable = t * 1024
|
||||
case "SUnreclaim":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.SUnreclaim = t * 1024
|
||||
case "PageTables":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.PageTables = t * 1024
|
||||
case "SwapCached":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.SwapCached = t * 1024
|
||||
case "CommitLimit":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.CommitLimit = t * 1024
|
||||
case "Committed_AS":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.CommittedAS = t * 1024
|
||||
case "HighTotal":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.HighTotal = t * 1024
|
||||
case "HighFree":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.HighFree = t * 1024
|
||||
case "LowTotal":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.LowTotal = t * 1024
|
||||
case "LowFree":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.LowFree = t * 1024
|
||||
case "SwapTotal":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.SwapTotal = t * 1024
|
||||
case "SwapFree":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.SwapFree = t * 1024
|
||||
case "Mapped":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Mapped = t * 1024
|
||||
case "VmallocTotal":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.VMallocTotal = t * 1024
|
||||
case "VmallocUsed":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.VMallocUsed = t * 1024
|
||||
case "VmallocChunk":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.VMallocChunk = t * 1024
|
||||
case "HugePages_Total":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.HugePagesTotal = t
|
||||
case "HugePages_Free":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.HugePagesFree = t
|
||||
case "Hugepagesize":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.HugePageSize = t * 1024
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ func FilterCounters() ([]FilterStat, error) {
|
|||
}
|
||||
|
||||
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for darwin")
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
|
@ -289,5 +289,5 @@ func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
|||
}
|
||||
|
||||
func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, errors.New("NetProtoCounters not implemented for darwin")
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ package net
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -109,7 +108,7 @@ func FilterCounters() ([]FilterStat, error) {
|
|||
}
|
||||
|
||||
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for freebsd")
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
|
@ -117,7 +116,7 @@ func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
|||
}
|
||||
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return nil, errors.New("ConntrackStats not implemented for freebsd")
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
|
@ -129,5 +128,5 @@ func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
|||
}
|
||||
|
||||
func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, errors.New("NetProtoCounters not implemented for freebsd")
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ package net
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
|
@ -153,7 +152,7 @@ func FilterCounters() ([]FilterStat, error) {
|
|||
}
|
||||
|
||||
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for openbsd")
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
|
@ -173,7 +172,7 @@ func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
|||
}
|
||||
|
||||
func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, errors.New("NetProtoCounters not implemented for openbsd")
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func parseNetstatLine(line string) (ConnectionStat, error) {
|
||||
|
|
|
@ -63,7 +63,7 @@ func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]C
|
|||
case "udp":
|
||||
args = append(args, "udp")
|
||||
case "udp4":
|
||||
args = append(args, "6udp")
|
||||
args = append(args, "4udp")
|
||||
case "udp6":
|
||||
args = append(args, "6udp")
|
||||
case "unix":
|
||||
|
|
|
@ -547,7 +547,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
|
|||
mibs := (*mibUDPRowOwnerPid)(unsafe.Pointer(&buf[index]))
|
||||
ns := mibs.convertToConnectionStat()
|
||||
stats = append(stats, ns)
|
||||
case kindUDP4.family:
|
||||
case kindUDP6.family:
|
||||
mibs := (*mibUDP6RowOwnerPid)(unsafe.Pointer(&buf[index]))
|
||||
ns := mibs.convertToConnectionStat()
|
||||
stats = append(stats, ns)
|
||||
|
|
|
@ -6,11 +6,14 @@ import (
|
|||
"errors"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"github.com/shirou/gopsutil/net"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -24,6 +27,7 @@ type Process struct {
|
|||
name string
|
||||
status string
|
||||
parent int32
|
||||
parentMutex *sync.RWMutex // for windows ppid cache
|
||||
numCtxSwitches *NumCtxSwitchesStat
|
||||
uids []int32
|
||||
gids []int32
|
||||
|
@ -150,21 +154,34 @@ func PidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
return pids, err
|
||||
}
|
||||
|
||||
// Processes returns a slice of pointers to Process structs for all
|
||||
// currently running processes.
|
||||
func Processes() ([]*Process, error) {
|
||||
return ProcessesWithContext(context.Background())
|
||||
}
|
||||
|
||||
// NewProcess creates a new Process instance, it only stores the pid and
|
||||
// checks that the process exists. Other method on Process can be used
|
||||
// to get more information about the process. An error will be returned
|
||||
// if the process does not exist.
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{Pid: pid}
|
||||
return NewProcessWithContext(context.Background(), pid)
|
||||
}
|
||||
|
||||
exists, err := PidExists(pid)
|
||||
func NewProcessWithContext(ctx context.Context, pid int32) (*Process, error) {
|
||||
p := &Process{
|
||||
Pid: pid,
|
||||
parentMutex: new(sync.RWMutex),
|
||||
}
|
||||
|
||||
exists, err := PidExistsWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
if !exists {
|
||||
return p, ErrorProcessNotRunning
|
||||
}
|
||||
p.CreateTime()
|
||||
p.CreateTimeWithContext(ctx)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
@ -192,7 +209,7 @@ func (p *Process) Percent(interval time.Duration) (float64, error) {
|
|||
}
|
||||
|
||||
func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration) (float64, error) {
|
||||
cpuTimes, err := p.Times()
|
||||
cpuTimes, err := p.TimesWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -204,7 +221,7 @@ func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration
|
|||
if err := common.Sleep(ctx, interval); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cpuTimes, err = p.Times()
|
||||
cpuTimes, err = p.TimesWithContext(ctx)
|
||||
now = time.Now()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -236,7 +253,7 @@ func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
|||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
p2, err := NewProcess(p.Pid)
|
||||
p2, err := NewProcessWithContext(ctx, p.Pid)
|
||||
if err == ErrorProcessNotRunning {
|
||||
return false, nil
|
||||
}
|
||||
|
@ -276,13 +293,13 @@ func (p *Process) MemoryPercent() (float32, error) {
|
|||
}
|
||||
|
||||
func (p *Process) MemoryPercentWithContext(ctx context.Context) (float32, error) {
|
||||
machineMemory, err := mem.VirtualMemory()
|
||||
machineMemory, err := mem.VirtualMemoryWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
total := machineMemory.Total
|
||||
|
||||
processMemory, err := p.MemoryInfo()
|
||||
processMemory, err := p.MemoryInfoWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -297,12 +314,12 @@ func (p *Process) CPUPercent() (float64, error) {
|
|||
}
|
||||
|
||||
func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) {
|
||||
crt_time, err := p.CreateTime()
|
||||
crt_time, err := p.createTimeWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cput, err := p.Times()
|
||||
cput, err := p.TimesWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -320,3 +337,208 @@ func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) {
|
|||
func (p *Process) Groups() ([]int32, error) {
|
||||
return p.GroupsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Ppid returns Parent Process ID of the process.
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Name returns name of the process.
|
||||
func (p *Process) Name() (string, error) {
|
||||
return p.NameWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Exe returns executable path of the process.
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Cmdline returns the command line arguments of the process as a string with
|
||||
// each argument separated by 0x20 ascii character.
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.CmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
// CmdlineSlice returns the command line arguments of the process as a slice with each
|
||||
// element being an argument.
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.CmdlineSliceWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Cwd returns current working directory of the process.
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.CwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Parent returns parent Process of the process.
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p.ParentWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Status returns the process status.
|
||||
// Return value could be one of these.
|
||||
// R: Running S: Sleep T: Stop I: Idle
|
||||
// Z: Zombie W: Wait L: Lock
|
||||
// The character is same within all supported platforms.
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Foreground returns true if the process is in foreground, false otherwise.
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Uids returns user ids of the process as a slice of the int
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Gids returns group ids of the process as a slice of the int
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
return p.GidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Terminal returns a terminal which is associated with the process.
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
return p.TerminalWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Nice returns a nice value (priority).
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
// IOnice returns process I/O nice value (priority).
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Rlimit returns Resource Limits.
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return p.RlimitWithContext(context.Background())
|
||||
}
|
||||
|
||||
// RlimitUsage returns Resource Limits.
|
||||
// If gatherUsed is true, the currently used value will be gathered and added
|
||||
// to the resulting RlimitStat.
|
||||
func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
return p.RlimitUsageWithContext(context.Background(), gatherUsed)
|
||||
}
|
||||
|
||||
// IOCounters returns IO Counters.
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.IOCountersWithContext(context.Background())
|
||||
}
|
||||
|
||||
// NumCtxSwitches returns the number of the context switches of the process.
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
}
|
||||
|
||||
// NumFDs returns the number of File Descriptors used by the process.
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return p.NumFDsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// NumThreads returns the number of threads used by the process.
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
return p.NumThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Times returns CPU times of the process.
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
return p.TimesWithContext(context.Background())
|
||||
}
|
||||
|
||||
// CPUAffinity returns CPU affinity of the process.
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return p.CPUAffinityWithContext(context.Background())
|
||||
}
|
||||
|
||||
// MemoryInfo returns generic process memory information,
|
||||
// such as RSS and VMS.
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return p.MemoryInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
// MemoryInfoEx returns platform-specific process memory information.
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return p.MemoryInfoExWithContext(context.Background())
|
||||
}
|
||||
|
||||
// PageFaultsInfo returns the process's page fault counters.
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Children returns a slice of Process of the process.
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
// OpenFiles returns a slice of OpenFilesStat opend by the process.
|
||||
// OpenFilesStat includes a file path and file descriptor.
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return p.OpenFilesWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process.
|
||||
// This returns all kind of the connection. This means TCP, UDP or UNIX.
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process at most `max`.
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
// NetIOCounters returns NetIOCounters of the process.
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
|
||||
// MemoryMaps get memory maps from /proc/(pid)/smaps
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
|
||||
// Tgid returns thread group id of the process.
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
return p.TgidWithContext(context.Background())
|
||||
}
|
||||
|
||||
// SendSignal sends a unix.Signal to the process.
|
||||
func (p *Process) SendSignal(sig syscall.Signal) error {
|
||||
return p.SendSignalWithContext(context.Background(), sig)
|
||||
}
|
||||
|
||||
// Suspend sends SIGSTOP to the process.
|
||||
func (p *Process) Suspend() error {
|
||||
return p.SuspendWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Resume sends SIGCONT to the process.
|
||||
func (p *Process) Resume() error {
|
||||
return p.ResumeWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Terminate sends SIGTERM to the process.
|
||||
func (p *Process) Terminate() error {
|
||||
return p.TerminateWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Kill sends SIGKILL to the process.
|
||||
func (p *Process) Kill() error {
|
||||
return p.KillWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Username returns a username of the process.
|
||||
func (p *Process) Username() (string, error) {
|
||||
return p.UsernameWithContext(context.Background())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
// +build darwin freebsd openbsd
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/net"
|
||||
)
|
||||
|
||||
type MemoryInfoExStat struct{}
|
||||
|
||||
type MemoryMapsStat struct{}
|
||||
|
||||
func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
var k KinfoProc
|
||||
br := bytes.NewReader(buf)
|
||||
err := common.Read(br, binary.LittleEndian, &k)
|
||||
return k, err
|
||||
}
|
|
@ -3,16 +3,13 @@
|
|||
package process
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
|
@ -38,13 +35,6 @@ type _Ctype_struct___0 struct {
|
|||
Pad uint64
|
||||
}
|
||||
|
||||
// MemoryInfoExStat is different between OSes
|
||||
type MemoryInfoExStat struct {
|
||||
}
|
||||
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var ret []int32
|
||||
|
||||
|
@ -64,10 +54,6 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
r, err := callPsWithContext(ctx, "ppid", p.Pid, false)
|
||||
if err != nil {
|
||||
|
@ -81,9 +67,6 @@ func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
|||
|
||||
return int32(v), err
|
||||
}
|
||||
func (p *Process) Name() (string, error) {
|
||||
return p.NameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -109,18 +92,6 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
|||
|
||||
return name, nil
|
||||
}
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
// Cmdline returns the command line arguments of the process as a string with
|
||||
// each argument separated by 0x20 ascii character.
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.CmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
r, err := callPsWithContext(ctx, "command", p.Pid, false)
|
||||
|
@ -130,15 +101,11 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
|||
return strings.Join(r[0], " "), err
|
||||
}
|
||||
|
||||
// CmdlineSlice returns the command line arguments of the process as a slice with each
|
||||
// CmdlineSliceWithContext returns the command line arguments of the process as a slice with each
|
||||
// element being an argument. Because of current deficiencies in the way that the command
|
||||
// line arguments are found, single arguments that have spaces in the will actually be
|
||||
// reported as two separate items. In order to do something better CGO would be needed
|
||||
// to use the native darwin functions.
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.CmdlineSliceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
r, err := callPsWithContext(ctx, "command", p.Pid, false)
|
||||
if err != nil {
|
||||
|
@ -177,38 +144,23 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
|||
start := time.Now().Add(-elapsed)
|
||||
return start.Unix() * 1000, nil
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.CwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p.ParentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
rr, err := common.CallLsofWithContext(ctx, invoke, p.Pid, "-FR")
|
||||
out, err := common.CallLsofWithContext(ctx, invoke, p.Pid, "-FR")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range rr {
|
||||
if strings.HasPrefix(r, "p") { // skip if process
|
||||
continue
|
||||
for _, line := range out {
|
||||
if len(line) >= 1 && line[0] == 'R' {
|
||||
v, err := strconv.Atoi(line[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewProcessWithContext(ctx, int32(v))
|
||||
}
|
||||
l := string(r)
|
||||
v, err := strconv.Atoi(strings.Replace(l, "R", "", 1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewProcess(int32(v))
|
||||
}
|
||||
return nil, fmt.Errorf("could not find parent line")
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
r, err := callPsWithContext(ctx, "state", p.Pid, false)
|
||||
|
@ -219,10 +171,6 @@ func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
|||
return r[0][0][0:1], err
|
||||
}
|
||||
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
pid := p.Pid
|
||||
|
@ -237,10 +185,6 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
|||
return strings.IndexByte(string(out), '+') != -1, nil
|
||||
}
|
||||
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
|
@ -252,9 +196,6 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
|
||||
return []int32{userEffectiveUID}, nil
|
||||
}
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
return p.GidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -269,20 +210,18 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
}
|
||||
|
||||
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, common.ErrNotImplementedError
|
||||
// k, err := p.getKProc()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
groups := make([]int32, k.Eproc.Ucred.Ngroups)
|
||||
for i := int16(0); i < k.Eproc.Ucred.Ngroups; i++ {
|
||||
groups[i] = int32(k.Eproc.Ucred.Groups[i])
|
||||
}
|
||||
// groups := make([]int32, k.Eproc.Ucred.Ngroups)
|
||||
// for i := int16(0); i < k.Eproc.Ucred.Ngroups; i++ {
|
||||
// groups[i] = int32(k.Eproc.Ucred.Groups[i])
|
||||
// }
|
||||
|
||||
return groups, nil
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
return p.TerminalWithContext(context.Background())
|
||||
// return groups, nil
|
||||
}
|
||||
|
||||
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -302,9 +241,6 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
|||
return termmap[ttyNr], nil
|
||||
*/
|
||||
}
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -313,53 +249,10 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
|||
}
|
||||
return int32(k.Proc.P_nice), nil
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return p.RlimitWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
return p.RlimitUsageWithContext(context.Background(), gatherUsed)
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.IOCountersWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return p.NumFDsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
return p.NumThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
r, err := callPsWithContext(ctx, "utime,stime", p.Pid, true)
|
||||
|
@ -368,14 +261,6 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
|||
}
|
||||
return int32(len(r)), nil
|
||||
}
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
|
||||
ret := make(map[int32]*cpu.TimesStat)
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func convertCPUTimes(s string) (ret float64, err error) {
|
||||
var t int
|
||||
|
@ -422,9 +307,6 @@ func convertCPUTimes(s string) (ret float64, err error) {
|
|||
t += h
|
||||
return float64(t) / ClockTicks, nil
|
||||
}
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
return p.TimesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
r, err := callPsWithContext(ctx, "utime,stime", p.Pid, false)
|
||||
|
@ -449,16 +331,6 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
|
|||
}
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return p.CPUAffinityWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return p.MemoryInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
r, err := callPsWithContext(ctx, "rss,vsize,pagein", p.Pid, false)
|
||||
|
@ -486,25 +358,6 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
|
|||
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return p.MemoryInfoExWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
|
@ -513,7 +366,7 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcess(pid)
|
||||
np, err := NewProcessWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -522,50 +375,12 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return p.OpenFilesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPid("all", p.Pid)
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
return net.ConnectionsPidWithContext(ctx, "all", p.Pid)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPidMax("all", p.Pid, max)
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
var ret []MemoryMapsStat
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Processes() ([]*Process, error) {
|
||||
return ProcessesWithContext(context.Background())
|
||||
return net.ConnectionsPidMaxWithContext(ctx, "all", p.Pid, max)
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
|
@ -577,7 +392,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
|
||||
for _, pid := range pids {
|
||||
p, err := NewProcess(pid)
|
||||
p, err := NewProcessWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -587,39 +402,12 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
var k KinfoProc
|
||||
br := bytes.NewReader(buf)
|
||||
|
||||
err := common.Read(br, binary.LittleEndian, &k)
|
||||
if err != nil {
|
||||
return k, err
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
// Returns a proc as defined here:
|
||||
// http://unix.superglobalmegacorp.com/Net2/newsrc/sys/kinfo_proc.h.html
|
||||
func (p *Process) getKProc() (*KinfoProc, error) {
|
||||
return p.getKProcWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
|
||||
mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid}
|
||||
procK := KinfoProc{}
|
||||
length := uint64(unsafe.Sizeof(procK))
|
||||
buf := make([]byte, length)
|
||||
_, _, syserr := unix.Syscall6(
|
||||
202, // unix.SYS___SYSCTL https://github.com/golang/sys/blob/76b94024e4b621e672466e8db3d7f084e7ddcad2/unix/zsysnum_darwin_amd64.go#L146
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
uintptr(len(mib)),
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&length)),
|
||||
0,
|
||||
0)
|
||||
if syserr != 0 {
|
||||
return nil, syserr
|
||||
buf, err := unix.SysctlRaw("kern.proc.pid", int(p.Pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k, err := parseKinfoProc(buf)
|
||||
if err != nil {
|
||||
|
|
|
@ -29,10 +29,6 @@ type MemoryInfoExStat struct {
|
|||
}
|
||||
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
return []int32{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Processes() ([]*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
|
@ -41,295 +37,168 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
|
||||
func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
||||
pids, err := PidsWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, i := range pids {
|
||||
if i == pid {
|
||||
return true, err
|
||||
}
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
return false, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Name() (string, error) {
|
||||
return p.NameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
|
||||
func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.CmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.CmdlineSliceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
return []string{}, common.ErrNotImplementedError
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.CwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p.ParentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
return false, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
return []int32{}, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
return p.GidsWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
return []int32{}, common.ErrNotImplementedError
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
|
||||
return []int32{}, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
return p.TerminalWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return p.RlimitWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
return p.RlimitUsageWithContext(context.Background(), gatherUsed)
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.IOCountersWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return p.NumFDsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
return p.NumThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
return p.TimesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return p.CPUAffinityWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return p.MemoryInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return p.MemoryInfoExWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return p.OpenFilesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
return []OpenFilesStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
return []net.IOCountersStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) SendSignal(sig syscall.Signal) error {
|
||||
return p.SendSignalWithContext(context.Background(), sig)
|
||||
}
|
||||
|
||||
func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error {
|
||||
return common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Suspend() error {
|
||||
return p.SuspendWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) SuspendWithContext(ctx context.Context) error {
|
||||
return common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Resume() error {
|
||||
return p.ResumeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ResumeWithContext(ctx context.Context) error {
|
||||
return common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Terminate() error {
|
||||
return p.TerminateWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TerminateWithContext(ctx context.Context) error {
|
||||
return common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Kill() error {
|
||||
return p.KillWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) KillWithContext(ctx context.Context) error {
|
||||
return common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Username() (string, error) {
|
||||
return p.UsernameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
|
|
|
@ -5,7 +5,6 @@ package process
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -17,16 +16,9 @@ import (
|
|||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// MemoryInfoExStat is different between OSes
|
||||
type MemoryInfoExStat struct {
|
||||
}
|
||||
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var ret []int32
|
||||
procs, err := Processes()
|
||||
procs, err := ProcessesWithContext(ctx)
|
||||
if err != nil {
|
||||
return ret, nil
|
||||
}
|
||||
|
@ -38,10 +30,6 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
|
@ -50,9 +38,6 @@ func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
|||
|
||||
return k.Ppid, nil
|
||||
}
|
||||
func (p *Process) Name() (string, error) {
|
||||
return p.NameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -78,21 +63,11 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
|||
|
||||
return name, nil
|
||||
}
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.CmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
|
@ -109,10 +84,6 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
|||
return strings.Join(ret, " "), nil
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.CmdlineSliceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
|
@ -137,22 +108,9 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
|
|||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.CwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p.ParentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return p, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -181,10 +139,6 @@ func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
pid := p.Pid
|
||||
|
@ -199,10 +153,6 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
|||
return strings.IndexByte(string(out), '+') != -1, nil
|
||||
}
|
||||
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
|
@ -215,9 +165,6 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
|
||||
return uids, nil
|
||||
}
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
return p.GidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -244,9 +191,6 @@ func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
|
|||
|
||||
return groups, nil
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
return p.TerminalWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -263,9 +207,6 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
|||
|
||||
return termmap[ttyNr], nil
|
||||
}
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -274,32 +215,6 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
|||
}
|
||||
return int32(k.Nice), nil
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return p.RlimitWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
return p.RlimitUsageWithContext(context.Background(), gatherUsed)
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.IOCountersWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -311,23 +226,6 @@ func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, e
|
|||
WriteCount: uint64(k.Rusage.Oublock),
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return p.NumFDsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
return p.NumThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -337,17 +235,6 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
|||
|
||||
return k.Numthreads, nil
|
||||
}
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
|
||||
ret := make(map[int32]*cpu.TimesStat)
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
return p.TimesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -360,16 +247,6 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
|
|||
System: float64(k.Rusage.Stime.Sec) + float64(k.Rusage.Stime.Usec)/1000000,
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return p.CPUAffinityWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return p.MemoryInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -387,25 +264,6 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
|
|||
VMS: uint64(k.Size),
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return p.MemoryInfoExWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
|
@ -414,7 +272,7 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcess(pid)
|
||||
np, err := NewProcessWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -423,52 +281,14 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return p.OpenFilesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
var ret []MemoryMapsStat
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Processes() ([]*Process, error) {
|
||||
return ProcessesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
results := []*Process{}
|
||||
|
||||
|
@ -488,7 +308,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p, err := NewProcess(int32(k.Pid))
|
||||
p, err := NewProcessWithContext(ctx, int32(k.Pid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -499,18 +319,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return results, nil
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
var k KinfoProc
|
||||
br := bytes.NewReader(buf)
|
||||
err := common.Read(br, binary.LittleEndian, &k)
|
||||
return k, err
|
||||
}
|
||||
|
||||
func (p *Process) getKProc() (*KinfoProc, error) {
|
||||
return p.getKProcWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
|
||||
mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid}
|
||||
|
||||
buf, length, err := common.CallSyscall(mib)
|
||||
|
|
|
@ -64,11 +64,6 @@ func (m MemoryMapsStat) String() string {
|
|||
return string(s)
|
||||
}
|
||||
|
||||
// Ppid returns Parent Process ID of the process.
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
_, ppid, _, _, _, _, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -77,11 +72,6 @@ func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
|||
return ppid, nil
|
||||
}
|
||||
|
||||
// Name returns name of the process.
|
||||
func (p *Process) Name() (string, error) {
|
||||
return p.NameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
if p.name == "" {
|
||||
if err := p.fillFromStatusWithContext(ctx); err != nil {
|
||||
|
@ -91,41 +81,23 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
|||
return p.name, nil
|
||||
}
|
||||
|
||||
// Tgid returns tgid, a Linux-synonym for user-space Pid
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
|
||||
if p.tgid == 0 {
|
||||
if err := p.fillFromStatusWithContext(context.Background()); err != nil {
|
||||
if err := p.fillFromStatusWithContext(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return p.tgid, nil
|
||||
}
|
||||
|
||||
// Exe returns executable path of the process.
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromExeWithContext(ctx)
|
||||
}
|
||||
|
||||
// Cmdline returns the command line arguments of the process as a string with
|
||||
// each argument separated by 0x20 ascii character.
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.CmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromCmdlineWithContext(ctx)
|
||||
}
|
||||
|
||||
// CmdlineSlice returns the command line arguments of the process as a slice with each
|
||||
// element being an argument.
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.CmdlineSliceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
return p.fillSliceFromCmdlineWithContext(ctx)
|
||||
}
|
||||
|
@ -138,20 +110,10 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
|||
return createTime, nil
|
||||
}
|
||||
|
||||
// Cwd returns current working directory of the process.
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.CwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromCwdWithContext(ctx)
|
||||
}
|
||||
|
||||
// Parent returns parent Process of the process.
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p.ParentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -160,16 +122,7 @@ func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
|||
if p.parent == 0 {
|
||||
return nil, fmt.Errorf("wrong number of parents")
|
||||
}
|
||||
return NewProcess(p.parent)
|
||||
}
|
||||
|
||||
// Status returns the process status.
|
||||
// Return value could be one of these.
|
||||
// R: Running S: Sleep T: Stop I: Idle
|
||||
// Z: Zombie W: Wait L: Lock
|
||||
// The character is same within all supported platforms.
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
return NewProcessWithContext(ctx, p.parent)
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -180,11 +133,6 @@ func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
|||
return p.status, nil
|
||||
}
|
||||
|
||||
// Foreground returns true if the process is in foreground, false otherwise.
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
pid := p.Pid
|
||||
|
@ -202,11 +150,6 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
|||
return pgid == tpgid, nil
|
||||
}
|
||||
|
||||
// Uids returns user ids of the process as a slice of the int
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -215,11 +158,6 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
return p.uids, nil
|
||||
}
|
||||
|
||||
// Gids returns group ids of the process as a slice of the int
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
return p.GidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -236,11 +174,6 @@ func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
|
|||
return p.groups, nil
|
||||
}
|
||||
|
||||
// Terminal returns a terminal which is associated with the process.
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
return p.TerminalWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
t, _, _, _, _, _, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -254,12 +187,6 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
|||
return terminal, nil
|
||||
}
|
||||
|
||||
// Nice returns a nice value (priority).
|
||||
// Notice: gopsutil can not set nice value.
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
_, _, _, _, _, nice, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -268,29 +195,12 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
|||
return nice, nil
|
||||
}
|
||||
|
||||
// IOnice returns process I/O nice value (priority).
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Rlimit returns Resource Limits.
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return p.RlimitWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
return p.RlimitUsage(false)
|
||||
}
|
||||
|
||||
// RlimitUsage returns Resource Limits.
|
||||
// If gatherUsed is true, the currently used value will be gathered and added
|
||||
// to the resulting RlimitStat.
|
||||
func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
return p.RlimitUsageWithContext(context.Background(), gatherUsed)
|
||||
return p.RlimitUsageWithContext(ctx, false)
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
|
@ -311,7 +221,7 @@ func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) (
|
|||
rs := &rlimits[i]
|
||||
switch rs.Resource {
|
||||
case RLIMIT_CPU:
|
||||
times, err := p.Times()
|
||||
times, err := p.TimesWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -323,7 +233,7 @@ func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) (
|
|||
case RLIMIT_RSS:
|
||||
rs.Used = uint64(p.memInfo.RSS)
|
||||
case RLIMIT_NOFILE:
|
||||
n, err := p.NumFDs()
|
||||
n, err := p.NumFDsWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -348,20 +258,10 @@ func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) (
|
|||
return rlimits, err
|
||||
}
|
||||
|
||||
// IOCounters returns IO Counters.
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.IOCountersWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
return p.fillFromIOWithContext(ctx)
|
||||
}
|
||||
|
||||
// NumCtxSwitches returns the number of the context switches of the process.
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -370,21 +270,11 @@ func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitche
|
|||
return p.numCtxSwitches, nil
|
||||
}
|
||||
|
||||
// NumFDs returns the number of File Descriptors used by the process.
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return p.NumFDsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
_, fnames, err := p.fillFromfdListWithContext(ctx)
|
||||
return int32(len(fnames)), err
|
||||
}
|
||||
|
||||
// NumThreads returns the number of threads used by the process.
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
return p.NumThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -393,10 +283,6 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
|||
return p.numThreads, nil
|
||||
}
|
||||
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
|
||||
ret := make(map[int32]*cpu.TimesStat)
|
||||
taskPath := common.HostProc(strconv.Itoa(int(p.Pid)), "task")
|
||||
|
@ -417,11 +303,6 @@ func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesS
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
// Times returns CPU times of the process.
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
return p.TimesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
_, _, cpuTimes, _, _, _, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -430,22 +311,10 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
|
|||
return cpuTimes, nil
|
||||
}
|
||||
|
||||
// CPUAffinity returns CPU affinity of the process.
|
||||
//
|
||||
// Notice: Not implemented yet.
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return p.CPUAffinityWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// MemoryInfo returns platform in-dependend memory information, such as RSS, VMS and Swap
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return p.MemoryInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
meminfo, _, err := p.fillFromStatmWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -454,11 +323,6 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
|
|||
return meminfo, nil
|
||||
}
|
||||
|
||||
// MemoryInfoEx returns platform dependend memory information.
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return p.MemoryInfoExWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
_, memInfoEx, err := p.fillFromStatmWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -467,11 +331,6 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
|
|||
return memInfoEx, nil
|
||||
}
|
||||
|
||||
// PageFaultsInfo returns the process's page fault counters
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
_, _, _, _, _, _, pageFaults, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -481,11 +340,6 @@ func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, e
|
|||
|
||||
}
|
||||
|
||||
// Children returns a slice of Process of the process.
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
if err != nil {
|
||||
|
@ -496,7 +350,7 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcess(pid)
|
||||
np, err := NewProcessWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -505,12 +359,6 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
// OpenFiles returns a slice of OpenFilesStat opend by the process.
|
||||
// OpenFilesStat includes a file path and file descriptor.
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return p.OpenFilesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
_, ofs, err := p.fillFromfdWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -524,38 +372,17 @@ func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, er
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process.
|
||||
// This returns all kind of the connection. This measn TCP, UDP or UNIX.
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPid("all", p.Pid)
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
return net.ConnectionsPidWithContext(ctx, "all", p.Pid)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPidMax("all", p.Pid, max)
|
||||
}
|
||||
|
||||
// NetIOCounters returns NetIOCounters of the process.
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
return net.ConnectionsPidMaxWithContext(ctx, "all", p.Pid, max)
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
filename := common.HostProc(strconv.Itoa(int(p.Pid)), "net/dev")
|
||||
return net.IOCountersByFile(pernic, filename)
|
||||
}
|
||||
|
||||
// MemoryMaps get memory maps from /proc/(pid)/smaps
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
return net.IOCountersByFileWithContext(ctx, pernic, filename)
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
|
@ -572,9 +399,9 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
|
|||
lines := strings.Split(string(contents), "\n")
|
||||
|
||||
// function of parsing a block
|
||||
getBlock := func(first_line []string, block []string) (MemoryMapsStat, error) {
|
||||
getBlock := func(firstLine []string, block []string) (MemoryMapsStat, error) {
|
||||
m := MemoryMapsStat{}
|
||||
m.Path = first_line[len(first_line)-1]
|
||||
m.Path = firstLine[len(firstLine)-1]
|
||||
|
||||
for _, line := range block {
|
||||
if strings.Contains(line, "VmFlags") {
|
||||
|
@ -617,13 +444,15 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
|
|||
return m, nil
|
||||
}
|
||||
|
||||
blocks := make([]string, 16)
|
||||
for _, line := range lines {
|
||||
var firstLine []string
|
||||
blocks := make([]string, 0, 16)
|
||||
for i, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) > 0 && !strings.HasSuffix(fields[0], ":") {
|
||||
|
||||
if (len(fields) > 0 && !strings.HasSuffix(fields[0], ":")) || i == len(lines)-1 {
|
||||
// new block section
|
||||
if len(blocks) > 0 {
|
||||
g, err := getBlock(fields, blocks)
|
||||
if len(firstLine) > 0 && len(blocks) > 0 {
|
||||
g, err := getBlock(firstLine, blocks)
|
||||
if err != nil {
|
||||
return &ret, err
|
||||
}
|
||||
|
@ -643,7 +472,8 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
|
|||
}
|
||||
}
|
||||
// starts new block
|
||||
blocks = make([]string, 16)
|
||||
blocks = make([]string, 0, 16)
|
||||
firstLine = fields
|
||||
} else {
|
||||
blocks = append(blocks, line)
|
||||
}
|
||||
|
@ -1181,7 +1011,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
|||
// docs). Note: I am assuming at least Linux 2.6.18
|
||||
iotime, err := strconv.ParseFloat(fields[i+40], 64)
|
||||
if err != nil {
|
||||
iotime = 0 // Ancient linux version, most likely
|
||||
iotime = 0 // Ancient linux version, most likely
|
||||
}
|
||||
|
||||
cpuTimes := &cpu.TimesStat{
|
||||
|
@ -1249,12 +1079,6 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
return readPidsFromDir(common.HostProc())
|
||||
}
|
||||
|
||||
// Process returns a slice of pointers to Process structs for all
|
||||
// currently running processes.
|
||||
func Processes() ([]*Process, error) {
|
||||
return ProcessesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
out := []*Process{}
|
||||
|
||||
|
@ -1264,7 +1088,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
|
||||
for _, pid := range pids {
|
||||
p, err := NewProcess(pid)
|
||||
p, err := NewProcessWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -4,9 +4,7 @@ package process
|
|||
|
||||
import (
|
||||
"C"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -20,16 +18,9 @@ import (
|
|||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// MemoryInfoExStat is different between OSes
|
||||
type MemoryInfoExStat struct {
|
||||
}
|
||||
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var ret []int32
|
||||
procs, err := Processes()
|
||||
procs, err := ProcessesWithContext(ctx)
|
||||
if err != nil {
|
||||
return ret, nil
|
||||
}
|
||||
|
@ -41,10 +32,6 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
|
@ -53,9 +40,6 @@ func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
|||
|
||||
return k.Ppid, nil
|
||||
}
|
||||
func (p *Process) Name() (string, error) {
|
||||
return p.NameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -81,21 +65,11 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
|||
|
||||
return name, nil
|
||||
}
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.CmdlineSliceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
mib := []int32{CTLKern, KernProcArgs, p.Pid, KernProcArgv}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
|
@ -119,12 +93,8 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
|
|||
return strParts, nil
|
||||
}
|
||||
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.CmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
argv, err := p.CmdlineSlice()
|
||||
argv, err := p.CmdlineSliceWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -134,22 +104,9 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
|||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.CwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p.ParentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return p, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -173,9 +130,6 @@ func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
|||
|
||||
return s, nil
|
||||
}
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
|
@ -190,9 +144,6 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
|||
}
|
||||
return strings.IndexByte(string(out), '+') != -1, nil
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -206,9 +157,6 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
|
||||
return uids, nil
|
||||
}
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
return p.GidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -221,16 +169,19 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
|||
|
||||
return gids, nil
|
||||
}
|
||||
|
||||
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return k.Groups, nil
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
return p.TerminalWithContext(context.Background())
|
||||
groups := make([]int32, k.Ngroups)
|
||||
for i := int16(0); i < k.Ngroups; i++ {
|
||||
groups[i] = int32(k.Groups[i])
|
||||
}
|
||||
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -248,9 +199,6 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
|||
|
||||
return termmap[ttyNr], nil
|
||||
}
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -259,32 +207,6 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
|||
}
|
||||
return int32(k.Nice), nil
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return p.RlimitWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
return p.RlimitUsageWithContext(context.Background(), gatherUsed)
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.IOCountersWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -296,39 +218,11 @@ func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, e
|
|||
WriteCount: uint64(k.Uru_oublock),
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return p.NumFDsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
return p.NumThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
/* not supported, just return 1 */
|
||||
return 1, nil
|
||||
}
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
|
||||
ret := make(map[int32]*cpu.TimesStat)
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
return p.TimesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
k, err := p.getKProc()
|
||||
|
@ -341,23 +235,13 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
|
|||
System: float64(k.Ustime_sec) + float64(k.Ustime_usec)/1000000,
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return p.CPUAffinityWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return p.MemoryInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pageSize, err := mem.GetPageSize()
|
||||
pageSize, err := mem.GetPageSizeWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -368,25 +252,6 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
|
|||
uint64(k.Vm_ssize),
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return p.MemoryInfoExWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
|
@ -395,7 +260,7 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcess(pid)
|
||||
np, err := NewProcessWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -404,55 +269,18 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return p.OpenFilesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
var ret []MemoryMapsStat
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Processes() ([]*Process, error) {
|
||||
return ProcessesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
results := []*Process{}
|
||||
|
||||
buf, length, err := CallKernProcSyscall(KernProcAll, 0)
|
||||
buf, length, err := callKernProcSyscall(KernProcAll, 0)
|
||||
|
||||
if err != nil {
|
||||
return results, err
|
||||
|
@ -468,7 +296,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p, err := NewProcess(int32(k.Pid))
|
||||
p, err := NewProcessWithContext(ctx, int32(k.Pid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -479,19 +307,8 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return results, nil
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
var k KinfoProc
|
||||
br := bytes.NewReader(buf)
|
||||
err := common.Read(br, binary.LittleEndian, &k)
|
||||
return k, err
|
||||
}
|
||||
|
||||
func (p *Process) getKProc() (*KinfoProc, error) {
|
||||
return p.getKProcWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
|
||||
buf, length, err := CallKernProcSyscall(KernProcPID, p.Pid)
|
||||
buf, length, err := callKernProcSyscall(KernProcPID, p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -506,11 +323,7 @@ func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
|
|||
return &k, nil
|
||||
}
|
||||
|
||||
func CallKernProcSyscall(op int32, arg int32) ([]byte, uint64, error) {
|
||||
return CallKernProcSyscallWithContext(context.Background(), op, arg)
|
||||
}
|
||||
|
||||
func CallKernProcSyscallWithContext(ctx context.Context, op int32, arg int32) ([]byte, uint64, error) {
|
||||
func callKernProcSyscall(op int32, arg int32) ([]byte, uint64, error) {
|
||||
mib := []int32{CTLKern, KernProc, op, arg, sizeOfKinfoProc, 0}
|
||||
mibptr := unsafe.Pointer(&mib[0])
|
||||
miblen := uint64(len(mib))
|
||||
|
|
|
@ -114,12 +114,6 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
// SendSignal sends a unix.Signal to the process.
|
||||
// Currently, SIGSTOP, SIGCONT, SIGTERM and SIGKILL are supported.
|
||||
func (p *Process) SendSignal(sig syscall.Signal) error {
|
||||
return p.SendSignalWithContext(context.Background(), sig)
|
||||
}
|
||||
|
||||
func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error {
|
||||
process, err := os.FindProcess(int(p.Pid))
|
||||
if err != nil {
|
||||
|
@ -134,49 +128,24 @@ func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal)
|
|||
return nil
|
||||
}
|
||||
|
||||
// Suspend sends SIGSTOP to the process.
|
||||
func (p *Process) Suspend() error {
|
||||
return p.SuspendWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) SuspendWithContext(ctx context.Context) error {
|
||||
return p.SendSignal(unix.SIGSTOP)
|
||||
}
|
||||
|
||||
// Resume sends SIGCONT to the process.
|
||||
func (p *Process) Resume() error {
|
||||
return p.ResumeWithContext(context.Background())
|
||||
return p.SendSignalWithContext(ctx, unix.SIGSTOP)
|
||||
}
|
||||
|
||||
func (p *Process) ResumeWithContext(ctx context.Context) error {
|
||||
return p.SendSignal(unix.SIGCONT)
|
||||
}
|
||||
|
||||
// Terminate sends SIGTERM to the process.
|
||||
func (p *Process) Terminate() error {
|
||||
return p.TerminateWithContext(context.Background())
|
||||
return p.SendSignalWithContext(ctx, unix.SIGCONT)
|
||||
}
|
||||
|
||||
func (p *Process) TerminateWithContext(ctx context.Context) error {
|
||||
return p.SendSignal(unix.SIGTERM)
|
||||
}
|
||||
|
||||
// Kill sends SIGKILL to the process.
|
||||
func (p *Process) Kill() error {
|
||||
return p.KillWithContext(context.Background())
|
||||
return p.SendSignalWithContext(ctx, unix.SIGTERM)
|
||||
}
|
||||
|
||||
func (p *Process) KillWithContext(ctx context.Context) error {
|
||||
return p.SendSignal(unix.SIGKILL)
|
||||
}
|
||||
|
||||
// Username returns a username of the process.
|
||||
func (p *Process) Username() (string, error) {
|
||||
return p.UsernameWithContext(context.Background())
|
||||
return p.SendSignalWithContext(ctx, unix.SIGKILL)
|
||||
}
|
||||
|
||||
func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
|
||||
uids, err := p.Uids()
|
||||
uids, err := p.UidsWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -235,38 +235,43 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
|||
return exitCode == STILL_ACTIVE, err
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
// if cached already, return from cache
|
||||
cachedPpid := p.getPpid()
|
||||
if cachedPpid != 0 {
|
||||
return cachedPpid, nil
|
||||
}
|
||||
|
||||
ppid, _, _, err := getFromSnapProcess(p.Pid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// no errors and not cached already, so cache it
|
||||
p.setPpid(ppid)
|
||||
|
||||
return ppid, nil
|
||||
}
|
||||
|
||||
func (p *Process) Name() (string, error) {
|
||||
return p.NameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
_, _, name, err := getFromSnapProcess(p.Pid)
|
||||
ppid, _, name, err := getFromSnapProcess(p.Pid)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not get Name: %s", err)
|
||||
}
|
||||
|
||||
// if no errors and not cached already, cache ppid
|
||||
p.parent = ppid
|
||||
if 0 == p.getPpid() {
|
||||
p.setPpid(ppid)
|
||||
}
|
||||
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
|
@ -294,10 +299,6 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
|||
return common.ConvertDOSPath(windows.UTF16ToString(buf[:])), nil
|
||||
}
|
||||
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.CmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
|
||||
cmdline, err := getProcessCommandLine(p.Pid)
|
||||
if err != nil {
|
||||
|
@ -306,13 +307,6 @@ func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
|
|||
return cmdline, nil
|
||||
}
|
||||
|
||||
// CmdlineSlice returns the command line arguments of the process as a slice with each
|
||||
// element being an argument. This merely returns the CommandLine informations passed
|
||||
// to the process split on the 0x20 ASCII character.
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.CmdlineSliceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
cmdline, err := p.CmdlineWithContext(ctx)
|
||||
if err != nil {
|
||||
|
@ -330,16 +324,9 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
|||
return ru.CreationTime.Nanoseconds() / 1000000, nil
|
||||
}
|
||||
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.CwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p.ParentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
ppid, err := p.PpidWithContext(ctx)
|
||||
|
@ -347,28 +334,17 @@ func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
|||
return nil, fmt.Errorf("could not get ParentProcessID: %s", err)
|
||||
}
|
||||
|
||||
return NewProcess(ppid)
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
return NewProcessWithContext(ctx, ppid)
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
return false, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Username() (string, error) {
|
||||
return p.UsernameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
|
||||
pid := p.Pid
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
|
||||
|
@ -392,30 +368,16 @@ func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
|
|||
return domain + "\\" + user, err
|
||||
}
|
||||
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var uids []int32
|
||||
|
||||
return uids, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
return p.GidsWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var gids []int32
|
||||
return gids, common.ErrNotImplementedError
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var groups []int32
|
||||
return groups, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
return p.TerminalWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -434,11 +396,6 @@ var priorityClasses = map[int]int32{
|
|||
0x00000100: 24, // REALTIME_PRIORITY_CLASS
|
||||
}
|
||||
|
||||
// Nice returns priority in Windows
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
|
@ -455,34 +412,17 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
|||
}
|
||||
return priority, nil
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return p.RlimitWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
return p.RlimitUsageWithContext(context.Background(), gatherUsed)
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.IOCountersWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
|
@ -505,41 +445,32 @@ func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, e
|
|||
|
||||
return stats, nil
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return p.NumFDsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
return p.NumThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
_, ret, _, err := getFromSnapProcess(p.Pid)
|
||||
ppid, ret, _, err := getFromSnapProcess(p.Pid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// if no errors and not cached already, cache ppid
|
||||
p.parent = ppid
|
||||
if 0 == p.getPpid() {
|
||||
p.setPpid(ppid)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
|
||||
ret := make(map[int32]*cpu.TimesStat)
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
return p.TimesWithContext(context.Background())
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
|
@ -565,16 +496,10 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
|
|||
System: kernel,
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return p.CPUAffinityWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return p.MemoryInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
mem, err := getMemoryInfo(p.Pid)
|
||||
|
@ -589,26 +514,15 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
|
|||
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return p.MemoryInfoExWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
out := []*Process{}
|
||||
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(0))
|
||||
|
@ -623,7 +537,7 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
for {
|
||||
if pe32.ParentProcessID == uint32(p.Pid) {
|
||||
p, err := NewProcess(int32(pe32.ProcessID))
|
||||
p, err := NewProcessWithContext(ctx, int32(pe32.ProcessID))
|
||||
if err == nil {
|
||||
out = append(out, p)
|
||||
}
|
||||
|
@ -635,59 +549,30 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return p.OpenFilesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPidWithContext(ctx, "all", p.Pid)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
var ret []MemoryMapsStat
|
||||
return &ret, common.ErrNotImplementedError
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) SendSignal(sig windows.Signal) error {
|
||||
return p.SendSignalWithContext(context.Background(), sig)
|
||||
}
|
||||
|
||||
func (p *Process) SendSignalWithContext(ctx context.Context, sig windows.Signal) error {
|
||||
func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error {
|
||||
return common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Suspend() error {
|
||||
return p.SuspendWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) SuspendWithContext(ctx context.Context) error {
|
||||
c, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
|
@ -695,7 +580,7 @@ func (p *Process) SuspendWithContext(ctx context.Context) error {
|
|||
}
|
||||
defer windows.CloseHandle(c)
|
||||
|
||||
r1, _, _ := procNtSuspendProcess.Call(uintptr(unsafe.Pointer(c)))
|
||||
r1, _, _ := procNtSuspendProcess.Call(uintptr(c))
|
||||
if r1 != 0 {
|
||||
// See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
|
||||
return fmt.Errorf("NtStatus='0x%.8X'", r1)
|
||||
|
@ -704,10 +589,6 @@ func (p *Process) SuspendWithContext(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Process) Resume() error {
|
||||
return p.ResumeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ResumeWithContext(ctx context.Context) error {
|
||||
c, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
|
@ -715,7 +596,7 @@ func (p *Process) ResumeWithContext(ctx context.Context) error {
|
|||
}
|
||||
defer windows.CloseHandle(c)
|
||||
|
||||
r1, _, _ := procNtResumeProcess.Call(uintptr(unsafe.Pointer(c)))
|
||||
r1, _, _ := procNtResumeProcess.Call(uintptr(c))
|
||||
if r1 != 0 {
|
||||
// See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
|
||||
return fmt.Errorf("NtStatus='0x%.8X'", r1)
|
||||
|
@ -724,10 +605,6 @@ func (p *Process) ResumeWithContext(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Process) Terminate() error {
|
||||
return p.TerminateWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) TerminateWithContext(ctx context.Context) error {
|
||||
proc, err := windows.OpenProcess(windows.PROCESS_TERMINATE, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
|
@ -738,15 +615,26 @@ func (p *Process) TerminateWithContext(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (p *Process) Kill() error {
|
||||
return p.KillWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) KillWithContext(ctx context.Context) error {
|
||||
process := os.Process{Pid: int(p.Pid)}
|
||||
return process.Kill()
|
||||
}
|
||||
|
||||
// retrieve Ppid in a thread-safe manner
|
||||
func (p *Process) getPpid() int32 {
|
||||
p.parentMutex.RLock()
|
||||
defer p.parentMutex.RUnlock()
|
||||
return p.parent
|
||||
}
|
||||
|
||||
// cache Ppid in a thread-safe manner (WINDOWS ONLY)
|
||||
// see https://psutil.readthedocs.io/en/latest/#psutil.Process.ppid
|
||||
func (p *Process) setPpid(ppid int32) {
|
||||
p.parentMutex.Lock()
|
||||
defer p.parentMutex.Unlock()
|
||||
p.parent = ppid
|
||||
}
|
||||
|
||||
func getFromSnapProcess(pid int32) (int32, int32, string, error) {
|
||||
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(pid))
|
||||
if err != nil {
|
||||
|
@ -770,11 +658,6 @@ func getFromSnapProcess(pid int32) (int32, int32, string, error) {
|
|||
return 0, 0, "", fmt.Errorf("couldn't find pid: %d", pid)
|
||||
}
|
||||
|
||||
// Get processes
|
||||
func Processes() ([]*Process, error) {
|
||||
return ProcessesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
out := []*Process{}
|
||||
|
||||
|
@ -784,7 +667,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|||
}
|
||||
|
||||
for _, pid := range pids {
|
||||
p, err := NewProcess(pid)
|
||||
p, err := NewProcessWithContext(ctx, pid)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -39,31 +39,34 @@ func initOptions() {
|
|||
|
||||
func archInit() {
|
||||
switch runtime.GOOS {
|
||||
case "android", "darwin", "ios", "netbsd":
|
||||
// Android and iOS don't seem to allow reading these registers.
|
||||
//
|
||||
// NetBSD:
|
||||
// ID_AA64ISAR0_EL1 is a privileged register and cannot be read from EL0.
|
||||
// It can be read via sysctl(3). Example for future implementers:
|
||||
// https://nxr.netbsd.org/xref/src/usr.sbin/cpuctl/arch/aarch64.c
|
||||
//
|
||||
// Fake the minimal features expected by
|
||||
// TestARM64minimalFeatures.
|
||||
ARM64.HasASIMD = true
|
||||
ARM64.HasFP = true
|
||||
case "linux":
|
||||
case "freebsd":
|
||||
readARM64Registers()
|
||||
case "linux", "netbsd":
|
||||
doinit()
|
||||
default:
|
||||
readARM64Registers()
|
||||
// Most platforms don't seem to allow reading these registers.
|
||||
//
|
||||
// OpenBSD:
|
||||
// See https://golang.org/issue/31746
|
||||
setMinimalFeatures()
|
||||
}
|
||||
}
|
||||
|
||||
// setMinimalFeatures fakes the minimal ARM64 features expected by
|
||||
// TestARM64minimalFeatures.
|
||||
func setMinimalFeatures() {
|
||||
ARM64.HasASIMD = true
|
||||
ARM64.HasFP = true
|
||||
}
|
||||
|
||||
func readARM64Registers() {
|
||||
Initialized = true
|
||||
|
||||
// ID_AA64ISAR0_EL1
|
||||
isar0 := getisar0()
|
||||
parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0())
|
||||
}
|
||||
|
||||
func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) {
|
||||
// ID_AA64ISAR0_EL1
|
||||
switch extractBits(isar0, 4, 7) {
|
||||
case 1:
|
||||
ARM64.HasAES = true
|
||||
|
@ -121,8 +124,6 @@ func readARM64Registers() {
|
|||
}
|
||||
|
||||
// ID_AA64ISAR1_EL1
|
||||
isar1 := getisar1()
|
||||
|
||||
switch extractBits(isar1, 0, 3) {
|
||||
case 1:
|
||||
ARM64.HasDCPOP = true
|
||||
|
@ -144,8 +145,6 @@ func readARM64Registers() {
|
|||
}
|
||||
|
||||
// ID_AA64PFR0_EL1
|
||||
pfr0 := getpfr0()
|
||||
|
||||
switch extractBits(pfr0, 16, 19) {
|
||||
case 0:
|
||||
ARM64.HasFP = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
package cpu
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
package cpu
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 amd64 amd64p32
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
package cpu
|
||||
|
||||
|
|
|
@ -17,86 +17,7 @@ const (
|
|||
hwcap_VXE = 8192
|
||||
)
|
||||
|
||||
// bitIsSet reports whether the bit at index is set. The bit index
|
||||
// is in big endian order, so bit index 0 is the leftmost bit.
|
||||
func bitIsSet(bits []uint64, index uint) bool {
|
||||
return bits[index/64]&((1<<63)>>(index%64)) != 0
|
||||
}
|
||||
|
||||
// function is the code for the named cryptographic function.
|
||||
type function uint8
|
||||
|
||||
const (
|
||||
// KM{,A,C,CTR} function codes
|
||||
aes128 function = 18 // AES-128
|
||||
aes192 function = 19 // AES-192
|
||||
aes256 function = 20 // AES-256
|
||||
|
||||
// K{I,L}MD function codes
|
||||
sha1 function = 1 // SHA-1
|
||||
sha256 function = 2 // SHA-256
|
||||
sha512 function = 3 // SHA-512
|
||||
sha3_224 function = 32 // SHA3-224
|
||||
sha3_256 function = 33 // SHA3-256
|
||||
sha3_384 function = 34 // SHA3-384
|
||||
sha3_512 function = 35 // SHA3-512
|
||||
shake128 function = 36 // SHAKE-128
|
||||
shake256 function = 37 // SHAKE-256
|
||||
|
||||
// KLMD function codes
|
||||
ghash function = 65 // GHASH
|
||||
)
|
||||
|
||||
// queryResult contains the result of a Query function
|
||||
// call. Bits are numbered in big endian order so the
|
||||
// leftmost bit (the MSB) is at index 0.
|
||||
type queryResult struct {
|
||||
bits [2]uint64
|
||||
}
|
||||
|
||||
// Has reports whether the given functions are present.
|
||||
func (q *queryResult) Has(fns ...function) bool {
|
||||
if len(fns) == 0 {
|
||||
panic("no function codes provided")
|
||||
}
|
||||
for _, f := range fns {
|
||||
if !bitIsSet(q.bits[:], uint(f)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// facility is a bit index for the named facility.
|
||||
type facility uint8
|
||||
|
||||
const (
|
||||
// cryptography facilities
|
||||
msa4 facility = 77 // message-security-assist extension 4
|
||||
msa8 facility = 146 // message-security-assist extension 8
|
||||
)
|
||||
|
||||
// facilityList contains the result of an STFLE call.
|
||||
// Bits are numbered in big endian order so the
|
||||
// leftmost bit (the MSB) is at index 0.
|
||||
type facilityList struct {
|
||||
bits [4]uint64
|
||||
}
|
||||
|
||||
// Has reports whether the given facilities are present.
|
||||
func (s *facilityList) Has(fs ...facility) bool {
|
||||
if len(fs) == 0 {
|
||||
panic("no facility bits provided")
|
||||
}
|
||||
for _, f := range fs {
|
||||
if !bitIsSet(s.bits[:], uint(f)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func doinit() {
|
||||
func initS390Xbase() {
|
||||
// test HWCAP bit vector
|
||||
has := func(featureMask uint) bool {
|
||||
return hwCap&featureMask == featureMask
|
||||
|
@ -116,44 +37,4 @@ func doinit() {
|
|||
if S390X.HasVX {
|
||||
S390X.HasVXE = has(hwcap_VXE)
|
||||
}
|
||||
|
||||
// We need implementations of stfle, km and so on
|
||||
// to detect cryptographic features.
|
||||
if !haveAsmFunctions() {
|
||||
return
|
||||
}
|
||||
|
||||
// optional cryptographic functions
|
||||
if S390X.HasMSA {
|
||||
aes := []function{aes128, aes192, aes256}
|
||||
|
||||
// cipher message
|
||||
km, kmc := kmQuery(), kmcQuery()
|
||||
S390X.HasAES = km.Has(aes...)
|
||||
S390X.HasAESCBC = kmc.Has(aes...)
|
||||
if S390X.HasSTFLE {
|
||||
facilities := stfle()
|
||||
if facilities.Has(msa4) {
|
||||
kmctr := kmctrQuery()
|
||||
S390X.HasAESCTR = kmctr.Has(aes...)
|
||||
}
|
||||
if facilities.Has(msa8) {
|
||||
kma := kmaQuery()
|
||||
S390X.HasAESGCM = kma.Has(aes...)
|
||||
}
|
||||
}
|
||||
|
||||
// compute message digest
|
||||
kimd := kimdQuery() // intermediate (no padding)
|
||||
klmd := klmdQuery() // last (padding)
|
||||
S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1)
|
||||
S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256)
|
||||
S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512)
|
||||
S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist
|
||||
sha3 := []function{
|
||||
sha3_224, sha3_256, sha3_384, sha3_512,
|
||||
shake128, shake256,
|
||||
}
|
||||
S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Minimal copy of functionality from x/sys/unix so the cpu package can call
|
||||
// sysctl without depending on x/sys/unix.
|
||||
|
||||
const (
|
||||
_CTL_QUERY = -2
|
||||
|
||||
_SYSCTL_VERS_1 = 0x1000000
|
||||
)
|
||||
|
||||
var _zero uintptr
|
||||
|
||||
func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
|
||||
var _p0 unsafe.Pointer
|
||||
if len(mib) > 0 {
|
||||
_p0 = unsafe.Pointer(&mib[0])
|
||||
} else {
|
||||
_p0 = unsafe.Pointer(&_zero)
|
||||
}
|
||||
_, _, errno := syscall.Syscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(_p0),
|
||||
uintptr(len(mib)),
|
||||
uintptr(unsafe.Pointer(old)),
|
||||
uintptr(unsafe.Pointer(oldlen)),
|
||||
uintptr(unsafe.Pointer(new)),
|
||||
uintptr(newlen))
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type sysctlNode struct {
|
||||
Flags uint32
|
||||
Num int32
|
||||
Name [32]int8
|
||||
Ver uint32
|
||||
__rsvd uint32
|
||||
Un [16]byte
|
||||
_sysctl_size [8]byte
|
||||
_sysctl_func [8]byte
|
||||
_sysctl_parent [8]byte
|
||||
_sysctl_desc [8]byte
|
||||
}
|
||||
|
||||
func sysctlNodes(mib []int32) ([]sysctlNode, error) {
|
||||
var olen uintptr
|
||||
|
||||
// Get a list of all sysctl nodes below the given MIB by performing
|
||||
// a sysctl for the given MIB with CTL_QUERY appended.
|
||||
mib = append(mib, _CTL_QUERY)
|
||||
qnode := sysctlNode{Flags: _SYSCTL_VERS_1}
|
||||
qp := (*byte)(unsafe.Pointer(&qnode))
|
||||
sz := unsafe.Sizeof(qnode)
|
||||
if err := sysctl(mib, nil, &olen, qp, sz); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now that we know the size, get the actual nodes.
|
||||
nodes := make([]sysctlNode, olen/sz)
|
||||
np := (*byte)(unsafe.Pointer(&nodes[0]))
|
||||
if err := sysctl(mib, np, &olen, qp, sz); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func nametomib(name string) ([]int32, error) {
|
||||
// Split name into components.
|
||||
var parts []string
|
||||
last := 0
|
||||
for i := 0; i < len(name); i++ {
|
||||
if name[i] == '.' {
|
||||
parts = append(parts, name[last:i])
|
||||
last = i + 1
|
||||
}
|
||||
}
|
||||
parts = append(parts, name[last:])
|
||||
|
||||
mib := []int32{}
|
||||
// Discover the nodes and construct the MIB OID.
|
||||
for partno, part := range parts {
|
||||
nodes, err := sysctlNodes(mib)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, node := range nodes {
|
||||
n := make([]byte, 0)
|
||||
for i := range node.Name {
|
||||
if node.Name[i] != 0 {
|
||||
n = append(n, byte(node.Name[i]))
|
||||
}
|
||||
}
|
||||
if string(n) == part {
|
||||
mib = append(mib, int32(node.Num))
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(mib) != partno+1 {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return mib, nil
|
||||
}
|
||||
|
||||
// aarch64SysctlCPUID is struct aarch64_sysctl_cpu_id from NetBSD's <aarch64/armreg.h>
|
||||
type aarch64SysctlCPUID struct {
|
||||
midr uint64 /* Main ID Register */
|
||||
revidr uint64 /* Revision ID Register */
|
||||
mpidr uint64 /* Multiprocessor Affinity Register */
|
||||
aa64dfr0 uint64 /* A64 Debug Feature Register 0 */
|
||||
aa64dfr1 uint64 /* A64 Debug Feature Register 1 */
|
||||
aa64isar0 uint64 /* A64 Instruction Set Attribute Register 0 */
|
||||
aa64isar1 uint64 /* A64 Instruction Set Attribute Register 1 */
|
||||
aa64mmfr0 uint64 /* A64 Memory Model Feature Register 0 */
|
||||
aa64mmfr1 uint64 /* A64 Memory Model Feature Register 1 */
|
||||
aa64mmfr2 uint64 /* A64 Memory Model Feature Register 2 */
|
||||
aa64pfr0 uint64 /* A64 Processor Feature Register 0 */
|
||||
aa64pfr1 uint64 /* A64 Processor Feature Register 1 */
|
||||
aa64zfr0 uint64 /* A64 SVE Feature ID Register 0 */
|
||||
mvfr0 uint32 /* Media and VFP Feature Register 0 */
|
||||
mvfr1 uint32 /* Media and VFP Feature Register 1 */
|
||||
mvfr2 uint32 /* Media and VFP Feature Register 2 */
|
||||
pad uint32
|
||||
clidr uint64 /* Cache Level ID Register */
|
||||
ctr uint64 /* Cache Type Register */
|
||||
}
|
||||
|
||||
func sysctlCPUID(name string) (*aarch64SysctlCPUID, error) {
|
||||
mib, err := nametomib(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := aarch64SysctlCPUID{}
|
||||
n := unsafe.Sizeof(out)
|
||||
_, _, errno := syscall.Syscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
uintptr(len(mib)),
|
||||
uintptr(unsafe.Pointer(&out)),
|
||||
uintptr(unsafe.Pointer(&n)),
|
||||
uintptr(0),
|
||||
uintptr(0))
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func doinit() {
|
||||
cpuid, err := sysctlCPUID("machdep.cpu0.cpu_id")
|
||||
if err != nil {
|
||||
setMinimalFeatures()
|
||||
return
|
||||
}
|
||||
parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0)
|
||||
|
||||
Initialized = true
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !linux,arm64
|
||||
// +build !linux,!netbsd
|
||||
// +build arm64
|
||||
|
||||
package cpu
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !linux
|
||||
// +build mips64 mips64le
|
||||
|
||||
package cpu
|
||||
|
||||
func archInit() {
|
||||
Initialized = true
|
||||
}
|
|
@ -8,10 +8,10 @@ const cacheLineSize = 256
|
|||
|
||||
func initOptions() {
|
||||
options = []option{
|
||||
{Name: "zarch", Feature: &S390X.HasZARCH},
|
||||
{Name: "stfle", Feature: &S390X.HasSTFLE},
|
||||
{Name: "ldisp", Feature: &S390X.HasLDISP},
|
||||
{Name: "eimm", Feature: &S390X.HasEIMM},
|
||||
{Name: "zarch", Feature: &S390X.HasZARCH, Required: true},
|
||||
{Name: "stfle", Feature: &S390X.HasSTFLE, Required: true},
|
||||
{Name: "ldisp", Feature: &S390X.HasLDISP, Required: true},
|
||||
{Name: "eimm", Feature: &S390X.HasEIMM, Required: true},
|
||||
{Name: "dfp", Feature: &S390X.HasDFP},
|
||||
{Name: "etf3eh", Feature: &S390X.HasETF3EH},
|
||||
{Name: "msa", Feature: &S390X.HasMSA},
|
||||
|
@ -28,3 +28,145 @@ func initOptions() {
|
|||
{Name: "vxe", Feature: &S390X.HasVXE},
|
||||
}
|
||||
}
|
||||
|
||||
// bitIsSet reports whether the bit at index is set. The bit index
|
||||
// is in big endian order, so bit index 0 is the leftmost bit.
|
||||
func bitIsSet(bits []uint64, index uint) bool {
|
||||
return bits[index/64]&((1<<63)>>(index%64)) != 0
|
||||
}
|
||||
|
||||
// facility is a bit index for the named facility.
|
||||
type facility uint8
|
||||
|
||||
const (
|
||||
// mandatory facilities
|
||||
zarch facility = 1 // z architecture mode is active
|
||||
stflef facility = 7 // store-facility-list-extended
|
||||
ldisp facility = 18 // long-displacement
|
||||
eimm facility = 21 // extended-immediate
|
||||
|
||||
// miscellaneous facilities
|
||||
dfp facility = 42 // decimal-floating-point
|
||||
etf3eh facility = 30 // extended-translation 3 enhancement
|
||||
|
||||
// cryptography facilities
|
||||
msa facility = 17 // message-security-assist
|
||||
msa3 facility = 76 // message-security-assist extension 3
|
||||
msa4 facility = 77 // message-security-assist extension 4
|
||||
msa5 facility = 57 // message-security-assist extension 5
|
||||
msa8 facility = 146 // message-security-assist extension 8
|
||||
msa9 facility = 155 // message-security-assist extension 9
|
||||
|
||||
// vector facilities
|
||||
vx facility = 129 // vector facility
|
||||
vxe facility = 135 // vector-enhancements 1
|
||||
vxe2 facility = 148 // vector-enhancements 2
|
||||
)
|
||||
|
||||
// facilityList contains the result of an STFLE call.
|
||||
// Bits are numbered in big endian order so the
|
||||
// leftmost bit (the MSB) is at index 0.
|
||||
type facilityList struct {
|
||||
bits [4]uint64
|
||||
}
|
||||
|
||||
// Has reports whether the given facilities are present.
|
||||
func (s *facilityList) Has(fs ...facility) bool {
|
||||
if len(fs) == 0 {
|
||||
panic("no facility bits provided")
|
||||
}
|
||||
for _, f := range fs {
|
||||
if !bitIsSet(s.bits[:], uint(f)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// function is the code for the named cryptographic function.
|
||||
type function uint8
|
||||
|
||||
const (
|
||||
// KM{,A,C,CTR} function codes
|
||||
aes128 function = 18 // AES-128
|
||||
aes192 function = 19 // AES-192
|
||||
aes256 function = 20 // AES-256
|
||||
|
||||
// K{I,L}MD function codes
|
||||
sha1 function = 1 // SHA-1
|
||||
sha256 function = 2 // SHA-256
|
||||
sha512 function = 3 // SHA-512
|
||||
sha3_224 function = 32 // SHA3-224
|
||||
sha3_256 function = 33 // SHA3-256
|
||||
sha3_384 function = 34 // SHA3-384
|
||||
sha3_512 function = 35 // SHA3-512
|
||||
shake128 function = 36 // SHAKE-128
|
||||
shake256 function = 37 // SHAKE-256
|
||||
|
||||
// KLMD function codes
|
||||
ghash function = 65 // GHASH
|
||||
)
|
||||
|
||||
// queryResult contains the result of a Query function
|
||||
// call. Bits are numbered in big endian order so the
|
||||
// leftmost bit (the MSB) is at index 0.
|
||||
type queryResult struct {
|
||||
bits [2]uint64
|
||||
}
|
||||
|
||||
// Has reports whether the given functions are present.
|
||||
func (q *queryResult) Has(fns ...function) bool {
|
||||
if len(fns) == 0 {
|
||||
panic("no function codes provided")
|
||||
}
|
||||
for _, f := range fns {
|
||||
if !bitIsSet(q.bits[:], uint(f)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func doinit() {
|
||||
initS390Xbase()
|
||||
|
||||
// We need implementations of stfle, km and so on
|
||||
// to detect cryptographic features.
|
||||
if !haveAsmFunctions() {
|
||||
return
|
||||
}
|
||||
|
||||
// optional cryptographic functions
|
||||
if S390X.HasMSA {
|
||||
aes := []function{aes128, aes192, aes256}
|
||||
|
||||
// cipher message
|
||||
km, kmc := kmQuery(), kmcQuery()
|
||||
S390X.HasAES = km.Has(aes...)
|
||||
S390X.HasAESCBC = kmc.Has(aes...)
|
||||
if S390X.HasSTFLE {
|
||||
facilities := stfle()
|
||||
if facilities.Has(msa4) {
|
||||
kmctr := kmctrQuery()
|
||||
S390X.HasAESCTR = kmctr.Has(aes...)
|
||||
}
|
||||
if facilities.Has(msa8) {
|
||||
kma := kmaQuery()
|
||||
S390X.HasAESGCM = kma.Has(aes...)
|
||||
}
|
||||
}
|
||||
|
||||
// compute message digest
|
||||
kimd := kimdQuery() // intermediate (no padding)
|
||||
klmd := klmdQuery() // last (padding)
|
||||
S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1)
|
||||
S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256)
|
||||
S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512)
|
||||
S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist
|
||||
sha3 := []function{
|
||||
sha3_224, sha3_256, sha3_384, sha3_512,
|
||||
shake128, shake256,
|
||||
}
|
||||
S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 amd64 amd64p32
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cpu
|
||||
|
||||
func archInit() {
|
||||
doinit()
|
||||
Initialized = true
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cpu
|
||||
|
||||
func initS390Xbase() {
|
||||
// get the facilities list
|
||||
facilities := stfle()
|
||||
|
||||
// mandatory
|
||||
S390X.HasZARCH = facilities.Has(zarch)
|
||||
S390X.HasSTFLE = facilities.Has(stflef)
|
||||
S390X.HasLDISP = facilities.Has(ldisp)
|
||||
S390X.HasEIMM = facilities.Has(eimm)
|
||||
|
||||
// optional
|
||||
S390X.HasETF3EH = facilities.Has(etf3eh)
|
||||
S390X.HasDFP = facilities.Has(dfp)
|
||||
S390X.HasMSA = facilities.Has(msa)
|
||||
S390X.HasVX = facilities.Has(vx)
|
||||
if S390X.HasVX {
|
||||
S390X.HasVXE = facilities.Has(vxe)
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
// (See golang.org/issue/32102)
|
||||
|
||||
// +build aix,ppc64
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
package cpu
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
// +build arm,darwin
|
||||
|
||||
#include "textflag.h"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
// +build arm64,darwin
|
||||
|
||||
#include "textflag.h"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// +build linux
|
||||
// +build arm64
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// +build linux
|
||||
// +build mips64 mips64le
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// +build linux
|
||||
// +build mips mipsle
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build riscv64,!gccgo
|
||||
// +build riscv64,gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// +build s390x
|
||||
// +build linux
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// +build ppc64 s390x mips mips64
|
||||
// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
|
||||
|
||||
package unix
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64
|
||||
// +build 386 amd64 amd64p32 alpha arm arm64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
|
||||
|
||||
package unix
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// +build linux,386 linux,arm linux,mips linux,mipsle
|
||||
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,386 linux,arm linux,mips linux,mipsle
|
||||
|
||||
package unix
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -59,12 +59,14 @@ includes_Darwin='
|
|||
#include <stdint.h>
|
||||
#include <sys/attr.h>
|
||||
#include <sys/clonefile.h>
|
||||
#include <sys/kern_control.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sys_domain.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
|
@ -94,6 +96,7 @@ includes_DragonFly='
|
|||
#include <sys/ioctl.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_clone.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
|
@ -201,6 +204,7 @@ struct ltchars {
|
|||
#include <linux/devlink.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
#include <linux/errqueue.h>
|
||||
#include <linux/ethtool_netlink.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/fanotify.h>
|
||||
#include <linux/filter.h>
|
||||
|
@ -222,6 +226,7 @@ struct ltchars {
|
|||
#include <linux/kexec.h>
|
||||
#include <linux/keyctl.h>
|
||||
#include <linux/loop.h>
|
||||
#include <linux/lwtunnel.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/memfd.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -230,6 +235,7 @@ struct ltchars {
|
|||
#include <linux/net_namespace.h>
|
||||
#include <linux/nsfs.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/pps.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/reboot.h>
|
||||
|
@ -372,6 +378,7 @@ includes_SunOS='
|
|||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/stream.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -496,6 +503,7 @@ ccflags="$@"
|
|||
$2 !~ "NLA_TYPE_MASK" &&
|
||||
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
|
||||
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
|
||||
$2 ~ /^FIORDCHK$/ ||
|
||||
$2 ~ /^SIOC/ ||
|
||||
$2 ~ /^TIOC/ ||
|
||||
$2 ~ /^TCGET/ ||
|
||||
|
@ -516,6 +524,7 @@ ccflags="$@"
|
|||
$2 ~ /^CAP_/ ||
|
||||
$2 ~ /^CP_/ ||
|
||||
$2 ~ /^CPUSTATES$/ ||
|
||||
$2 ~ /^CTLIOCGINFO$/ ||
|
||||
$2 ~ /^ALG_/ ||
|
||||
$2 ~ /^FI(CLONE|DEDUPERANGE)/ ||
|
||||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
|
||||
|
@ -527,7 +536,7 @@ ccflags="$@"
|
|||
$2 ~ /^RND/ ||
|
||||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
||||
$2 ~ /^KEYCTL_/ ||
|
||||
$2 ~ /^PERF_EVENT_IOC_/ ||
|
||||
$2 ~ /^PERF_/ ||
|
||||
$2 ~ /^SECCOMP_MODE_/ ||
|
||||
$2 ~ /^SPLICE_/ ||
|
||||
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
||||
|
@ -546,14 +555,17 @@ ccflags="$@"
|
|||
$2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ ||
|
||||
$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
|
||||
$2 ~ /^FSOPT_/ ||
|
||||
$2 ~ /^WDIOC_/ ||
|
||||
$2 ~ /^WDIO[CFS]_/ ||
|
||||
$2 ~ /^NFN/ ||
|
||||
$2 ~ /^XDP_/ ||
|
||||
$2 ~ /^RWF_/ ||
|
||||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
||||
$2 ~ /^CRYPTO_/ ||
|
||||
$2 ~ /^TIPC_/ ||
|
||||
$2 !~ "DEVLINK_RELOAD_LIMITS_VALID_MASK" &&
|
||||
$2 ~ /^DEVLINK_/ ||
|
||||
$2 ~ /^ETHTOOL_/ ||
|
||||
$2 ~ /^LWTUNNEL_IP/ ||
|
||||
$2 !~ "WMESGLEN" &&
|
||||
$2 ~ /^W[A-Z0-9]+$/ ||
|
||||
$2 ~/^PPPIOC/ ||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin,!ios
|
||||
|
||||
package unix
|
||||
|
||||
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||
return ptrace1(request, pid, addr, data)
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ios
|
||||
|
||||
package unix
|
||||
|
||||
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
||||
return ENOTSUP
|
||||
}
|
|
@ -24,7 +24,13 @@
|
|||
// holds a value of type syscall.Errno.
|
||||
package unix // import "golang.org/x/sys/unix"
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
)
|
||||
|
||||
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||
// containing the text of s. If s contains a NUL byte at any
|
||||
|
@ -49,5 +55,40 @@ func BytePtrFromString(s string) (*byte, error) {
|
|||
return &a[0], nil
|
||||
}
|
||||
|
||||
// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any
|
||||
// bytes after the NUL removed.
|
||||
func ByteSliceToString(s []byte) string {
|
||||
if i := bytes.IndexByte(s, 0); i != -1 {
|
||||
s = s[:i]
|
||||
}
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string.
|
||||
// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated
|
||||
// at a zero byte; if the zero byte is not present, the program may crash.
|
||||
func BytePtrToString(p *byte) string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
if *p == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Find NUL terminator.
|
||||
n := 0
|
||||
for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ {
|
||||
ptr = unsafe.Pointer(uintptr(ptr) + 1)
|
||||
}
|
||||
|
||||
var s []byte
|
||||
h := (*unsafeheader.Slice)(unsafe.Pointer(&s))
|
||||
h.Data = unsafe.Pointer(p)
|
||||
h.Len = n
|
||||
h.Cap = n
|
||||
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||
var _zero uintptr
|
||||
|
|
|
@ -19,6 +19,22 @@ import "unsafe"
|
|||
* Wrapped
|
||||
*/
|
||||
|
||||
func Access(path string, mode uint32) (err error) {
|
||||
return Faccessat(AT_FDCWD, path, mode, 0)
|
||||
}
|
||||
|
||||
func Chmod(path string, mode uint32) (err error) {
|
||||
return Fchmodat(AT_FDCWD, path, mode, 0)
|
||||
}
|
||||
|
||||
func Chown(path string, uid int, gid int) (err error) {
|
||||
return Fchownat(AT_FDCWD, path, uid, gid, 0)
|
||||
}
|
||||
|
||||
func Creat(path string, mode uint32) (fd int, err error) {
|
||||
return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
|
||||
}
|
||||
|
||||
//sys utimes(path string, times *[2]Timeval) (err error)
|
||||
func Utimes(path string, tv []Timeval) error {
|
||||
if len(tv) != 2 {
|
||||
|
|
|
@ -277,7 +277,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|||
}
|
||||
return sa, nil
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
return anyToSockaddrGOOS(fd, rsa)
|
||||
}
|
||||
|
||||
func Accept(fd int) (nfd int, sa Sockaddr, err error) {
|
||||
|
|
|
@ -26,7 +26,6 @@ func fdopendir(fd int) (dir uintptr, err error) {
|
|||
|
||||
func libc_fdopendir_trampoline()
|
||||
|
||||
//go:linkname libc_fdopendir libc_fdopendir
|
||||
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package unix
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -30,10 +31,40 @@ type SockaddrDatalink struct {
|
|||
raw RawSockaddrDatalink
|
||||
}
|
||||
|
||||
// SockaddrCtl implements the Sockaddr interface for AF_SYSTEM type sockets.
|
||||
type SockaddrCtl struct {
|
||||
ID uint32
|
||||
Unit uint32
|
||||
raw RawSockaddrCtl
|
||||
}
|
||||
|
||||
func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Sc_len = SizeofSockaddrCtl
|
||||
sa.raw.Sc_family = AF_SYSTEM
|
||||
sa.raw.Ss_sysaddr = AF_SYS_CONTROL
|
||||
sa.raw.Sc_id = sa.ID
|
||||
sa.raw.Sc_unit = sa.Unit
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil
|
||||
}
|
||||
|
||||
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
switch rsa.Addr.Family {
|
||||
case AF_SYSTEM:
|
||||
pp := (*RawSockaddrCtl)(unsafe.Pointer(rsa))
|
||||
if pp.Ss_sysaddr == AF_SYS_CONTROL {
|
||||
sa := new(SockaddrCtl)
|
||||
sa.ID = pp.Sc_id
|
||||
sa.Unit = pp.Sc_unit
|
||||
return sa, nil
|
||||
}
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
}
|
||||
|
||||
// Some external packages rely on SYS___SYSCTL being defined to implement their
|
||||
// own sysctl wrappers. Provide it here, even though direct syscalls are no
|
||||
// longer supported on darwin.
|
||||
const SYS___SYSCTL = 202
|
||||
const SYS___SYSCTL = SYS_SYSCTL
|
||||
|
||||
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
|
||||
func nametomib(name string) (mib []_C_int, err error) {
|
||||
|
@ -88,13 +119,16 @@ type attrList struct {
|
|||
Forkattr uint32
|
||||
}
|
||||
|
||||
//sysnb pipe() (r int, w int, err error)
|
||||
//sysnb pipe(p *[2]int32) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
p[0], p[1], err = pipe()
|
||||
var x [2]int32
|
||||
err = pipe(&x)
|
||||
p[0] = int(x[0])
|
||||
p[1] = int(x[1])
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -257,6 +291,35 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
|
|||
|
||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||
|
||||
func IoctlCtlInfo(fd int, ctlInfo *CtlInfo) error {
|
||||
err := ioctl(fd, CTLIOCGINFO, uintptr(unsafe.Pointer(ctlInfo)))
|
||||
runtime.KeepAlive(ctlInfo)
|
||||
return err
|
||||
}
|
||||
|
||||
// IfreqMTU is struct ifreq used to get or set a network device's MTU.
|
||||
type IfreqMTU struct {
|
||||
Name [IFNAMSIZ]byte
|
||||
MTU int32
|
||||
}
|
||||
|
||||
// IoctlGetIfreqMTU performs the SIOCGIFMTU ioctl operation on fd to get the MTU
|
||||
// of the network device specified by ifname.
|
||||
func IoctlGetIfreqMTU(fd int, ifname string) (*IfreqMTU, error) {
|
||||
var ifreq IfreqMTU
|
||||
copy(ifreq.Name[:], ifname)
|
||||
err := ioctl(fd, SIOCGIFMTU, uintptr(unsafe.Pointer(&ifreq)))
|
||||
return &ifreq, err
|
||||
}
|
||||
|
||||
// IoctlSetIfreqMTU performs the SIOCSIFMTU ioctl operation on fd to set the MTU
|
||||
// of the network device specified by ifreq.Name.
|
||||
func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error {
|
||||
err := ioctl(fd, SIOCSIFMTU, uintptr(unsafe.Pointer(ifreq)))
|
||||
runtime.KeepAlive(ifreq)
|
||||
return err
|
||||
}
|
||||
|
||||
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL
|
||||
|
||||
func Uname(uname *Utsname) error {
|
||||
|
|
|
@ -6,11 +6,7 @@
|
|||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||
import "syscall"
|
||||
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
||||
|
@ -49,5 +45,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
|||
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
|
||||
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
|
||||
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
||||
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
|
||||
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
||||
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
|
||||
|
|
|
@ -6,11 +6,7 @@
|
|||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||
import "syscall"
|
||||
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: sec, Nsec: nsec}
|
||||
|
@ -49,5 +45,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
|||
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
|
||||
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
|
||||
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
||||
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
|
||||
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
||||
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
import "syscall"
|
||||
|
||||
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||
func ptrace1(request int, pid int, addr uintptr, data uintptr) error {
|
||||
return ENOTSUP
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||
return ENOTSUP
|
||||
}
|
||||
import "syscall"
|
||||
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: sec, Nsec: nsec}
|
||||
|
@ -51,5 +45,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
|||
//sys Fstatfs(fd int, stat *Statfs_t) (err error)
|
||||
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT
|
||||
//sys Lstat(path string, stat *Stat_t) (err error)
|
||||
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
|
||||
//sys Stat(path string, stat *Stat_t) (err error)
|
||||
//sys Statfs(path string, stat *Statfs_t) (err error)
|
||||
|
|
|
@ -47,6 +47,10 @@ type SockaddrDatalink struct {
|
|||
raw RawSockaddrDatalink
|
||||
}
|
||||
|
||||
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
return nil, EAFNOSUPPORT
|
||||
}
|
||||
|
||||
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
|
||||
func nametomib(name string) (mib []_C_int, err error) {
|
||||
const siz = unsafe.Sizeof(mib[0])
|
||||
|
@ -101,6 +105,19 @@ func Pipe(p []int) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) error {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err := pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return err
|
||||
}
|
||||
|
||||
//sys extpread(fd int, p []byte, flags int, offset int64) (n int, err error)
|
||||
func Pread(fd int, p []byte, offset int64) (n int, err error) {
|
||||
return extpread(fd, p, 0, offset)
|
||||
|
|
|
@ -54,6 +54,10 @@ type SockaddrDatalink struct {
|
|||
raw RawSockaddrDatalink
|
||||
}
|
||||
|
||||
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
return nil, EAFNOSUPPORT
|
||||
}
|
||||
|
||||
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
|
||||
func nametomib(name string) (mib []_C_int, err error) {
|
||||
const siz = unsafe.Sizeof(mib[0])
|
||||
|
|
|
@ -75,16 +75,3 @@ func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) error {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err := pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -106,15 +106,24 @@ func IoctlGetRTCTime(fd int) (*RTCTime, error) {
|
|||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlGetWatchdogInfo fetches information about a watchdog device from the
|
||||
// Linux watchdog API. For more information, see:
|
||||
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
|
||||
func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
|
||||
var value WatchdogInfo
|
||||
err := ioctl(fd, WDIOC_GETSUPPORT, uintptr(unsafe.Pointer(&value)))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
|
||||
var value RTCWkAlrm
|
||||
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value)))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlFileClone performs an FICLONERANGE ioctl operation to clone the range of
|
||||
// data conveyed in value to the file associated with the file descriptor
|
||||
// destFd. See the ioctl_ficlonerange(2) man page for details.
|
||||
// IoctlFileCloneRange performs an FICLONERANGE ioctl operation to clone the
|
||||
// range of data conveyed in value to the file associated with the file
|
||||
// descriptor destFd. See the ioctl_ficlonerange(2) man page for details.
|
||||
func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
|
||||
err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value)))
|
||||
runtime.KeepAlive(value)
|
||||
|
@ -128,15 +137,22 @@ func IoctlFileClone(destFd, srcFd int) error {
|
|||
return ioctl(destFd, FICLONE, uintptr(srcFd))
|
||||
}
|
||||
|
||||
// IoctlFileClone performs an FIDEDUPERANGE ioctl operation to share the range of
|
||||
// data conveyed in value with the file associated with the file descriptor
|
||||
// destFd. See the ioctl_fideduperange(2) man page for details.
|
||||
// IoctlFileDedupeRange performs an FIDEDUPERANGE ioctl operation to share the
|
||||
// range of data conveyed in value with the file associated with the file
|
||||
// descriptor destFd. See the ioctl_fideduperange(2) man page for details.
|
||||
func IoctlFileDedupeRange(destFd int, value *FileDedupeRange) error {
|
||||
err := ioctl(destFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(value)))
|
||||
runtime.KeepAlive(value)
|
||||
return err
|
||||
}
|
||||
|
||||
// IoctlWatchdogKeepalive issues a keepalive ioctl to a watchdog device. For
|
||||
// more information, see:
|
||||
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
|
||||
func IoctlWatchdogKeepalive(fd int) error {
|
||||
return ioctl(fd, WDIOC_KEEPALIVE, 0)
|
||||
}
|
||||
|
||||
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
|
||||
|
||||
func Link(oldpath string, newpath string) (err error) {
|
||||
|
@ -625,6 +641,36 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
|||
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
|
||||
}
|
||||
|
||||
// SockaddrCANJ1939 implements the Sockaddr interface for AF_CAN using J1939
|
||||
// protocol (https://en.wikipedia.org/wiki/SAE_J1939). For more information
|
||||
// on the purposes of the fields, check the official linux kernel documentation
|
||||
// available here: https://www.kernel.org/doc/Documentation/networking/j1939.rst
|
||||
type SockaddrCANJ1939 struct {
|
||||
Ifindex int
|
||||
Name uint64
|
||||
PGN uint32
|
||||
Addr uint8
|
||||
raw RawSockaddrCAN
|
||||
}
|
||||
|
||||
func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
|
||||
return nil, 0, EINVAL
|
||||
}
|
||||
sa.raw.Family = AF_CAN
|
||||
sa.raw.Ifindex = int32(sa.Ifindex)
|
||||
n := (*[8]byte)(unsafe.Pointer(&sa.Name))
|
||||
for i := 0; i < 8; i++ {
|
||||
sa.raw.Addr[i] = n[i]
|
||||
}
|
||||
p := (*[4]byte)(unsafe.Pointer(&sa.PGN))
|
||||
for i := 0; i < 4; i++ {
|
||||
sa.raw.Addr[i+8] = p[i]
|
||||
}
|
||||
sa.raw.Addr[12] = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
|
||||
}
|
||||
|
||||
// SockaddrALG implements the Sockaddr interface for AF_ALG type sockets.
|
||||
// SockaddrALG enables userspace access to the Linux kernel's cryptography
|
||||
// subsystem. The Type and Name fields specify which type of hash or cipher
|
||||
|
@ -936,6 +982,10 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
|||
return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil
|
||||
}
|
||||
|
||||
var socketProtocol = func(fd int) (int, error) {
|
||||
return GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
|
||||
}
|
||||
|
||||
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
switch rsa.Addr.Family {
|
||||
case AF_NETLINK:
|
||||
|
@ -986,7 +1036,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|||
return sa, nil
|
||||
|
||||
case AF_INET:
|
||||
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
|
||||
proto, err := socketProtocol(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1012,7 +1062,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|||
}
|
||||
|
||||
case AF_INET6:
|
||||
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
|
||||
proto, err := socketProtocol(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1047,7 +1097,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|||
}
|
||||
return sa, nil
|
||||
case AF_BLUETOOTH:
|
||||
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
|
||||
proto, err := socketProtocol(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1134,20 +1184,43 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|||
return sa, nil
|
||||
|
||||
case AF_CAN:
|
||||
pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
|
||||
sa := &SockaddrCAN{
|
||||
Ifindex: int(pp.Ifindex),
|
||||
proto, err := socketProtocol(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
rx[i] = pp.Addr[i]
|
||||
}
|
||||
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
tx[i] = pp.Addr[i+4]
|
||||
}
|
||||
return sa, nil
|
||||
|
||||
pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
|
||||
|
||||
switch proto {
|
||||
case CAN_J1939:
|
||||
sa := &SockaddrCANJ1939{
|
||||
Ifindex: int(pp.Ifindex),
|
||||
}
|
||||
name := (*[8]byte)(unsafe.Pointer(&sa.Name))
|
||||
for i := 0; i < 8; i++ {
|
||||
name[i] = pp.Addr[i]
|
||||
}
|
||||
pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN))
|
||||
for i := 0; i < 4; i++ {
|
||||
pgn[i] = pp.Addr[i+8]
|
||||
}
|
||||
addr := (*[1]byte)(unsafe.Pointer(&sa.Addr))
|
||||
addr[0] = pp.Addr[12]
|
||||
return sa, nil
|
||||
default:
|
||||
sa := &SockaddrCAN{
|
||||
Ifindex: int(pp.Ifindex),
|
||||
}
|
||||
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
rx[i] = pp.Addr[i]
|
||||
}
|
||||
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
tx[i] = pp.Addr[i+4]
|
||||
}
|
||||
return sa, nil
|
||||
}
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
}
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
|
||||
// so that go vet can check that they are correct.
|
||||
|
||||
// +build 386,linux
|
||||
|
||||
package unix
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,linux
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
package unix
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,!gccgo
|
||||
// +build linux,gc
|
||||
|
||||
package unix
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,!gccgo,386
|
||||
// +build linux,gc,386
|
||||
|
||||
package unix
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue