chore: upgrade to gopsutil/v3 (#9118)
* deps: update golang.org/x/sys * deps: update imports to gopsutil/v3 * chore: make update-vendor
This commit is contained in:
parent
2be2be577c
commit
9ccb340893
|
@ -3,10 +3,10 @@ package debug
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
)
|
||||
|
||||
// newNodeIDFromConfig will pull the persisted node ID, if any, or create a random one
|
||||
|
|
8
go.mod
8
go.mod
|
@ -11,7 +11,6 @@ replace launchpad.net/gocheck => github.com/go-check/check v0.0.0-20140225173054
|
|||
require (
|
||||
github.com/Microsoft/go-winio v0.4.3 // indirect
|
||||
github.com/NYTimes/gziphandler v1.0.1
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e
|
||||
github.com/armon/go-metrics v0.3.5-0.20201104215618-6fd5a4ddf425
|
||||
github.com/armon/go-radix v1.0.0
|
||||
|
@ -23,7 +22,6 @@ require (
|
|||
github.com/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0
|
||||
github.com/envoyproxy/go-control-plane v0.9.5
|
||||
github.com/frankban/quicktest v1.11.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.1 // indirect
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d
|
||||
github.com/golang/protobuf v1.3.5
|
||||
github.com/google/go-cmp v0.5.2
|
||||
|
@ -78,15 +76,15 @@ require (
|
|||
github.com/prometheus/client_golang v1.4.0
|
||||
github.com/rboyer/safeio v0.2.1
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible
|
||||
github.com/stretchr/testify v1.5.1
|
||||
github.com/shirou/gopsutil/v3 v3.20.10
|
||||
github.com/stretchr/testify v1.6.1
|
||||
go.opencensus.io v0.22.0 // indirect
|
||||
go.uber.org/goleak v1.0.0
|
||||
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae
|
||||
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||
golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf
|
||||
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
||||
golang.org/x/tools v0.0.0-20200513154647-78b527d18275 // indirect
|
||||
|
|
22
go.sum
22
go.sum
|
@ -45,8 +45,8 @@ github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64
|
|||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=
|
||||
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
|
@ -149,8 +149,8 @@ github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa
|
|||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
|
@ -469,8 +469,8 @@ github.com/sean-/conswriter v0.0.0-20180208195008-f5ae3917a627/go.mod h1:7zjs06q
|
|||
github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6qbIiqJ6/Bqeq25bCLbL7YFmpaFfJDuM=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
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 v3.20.10 h1:7zomV9HJv6UGk225YtvEa5+camNLpbua3MAz/GqiVJY=
|
||||
github.com/shirou/gopsutil/v3 v3.20.10/go.mod h1:igHnfak0qnw1biGeI2qKQvu0ZkwvEkUcCLlYhZzdr/4=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
|
@ -499,8 +499,8 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci
|
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible h1:8uRvJleFpqLsO77WaAh2UrasMOzd8MxXrNj20e7El+Q=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
|
||||
github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8=
|
||||
|
@ -613,8 +613,8 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf h1:AvBTl0xbF/KtHyvm61X4gSPF7/dKJ/xQqJwKr1Qu9no=
|
||||
golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 h1:iCaAy5bMeEvwANu3YnJfWwI0kWAGkEa2RXPdweI/ysk=
|
||||
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -691,6 +691,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -77,7 +77,7 @@ func (s *SWbemServices) process(initError chan error) {
|
|||
//fmt.Println("process: starting background thread initialization")
|
||||
//All OLE/WMI calls must happen on the same initialized thead, so lock this goroutine
|
||||
runtime.LockOSThread()
|
||||
defer runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED)
|
||||
if err != nil {
|
||||
|
|
|
@ -285,6 +285,10 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat
|
|||
}
|
||||
defer prop.Clear()
|
||||
|
||||
if prop.VT == 0x1 { //VT_NULL
|
||||
continue
|
||||
}
|
||||
|
||||
switch val := prop.Value().(type) {
|
||||
case int8, int16, int32, int64, int:
|
||||
v := reflect.ValueOf(val).Int()
|
||||
|
@ -383,7 +387,7 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat
|
|||
}
|
||||
f.Set(fArr)
|
||||
}
|
||||
case reflect.Uint8:
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
safeArray := prop.ToArray()
|
||||
if safeArray != nil {
|
||||
arr := safeArray.ToValueArray()
|
||||
|
@ -394,6 +398,17 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat
|
|||
}
|
||||
f.Set(fArr)
|
||||
}
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
safeArray := prop.ToArray()
|
||||
if safeArray != nil {
|
||||
arr := safeArray.ToValueArray()
|
||||
fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr))
|
||||
for i, v := range arr {
|
||||
s := fArr.Index(i)
|
||||
s.SetInt(reflect.ValueOf(v).Int())
|
||||
}
|
||||
f.Set(fArr)
|
||||
}
|
||||
default:
|
||||
return &ErrFieldMismatch{
|
||||
StructType: of.Type(),
|
||||
|
|
|
@ -2,8 +2,7 @@ language: go
|
|||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- tip
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#Go OLE
|
||||
# Go OLE
|
||||
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/qr0u2sf7q43us9fj?svg=true)](https://ci.appveyor.com/project/jacobsantos/go-ole-jgs28)
|
||||
[![Build Status](https://travis-ci.org/go-ole/go-ole.svg?branch=master)](https://travis-ci.org/go-ole/go-ole)
|
||||
|
@ -35,12 +35,12 @@ AppVeyor is used to build on Windows using the (in-development) test COM server.
|
|||
|
||||
The tests currently do run and do pass and this should be maintained with commits.
|
||||
|
||||
##Versioning
|
||||
## Versioning
|
||||
|
||||
Go OLE uses [semantic versioning](http://semver.org) for version numbers, which is similar to the version contract of the Go language. Which means that the major version will always maintain backwards compatibility with minor versions. Minor versions will only add new additions and changes. Fixes will always be in patch.
|
||||
|
||||
This contract should allow you to upgrade to new minor and patch versions without breakage or modifications to your existing code. Leave a ticket, if there is breakage, so that it could be fixed.
|
||||
|
||||
##LICENSE
|
||||
## LICENSE
|
||||
|
||||
Under the MIT License: http://mattn.mit-license.org/2013
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
package ole
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"time"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -21,6 +19,7 @@ var (
|
|||
procStringFromCLSID, _ = modole32.FindProc("StringFromCLSID")
|
||||
procStringFromIID, _ = modole32.FindProc("StringFromIID")
|
||||
procIIDFromString, _ = modole32.FindProc("IIDFromString")
|
||||
procCoGetObject, _ = modole32.FindProc("CoGetObject")
|
||||
procGetUserDefaultLCID, _ = modkernel32.FindProc("GetUserDefaultLCID")
|
||||
procCopyMemory, _ = modkernel32.FindProc("RtlMoveMemory")
|
||||
procVariantInit, _ = modoleaut32.FindProc("VariantInit")
|
||||
|
@ -209,6 +208,32 @@ func GetActiveObject(clsid *GUID, iid *GUID) (unk *IUnknown, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
type BindOpts struct {
|
||||
CbStruct uint32
|
||||
GrfFlags uint32
|
||||
GrfMode uint32
|
||||
TickCountDeadline uint32
|
||||
}
|
||||
|
||||
// GetObject retrieves pointer to active object.
|
||||
func GetObject(programID string, bindOpts *BindOpts, iid *GUID) (unk *IUnknown, err error) {
|
||||
if bindOpts != nil {
|
||||
bindOpts.CbStruct = uint32(unsafe.Sizeof(BindOpts{}))
|
||||
}
|
||||
if iid == nil {
|
||||
iid = IID_IUnknown
|
||||
}
|
||||
hr, _, _ := procCoGetObject.Call(
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(programID))),
|
||||
uintptr(unsafe.Pointer(bindOpts)),
|
||||
uintptr(unsafe.Pointer(iid)),
|
||||
uintptr(unsafe.Pointer(&unk)))
|
||||
if hr != 0 {
|
||||
err = NewError(hr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// VariantInit initializes variant.
|
||||
func VariantInit(v *VARIANT) (err error) {
|
||||
hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))
|
||||
|
@ -317,13 +342,3 @@ func DispatchMessage(msg *Msg) (ret int32) {
|
|||
ret = int32(r0)
|
||||
return
|
||||
}
|
||||
|
||||
// GetVariantDate converts COM Variant Time value to Go time.Time.
|
||||
func GetVariantDate(value float64) (time.Time, error) {
|
||||
var st syscall.Systemtime
|
||||
r, _, _ := procVariantTimeToSystemTime.Call(uintptr(value), uintptr(unsafe.Pointer(&st)))
|
||||
if r != 0 {
|
||||
return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil
|
||||
}
|
||||
return time.Now(), errors.New("Could not convert to time, passing current time.")
|
||||
}
|
||||
|
|
|
@ -169,6 +169,6 @@ func DispatchMessage(msg *Msg) int32 {
|
|||
return int32(0)
|
||||
}
|
||||
|
||||
func GetVariantDate(value float64) (time.Time, error) {
|
||||
func GetVariantDate(value uint64) (time.Time, error) {
|
||||
return time.Now(), NewError(E_NOTIMPL)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
module github.com/go-ole/go-ole
|
||||
|
||||
go 1.12
|
|
@ -3,6 +3,7 @@
|
|||
package ole
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
@ -132,6 +133,8 @@ func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}
|
|||
vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv)))
|
||||
case *float64:
|
||||
vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64)))))
|
||||
case *big.Int:
|
||||
vargs[n] = NewVariant(VT_DECIMAL, v.(*big.Int).Int64())
|
||||
case string:
|
||||
vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string))))))
|
||||
case *string:
|
||||
|
|
|
@ -124,12 +124,12 @@ func safeArrayGetElementSize(safearray *SafeArray) (*uint32, error) {
|
|||
}
|
||||
|
||||
// safeArrayGetElement retrieves element at given index.
|
||||
func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error {
|
||||
func safeArrayGetElement(safearray *SafeArray, index int32, pv unsafe.Pointer) error {
|
||||
return NewError(E_NOTIMPL)
|
||||
}
|
||||
|
||||
// safeArrayGetElement retrieves element at given index and converts to string.
|
||||
func safeArrayGetElementString(safearray *SafeArray, index int64) (string, error) {
|
||||
func safeArrayGetElementString(safearray *SafeArray, index int32) (string, error) {
|
||||
return "", NewError(E_NOTIMPL)
|
||||
}
|
||||
|
||||
|
@ -146,8 +146,8 @@ func safeArrayGetIID(safearray *SafeArray) (*GUID, error) {
|
|||
// multidimensional array.
|
||||
//
|
||||
// AKA: SafeArrayGetLBound in Windows API.
|
||||
func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int64, error) {
|
||||
return int64(0), NewError(E_NOTIMPL)
|
||||
func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int32, error) {
|
||||
return int32(0), NewError(E_NOTIMPL)
|
||||
}
|
||||
|
||||
// safeArrayGetUBound returns upper bounds of SafeArray.
|
||||
|
@ -156,8 +156,8 @@ func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int64, error) {
|
|||
// multidimensional array.
|
||||
//
|
||||
// AKA: SafeArrayGetUBound in Windows API.
|
||||
func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (int64, error) {
|
||||
return int64(0), NewError(E_NOTIMPL)
|
||||
func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (int32, error) {
|
||||
return int32(0), NewError(E_NOTIMPL)
|
||||
}
|
||||
|
||||
// safeArrayGetVartype returns data type of SafeArray.
|
||||
|
|
|
@ -205,7 +205,7 @@ func safeArrayGetElementSize(safearray *SafeArray) (length *uint32, err error) {
|
|||
}
|
||||
|
||||
// safeArrayGetElement retrieves element at given index.
|
||||
func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error {
|
||||
func safeArrayGetElement(safearray *SafeArray, index int32, pv unsafe.Pointer) error {
|
||||
return convertHresultToError(
|
||||
procSafeArrayGetElement.Call(
|
||||
uintptr(unsafe.Pointer(safearray)),
|
||||
|
@ -214,7 +214,7 @@ func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) e
|
|||
}
|
||||
|
||||
// safeArrayGetElementString retrieves element at given index and converts to string.
|
||||
func safeArrayGetElementString(safearray *SafeArray, index int64) (str string, err error) {
|
||||
func safeArrayGetElementString(safearray *SafeArray, index int32) (str string, err error) {
|
||||
var element *int16
|
||||
err = convertHresultToError(
|
||||
procSafeArrayGetElement.Call(
|
||||
|
@ -243,7 +243,7 @@ func safeArrayGetIID(safearray *SafeArray) (guid *GUID, err error) {
|
|||
// multidimensional array.
|
||||
//
|
||||
// AKA: SafeArrayGetLBound in Windows API.
|
||||
func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int64, err error) {
|
||||
func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int32, err error) {
|
||||
err = convertHresultToError(
|
||||
procSafeArrayGetLBound.Call(
|
||||
uintptr(unsafe.Pointer(safearray)),
|
||||
|
@ -258,7 +258,7 @@ func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int6
|
|||
// multidimensional array.
|
||||
//
|
||||
// AKA: SafeArrayGetUBound in Windows API.
|
||||
func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int64, err error) {
|
||||
func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int32, err error) {
|
||||
err = convertHresultToError(
|
||||
procSafeArrayGetUBound.Call(
|
||||
uintptr(unsafe.Pointer(safearray)),
|
||||
|
|
|
@ -14,7 +14,7 @@ func (sac *SafeArrayConversion) ToStringArray() (strings []string) {
|
|||
totalElements, _ := sac.TotalElements(0)
|
||||
strings = make([]string, totalElements)
|
||||
|
||||
for i := int64(0); i < totalElements; i++ {
|
||||
for i := int32(0); i < totalElements; i++ {
|
||||
strings[int32(i)], _ = safeArrayGetElementString(sac.Array, i)
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ func (sac *SafeArrayConversion) ToByteArray() (bytes []byte) {
|
|||
totalElements, _ := sac.TotalElements(0)
|
||||
bytes = make([]byte, totalElements)
|
||||
|
||||
for i := int64(0); i < totalElements; i++ {
|
||||
for i := int32(0); i < totalElements; i++ {
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&bytes[int32(i)]))
|
||||
}
|
||||
|
||||
|
@ -37,59 +37,59 @@ func (sac *SafeArrayConversion) ToValueArray() (values []interface{}) {
|
|||
values = make([]interface{}, totalElements)
|
||||
vt, _ := safeArrayGetVartype(sac.Array)
|
||||
|
||||
for i := 0; i < int(totalElements); i++ {
|
||||
for i := int32(0); i < totalElements; i++ {
|
||||
switch VT(vt) {
|
||||
case VT_BOOL:
|
||||
var v bool
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_I1:
|
||||
var v int8
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_I2:
|
||||
var v int16
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_I4:
|
||||
var v int32
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_I8:
|
||||
var v int64
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_UI1:
|
||||
var v uint8
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_UI2:
|
||||
var v uint16
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_UI4:
|
||||
var v uint32
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_UI8:
|
||||
var v uint64
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_R4:
|
||||
var v float32
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_R8:
|
||||
var v float64
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_BSTR:
|
||||
var v string
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v
|
||||
case VT_VARIANT:
|
||||
var v VARIANT
|
||||
safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
|
||||
safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v))
|
||||
values[i] = v.Value()
|
||||
default:
|
||||
// TODO
|
||||
|
@ -111,14 +111,14 @@ func (sac *SafeArrayConversion) GetSize() (length *uint32, err error) {
|
|||
return safeArrayGetElementSize(sac.Array)
|
||||
}
|
||||
|
||||
func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int64, err error) {
|
||||
func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int32, err error) {
|
||||
if index < 1 {
|
||||
index = 1
|
||||
}
|
||||
|
||||
// Get array bounds
|
||||
var LowerBounds int64
|
||||
var UpperBounds int64
|
||||
var LowerBounds int32
|
||||
var UpperBounds int32
|
||||
|
||||
LowerBounds, err = safeArrayGetLBound(sac.Array, index)
|
||||
if err != nil {
|
||||
|
|
|
@ -88,10 +88,10 @@ func (v *VARIANT) Value() interface{} {
|
|||
return v.ToString()
|
||||
case VT_DATE:
|
||||
// VT_DATE type will either return float64 or time.Time.
|
||||
d := float64(v.Val)
|
||||
d := uint64(v.Val)
|
||||
date, err := GetVariantDate(d)
|
||||
if err != nil {
|
||||
return d
|
||||
return float64(v.Val)
|
||||
}
|
||||
return date
|
||||
case VT_UNKNOWN:
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// +build windows,386
|
||||
|
||||
package ole
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// GetVariantDate converts COM Variant Time value to Go time.Time.
|
||||
func GetVariantDate(value uint64) (time.Time, error) {
|
||||
var st syscall.Systemtime
|
||||
v1 := uint32(value)
|
||||
v2 := uint32(value >> 32)
|
||||
r, _, _ := procVariantTimeToSystemTime.Call(uintptr(v1), uintptr(v2), uintptr(unsafe.Pointer(&st)))
|
||||
if r != 0 {
|
||||
return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil
|
||||
}
|
||||
return time.Now(), errors.New("Could not convert to time, passing current time.")
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// +build windows,amd64
|
||||
|
||||
package ole
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// GetVariantDate converts COM Variant Time value to Go time.Time.
|
||||
func GetVariantDate(value uint64) (time.Time, error) {
|
||||
var st syscall.Systemtime
|
||||
r, _, _ := procVariantTimeToSystemTime.Call(uintptr(value), uintptr(unsafe.Pointer(&st)))
|
||||
if r != 0 {
|
||||
return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil
|
||||
}
|
||||
return time.Now(), errors.New("Could not convert to time, passing current time.")
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// +build ppc64le
|
||||
|
||||
package ole
|
||||
|
||||
type VARIANT struct {
|
||||
VT VT // 2
|
||||
wReserved1 uint16 // 4
|
||||
wReserved2 uint16 // 6
|
||||
wReserved3 uint16 // 8
|
||||
Val int64 // 16
|
||||
_ [8]byte // 24
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package disk
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
||||
type UsageStat struct {
|
||||
Path string `json:"path"`
|
||||
Fstype string `json:"fstype"`
|
||||
Total uint64 `json:"total"`
|
||||
Free uint64 `json:"free"`
|
||||
Used uint64 `json:"used"`
|
||||
UsedPercent float64 `json:"usedPercent"`
|
||||
InodesTotal uint64 `json:"inodesTotal"`
|
||||
InodesUsed uint64 `json:"inodesUsed"`
|
||||
InodesFree uint64 `json:"inodesFree"`
|
||||
InodesUsedPercent float64 `json:"inodesUsedPercent"`
|
||||
}
|
||||
|
||||
type PartitionStat struct {
|
||||
Device string `json:"device"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
Fstype string `json:"fstype"`
|
||||
Opts string `json:"opts"`
|
||||
}
|
||||
|
||||
type IOCountersStat struct {
|
||||
ReadCount uint64 `json:"readCount"`
|
||||
MergedReadCount uint64 `json:"mergedReadCount"`
|
||||
WriteCount uint64 `json:"writeCount"`
|
||||
MergedWriteCount uint64 `json:"mergedWriteCount"`
|
||||
ReadBytes uint64 `json:"readBytes"`
|
||||
WriteBytes uint64 `json:"writeBytes"`
|
||||
ReadTime uint64 `json:"readTime"`
|
||||
WriteTime uint64 `json:"writeTime"`
|
||||
IopsInProgress uint64 `json:"iopsInProgress"`
|
||||
IoTime uint64 `json:"ioTime"`
|
||||
WeightedIO uint64 `json:"weightedIO"`
|
||||
Name string `json:"name"`
|
||||
SerialNumber string `json:"serialNumber"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
func (d UsageStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (d PartitionStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (d IOCountersStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
|
@ -1,322 +0,0 @@
|
|||
package process
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"runtime"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
var (
|
||||
invoke common.Invoker = common.Invoke{}
|
||||
ErrorNoChildren = errors.New("process does not have children")
|
||||
ErrorProcessNotRunning = errors.New("process does not exist")
|
||||
)
|
||||
|
||||
type Process struct {
|
||||
Pid int32 `json:"pid"`
|
||||
name string
|
||||
status string
|
||||
parent int32
|
||||
numCtxSwitches *NumCtxSwitchesStat
|
||||
uids []int32
|
||||
gids []int32
|
||||
groups []int32
|
||||
numThreads int32
|
||||
memInfo *MemoryInfoStat
|
||||
sigInfo *SignalInfoStat
|
||||
createTime int64
|
||||
|
||||
lastCPUTimes *cpu.TimesStat
|
||||
lastCPUTime time.Time
|
||||
|
||||
tgid int32
|
||||
}
|
||||
|
||||
type OpenFilesStat struct {
|
||||
Path string `json:"path"`
|
||||
Fd uint64 `json:"fd"`
|
||||
}
|
||||
|
||||
type MemoryInfoStat struct {
|
||||
RSS uint64 `json:"rss"` // bytes
|
||||
VMS uint64 `json:"vms"` // bytes
|
||||
HWM uint64 `json:"hwm"` // bytes
|
||||
Data uint64 `json:"data"` // bytes
|
||||
Stack uint64 `json:"stack"` // bytes
|
||||
Locked uint64 `json:"locked"` // bytes
|
||||
Swap uint64 `json:"swap"` // bytes
|
||||
}
|
||||
|
||||
type SignalInfoStat struct {
|
||||
PendingProcess uint64 `json:"pending_process"`
|
||||
PendingThread uint64 `json:"pending_thread"`
|
||||
Blocked uint64 `json:"blocked"`
|
||||
Ignored uint64 `json:"ignored"`
|
||||
Caught uint64 `json:"caught"`
|
||||
}
|
||||
|
||||
type RlimitStat struct {
|
||||
Resource int32 `json:"resource"`
|
||||
Soft int32 `json:"soft"` //TODO too small. needs to be uint64
|
||||
Hard int32 `json:"hard"` //TODO too small. needs to be uint64
|
||||
Used uint64 `json:"used"`
|
||||
}
|
||||
|
||||
type IOCountersStat struct {
|
||||
ReadCount uint64 `json:"readCount"`
|
||||
WriteCount uint64 `json:"writeCount"`
|
||||
ReadBytes uint64 `json:"readBytes"`
|
||||
WriteBytes uint64 `json:"writeBytes"`
|
||||
}
|
||||
|
||||
type NumCtxSwitchesStat struct {
|
||||
Voluntary int64 `json:"voluntary"`
|
||||
Involuntary int64 `json:"involuntary"`
|
||||
}
|
||||
|
||||
type PageFaultsStat struct {
|
||||
MinorFaults uint64 `json:"minorFaults"`
|
||||
MajorFaults uint64 `json:"majorFaults"`
|
||||
ChildMinorFaults uint64 `json:"childMinorFaults"`
|
||||
ChildMajorFaults uint64 `json:"childMajorFaults"`
|
||||
}
|
||||
|
||||
// Resource limit constants are from /usr/include/x86_64-linux-gnu/bits/resource.h
|
||||
// from libc6-dev package in Ubuntu 16.10
|
||||
const (
|
||||
RLIMIT_CPU int32 = 0
|
||||
RLIMIT_FSIZE int32 = 1
|
||||
RLIMIT_DATA int32 = 2
|
||||
RLIMIT_STACK int32 = 3
|
||||
RLIMIT_CORE int32 = 4
|
||||
RLIMIT_RSS int32 = 5
|
||||
RLIMIT_NPROC int32 = 6
|
||||
RLIMIT_NOFILE int32 = 7
|
||||
RLIMIT_MEMLOCK int32 = 8
|
||||
RLIMIT_AS int32 = 9
|
||||
RLIMIT_LOCKS int32 = 10
|
||||
RLIMIT_SIGPENDING int32 = 11
|
||||
RLIMIT_MSGQUEUE int32 = 12
|
||||
RLIMIT_NICE int32 = 13
|
||||
RLIMIT_RTPRIO int32 = 14
|
||||
RLIMIT_RTTIME int32 = 15
|
||||
)
|
||||
|
||||
func (p Process) String() string {
|
||||
s, _ := json.Marshal(p)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (o OpenFilesStat) String() string {
|
||||
s, _ := json.Marshal(o)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (m MemoryInfoStat) String() string {
|
||||
s, _ := json.Marshal(m)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (r RlimitStat) String() string {
|
||||
s, _ := json.Marshal(r)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (i IOCountersStat) String() string {
|
||||
s, _ := json.Marshal(i)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (p NumCtxSwitchesStat) String() string {
|
||||
s, _ := json.Marshal(p)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// Pids returns a slice of process ID list which are running now.
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
pids, err := pidsWithContext(ctx)
|
||||
sort.Slice(pids, func(i, j int) bool { return pids[i] < pids[j] })
|
||||
return pids, err
|
||||
}
|
||||
|
||||
// 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}
|
||||
|
||||
exists, err := PidExists(pid)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
if !exists {
|
||||
return p, ErrorProcessNotRunning
|
||||
}
|
||||
p.CreateTime()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func PidExists(pid int32) (bool, error) {
|
||||
return PidExistsWithContext(context.Background(), pid)
|
||||
}
|
||||
|
||||
// Background returns true if the process is in background, false otherwise.
|
||||
func (p *Process) Background() (bool, error) {
|
||||
return p.BackgroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) BackgroundWithContext(ctx context.Context) (bool, error) {
|
||||
fg, err := p.ForegroundWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !fg, err
|
||||
}
|
||||
|
||||
// If interval is 0, return difference from last call(non-blocking).
|
||||
// If interval > 0, wait interval sec and return diffrence between start and end.
|
||||
func (p *Process) Percent(interval time.Duration) (float64, error) {
|
||||
return p.PercentWithContext(context.Background(), interval)
|
||||
}
|
||||
|
||||
func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration) (float64, error) {
|
||||
cpuTimes, err := p.Times()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
now := time.Now()
|
||||
|
||||
if interval > 0 {
|
||||
p.lastCPUTimes = cpuTimes
|
||||
p.lastCPUTime = now
|
||||
if err := common.Sleep(ctx, interval); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cpuTimes, err = p.Times()
|
||||
now = time.Now()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
if p.lastCPUTimes == nil {
|
||||
// invoked first time
|
||||
p.lastCPUTimes = cpuTimes
|
||||
p.lastCPUTime = now
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
numcpu := runtime.NumCPU()
|
||||
delta := (now.Sub(p.lastCPUTime).Seconds()) * float64(numcpu)
|
||||
ret := calculatePercent(p.lastCPUTimes, cpuTimes, delta, numcpu)
|
||||
p.lastCPUTimes = cpuTimes
|
||||
p.lastCPUTime = now
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// IsRunning returns whether the process is still running or not.
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
createTime, err := p.CreateTimeWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
p2, err := NewProcess(p.Pid)
|
||||
if err == ErrorProcessNotRunning {
|
||||
return false, nil
|
||||
}
|
||||
createTime2, err := p2.CreateTimeWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return createTime == createTime2, nil
|
||||
}
|
||||
|
||||
// CreateTime returns created time of the process in milliseconds since the epoch, in UTC.
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
if p.createTime != 0 {
|
||||
return p.createTime, nil
|
||||
}
|
||||
createTime, err := p.createTimeWithContext(ctx)
|
||||
p.createTime = createTime
|
||||
return p.createTime, err
|
||||
}
|
||||
|
||||
func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 {
|
||||
if delta == 0 {
|
||||
return 0
|
||||
}
|
||||
delta_proc := t2.Total() - t1.Total()
|
||||
overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
|
||||
return overall_percent
|
||||
}
|
||||
|
||||
// MemoryPercent returns how many percent of the total RAM this process uses
|
||||
func (p *Process) MemoryPercent() (float32, error) {
|
||||
return p.MemoryPercentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) MemoryPercentWithContext(ctx context.Context) (float32, error) {
|
||||
machineMemory, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
total := machineMemory.Total
|
||||
|
||||
processMemory, err := p.MemoryInfo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
used := processMemory.RSS
|
||||
|
||||
return (100 * float32(used) / float32(total)), nil
|
||||
}
|
||||
|
||||
// CPU_Percent returns how many percent of the CPU time this process uses
|
||||
func (p *Process) CPUPercent() (float64, error) {
|
||||
return p.CPUPercentWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) {
|
||||
crt_time, err := p.CreateTime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cput, err := p.Times()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
created := time.Unix(0, crt_time*int64(time.Millisecond))
|
||||
totalTime := time.Since(created).Seconds()
|
||||
if totalTime <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return 100 * cput.Total() / totalTime, nil
|
||||
}
|
||||
|
||||
// Groups returns all group IDs(include supplementary groups) of the process as a slice of the int
|
||||
func (p *Process) Groups() ([]int32, error) {
|
||||
return p.GroupsWithContext(context.Background())
|
||||
}
|
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* Apple System Management Control (SMC) Tool
|
||||
* Copyright (C) 2006 devnull
|
||||
* Portions Copyright (C) 2013 Michael Wilber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include "_smc.h"
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
// Cache the keyInfo to lower the energy impact of SMCReadKey() / SMCReadKey2()
|
||||
#define KEY_INFO_CACHE_SIZE 100
|
||||
struct {
|
||||
UInt32 key;
|
||||
SMCKeyData_keyInfo_t keyInfo;
|
||||
} g_keyInfoCache[KEY_INFO_CACHE_SIZE];
|
||||
|
||||
int g_keyInfoCacheCount = 0;
|
||||
OSSpinLock g_keyInfoSpinLock = 0;
|
||||
|
||||
kern_return_t SMCCall2(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure, io_connect_t conn);
|
||||
|
||||
UInt32 _strtoul(char *str, int size, int base)
|
||||
{
|
||||
UInt32 total = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (base == 16)
|
||||
total += str[i] << (size - 1 - i) * 8;
|
||||
else
|
||||
total += ((unsigned char) (str[i]) << (size - 1 - i) * 8);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void _ultostr(char *str, UInt32 val)
|
||||
{
|
||||
str[0] = '\0';
|
||||
sprintf(str, "%c%c%c%c",
|
||||
(unsigned int) val >> 24,
|
||||
(unsigned int) val >> 16,
|
||||
(unsigned int) val >> 8,
|
||||
(unsigned int) val);
|
||||
}
|
||||
|
||||
float _strtof(unsigned char *str, int size, int e)
|
||||
{
|
||||
float total = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (i == (size - 1))
|
||||
total += (str[i] & 0xff) >> e;
|
||||
else
|
||||
total += str[i] << (size - 1 - i) * (8 - e);
|
||||
}
|
||||
|
||||
total += (str[size-1] & 0x03) * 0.25;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
void printFP1F(SMCVal_t val)
|
||||
{
|
||||
printf("%.5f ", ntohs(*(UInt16*)val.bytes) / 32768.0);
|
||||
}
|
||||
|
||||
void printFP4C(SMCVal_t val)
|
||||
{
|
||||
printf("%.5f ", ntohs(*(UInt16*)val.bytes) / 4096.0);
|
||||
}
|
||||
|
||||
void printFP5B(SMCVal_t val)
|
||||
{
|
||||
printf("%.5f ", ntohs(*(UInt16*)val.bytes) / 2048.0);
|
||||
}
|
||||
|
||||
void printFP6A(SMCVal_t val)
|
||||
{
|
||||
printf("%.4f ", ntohs(*(UInt16*)val.bytes) / 1024.0);
|
||||
}
|
||||
|
||||
void printFP79(SMCVal_t val)
|
||||
{
|
||||
printf("%.4f ", ntohs(*(UInt16*)val.bytes) / 512.0);
|
||||
}
|
||||
|
||||
void printFP88(SMCVal_t val)
|
||||
{
|
||||
printf("%.3f ", ntohs(*(UInt16*)val.bytes) / 256.0);
|
||||
}
|
||||
|
||||
void printFPA6(SMCVal_t val)
|
||||
{
|
||||
printf("%.2f ", ntohs(*(UInt16*)val.bytes) / 64.0);
|
||||
}
|
||||
|
||||
void printFPC4(SMCVal_t val)
|
||||
{
|
||||
printf("%.2f ", ntohs(*(UInt16*)val.bytes) / 16.0);
|
||||
}
|
||||
|
||||
void printFPE2(SMCVal_t val)
|
||||
{
|
||||
printf("%.2f ", ntohs(*(UInt16*)val.bytes) / 4.0);
|
||||
}
|
||||
|
||||
void printUInt(SMCVal_t val)
|
||||
{
|
||||
printf("%u ", (unsigned int) _strtoul((char *)val.bytes, val.dataSize, 10));
|
||||
}
|
||||
|
||||
void printSP1E(SMCVal_t val)
|
||||
{
|
||||
printf("%.5f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 16384.0);
|
||||
}
|
||||
|
||||
void printSP3C(SMCVal_t val)
|
||||
{
|
||||
printf("%.5f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 4096.0);
|
||||
}
|
||||
|
||||
void printSP4B(SMCVal_t val)
|
||||
{
|
||||
printf("%.4f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 2048.0);
|
||||
}
|
||||
|
||||
void printSP5A(SMCVal_t val)
|
||||
{
|
||||
printf("%.4f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 1024.0);
|
||||
}
|
||||
|
||||
void printSP69(SMCVal_t val)
|
||||
{
|
||||
printf("%.3f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 512.0);
|
||||
}
|
||||
|
||||
void printSP78(SMCVal_t val)
|
||||
{
|
||||
printf("%.3f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 256.0);
|
||||
}
|
||||
|
||||
void printSP87(SMCVal_t val)
|
||||
{
|
||||
printf("%.3f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 128.0);
|
||||
}
|
||||
|
||||
void printSP96(SMCVal_t val)
|
||||
{
|
||||
printf("%.2f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 64.0);
|
||||
}
|
||||
|
||||
void printSPB4(SMCVal_t val)
|
||||
{
|
||||
printf("%.2f ", ((SInt16)ntohs(*(UInt16*)val.bytes)) / 16.0);
|
||||
}
|
||||
|
||||
void printSPF0(SMCVal_t val)
|
||||
{
|
||||
printf("%.0f ", (float)ntohs(*(UInt16*)val.bytes));
|
||||
}
|
||||
|
||||
void printSI8(SMCVal_t val)
|
||||
{
|
||||
printf("%d ", (signed char)*val.bytes);
|
||||
}
|
||||
|
||||
void printSI16(SMCVal_t val)
|
||||
{
|
||||
printf("%d ", ntohs(*(SInt16*)val.bytes));
|
||||
}
|
||||
|
||||
void printPWM(SMCVal_t val)
|
||||
{
|
||||
printf("%.1f%% ", ntohs(*(UInt16*)val.bytes) * 100 / 65536.0);
|
||||
}
|
||||
|
||||
void printBytesHex(SMCVal_t val)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("(bytes");
|
||||
for (i = 0; i < val.dataSize; i++)
|
||||
printf(" %02x", (unsigned char) val.bytes[i]);
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
void printVal(SMCVal_t val)
|
||||
{
|
||||
printf(" %-4s [%-4s] ", val.key, val.dataType);
|
||||
if (val.dataSize > 0)
|
||||
{
|
||||
if ((strcmp(val.dataType, DATATYPE_UINT8) == 0) ||
|
||||
(strcmp(val.dataType, DATATYPE_UINT16) == 0) ||
|
||||
(strcmp(val.dataType, DATATYPE_UINT32) == 0))
|
||||
printUInt(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FP1F) == 0 && val.dataSize == 2)
|
||||
printFP1F(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FP4C) == 0 && val.dataSize == 2)
|
||||
printFP4C(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FP5B) == 0 && val.dataSize == 2)
|
||||
printFP5B(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FP6A) == 0 && val.dataSize == 2)
|
||||
printFP6A(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FP79) == 0 && val.dataSize == 2)
|
||||
printFP79(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FP88) == 0 && val.dataSize == 2)
|
||||
printFP88(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FPA6) == 0 && val.dataSize == 2)
|
||||
printFPA6(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FPC4) == 0 && val.dataSize == 2)
|
||||
printFPC4(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_FPE2) == 0 && val.dataSize == 2)
|
||||
printFPE2(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP1E) == 0 && val.dataSize == 2)
|
||||
printSP1E(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP3C) == 0 && val.dataSize == 2)
|
||||
printSP3C(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP4B) == 0 && val.dataSize == 2)
|
||||
printSP4B(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP5A) == 0 && val.dataSize == 2)
|
||||
printSP5A(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP69) == 0 && val.dataSize == 2)
|
||||
printSP69(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP78) == 0 && val.dataSize == 2)
|
||||
printSP78(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP87) == 0 && val.dataSize == 2)
|
||||
printSP87(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SP96) == 0 && val.dataSize == 2)
|
||||
printSP96(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SPB4) == 0 && val.dataSize == 2)
|
||||
printSPB4(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SPF0) == 0 && val.dataSize == 2)
|
||||
printSPF0(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SI8) == 0 && val.dataSize == 1)
|
||||
printSI8(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_SI16) == 0 && val.dataSize == 2)
|
||||
printSI16(val);
|
||||
else if (strcmp(val.dataType, DATATYPE_PWM) == 0 && val.dataSize == 2)
|
||||
printPWM(val);
|
||||
|
||||
printBytesHex(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("no data\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kern_return_t SMCOpen(io_connect_t *conn)
|
||||
{
|
||||
kern_return_t result;
|
||||
mach_port_t masterPort;
|
||||
io_iterator_t iterator;
|
||||
io_object_t device;
|
||||
|
||||
IOMasterPort(MACH_PORT_NULL, &masterPort);
|
||||
|
||||
CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
|
||||
result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
|
||||
if (result != kIOReturnSuccess)
|
||||
{
|
||||
printf("Error: IOServiceGetMatchingServices() = %08x\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
device = IOIteratorNext(iterator);
|
||||
IOObjectRelease(iterator);
|
||||
if (device == 0)
|
||||
{
|
||||
printf("Error: no SMC found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = IOServiceOpen(device, mach_task_self(), 0, conn);
|
||||
IOObjectRelease(device);
|
||||
if (result != kIOReturnSuccess)
|
||||
{
|
||||
printf("Error: IOServiceOpen() = %08x\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
kern_return_t SMCClose(io_connect_t conn)
|
||||
{
|
||||
return IOServiceClose(conn);
|
||||
}
|
||||
|
||||
kern_return_t SMCCall2(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure,io_connect_t conn)
|
||||
{
|
||||
size_t structureInputSize;
|
||||
size_t structureOutputSize;
|
||||
structureInputSize = sizeof(SMCKeyData_t);
|
||||
structureOutputSize = sizeof(SMCKeyData_t);
|
||||
|
||||
return IOConnectCallStructMethod(conn, index, inputStructure, structureInputSize, outputStructure, &structureOutputSize);
|
||||
}
|
||||
|
||||
// Provides key info, using a cache to dramatically improve the energy impact of smcFanControl
|
||||
kern_return_t SMCGetKeyInfo(UInt32 key, SMCKeyData_keyInfo_t* keyInfo, io_connect_t conn)
|
||||
{
|
||||
SMCKeyData_t inputStructure;
|
||||
SMCKeyData_t outputStructure;
|
||||
kern_return_t result = kIOReturnSuccess;
|
||||
int i = 0;
|
||||
|
||||
OSSpinLockLock(&g_keyInfoSpinLock);
|
||||
|
||||
for (; i < g_keyInfoCacheCount; ++i)
|
||||
{
|
||||
if (key == g_keyInfoCache[i].key)
|
||||
{
|
||||
*keyInfo = g_keyInfoCache[i].keyInfo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == g_keyInfoCacheCount)
|
||||
{
|
||||
// Not in cache, must look it up.
|
||||
memset(&inputStructure, 0, sizeof(inputStructure));
|
||||
memset(&outputStructure, 0, sizeof(outputStructure));
|
||||
|
||||
inputStructure.key = key;
|
||||
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
|
||||
|
||||
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure, conn);
|
||||
if (result == kIOReturnSuccess)
|
||||
{
|
||||
*keyInfo = outputStructure.keyInfo;
|
||||
if (g_keyInfoCacheCount < KEY_INFO_CACHE_SIZE)
|
||||
{
|
||||
g_keyInfoCache[g_keyInfoCacheCount].key = key;
|
||||
g_keyInfoCache[g_keyInfoCacheCount].keyInfo = outputStructure.keyInfo;
|
||||
++g_keyInfoCacheCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OSSpinLockUnlock(&g_keyInfoSpinLock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn)
|
||||
{
|
||||
kern_return_t result;
|
||||
SMCKeyData_t inputStructure;
|
||||
SMCKeyData_t outputStructure;
|
||||
|
||||
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(val, 0, sizeof(SMCVal_t));
|
||||
|
||||
inputStructure.key = _strtoul(key, 4, 16);
|
||||
sprintf(val->key, key);
|
||||
|
||||
result = SMCGetKeyInfo(inputStructure.key, &outputStructure.keyInfo, conn);
|
||||
if (result != kIOReturnSuccess)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
val->dataSize = outputStructure.keyInfo.dataSize;
|
||||
_ultostr(val->dataType, outputStructure.keyInfo.dataType);
|
||||
inputStructure.keyInfo.dataSize = val->dataSize;
|
||||
inputStructure.data8 = SMC_CMD_READ_BYTES;
|
||||
|
||||
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure,conn);
|
||||
if (result != kIOReturnSuccess)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
io_connect_t g_conn = 0;
|
||||
|
||||
void smc_init(){
|
||||
SMCOpen(&g_conn);
|
||||
}
|
||||
|
||||
void smc_close(){
|
||||
SMCClose(g_conn);
|
||||
}
|
||||
|
||||
kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure)
|
||||
{
|
||||
return SMCCall2(index, inputStructure, outputStructure, g_conn);
|
||||
}
|
||||
|
||||
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val)
|
||||
{
|
||||
return SMCReadKey2(key, val, g_conn);
|
||||
}
|
||||
|
||||
kern_return_t SMCWriteKey2(SMCVal_t writeVal, io_connect_t conn)
|
||||
{
|
||||
kern_return_t result;
|
||||
SMCKeyData_t inputStructure;
|
||||
SMCKeyData_t outputStructure;
|
||||
|
||||
SMCVal_t readVal;
|
||||
|
||||
result = SMCReadKey2(writeVal.key, &readVal,conn);
|
||||
if (result != kIOReturnSuccess)
|
||||
return result;
|
||||
|
||||
if (readVal.dataSize != writeVal.dataSize)
|
||||
return kIOReturnError;
|
||||
|
||||
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
|
||||
|
||||
inputStructure.key = _strtoul(writeVal.key, 4, 16);
|
||||
inputStructure.data8 = SMC_CMD_WRITE_BYTES;
|
||||
inputStructure.keyInfo.dataSize = writeVal.dataSize;
|
||||
memcpy(inputStructure.bytes, writeVal.bytes, sizeof(writeVal.bytes));
|
||||
result = SMCCall2(KERNEL_INDEX_SMC, &inputStructure, &outputStructure,conn);
|
||||
|
||||
if (result != kIOReturnSuccess)
|
||||
return result;
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
kern_return_t SMCWriteKey(SMCVal_t writeVal)
|
||||
{
|
||||
return SMCWriteKey2(writeVal, g_conn);
|
||||
}
|
||||
|
||||
UInt32 SMCReadIndexCount(void)
|
||||
{
|
||||
SMCVal_t val;
|
||||
|
||||
SMCReadKey("#KEY", &val);
|
||||
return _strtoul((char *)val.bytes, val.dataSize, 10);
|
||||
}
|
||||
|
||||
kern_return_t SMCPrintAll(void)
|
||||
{
|
||||
kern_return_t result;
|
||||
SMCKeyData_t inputStructure;
|
||||
SMCKeyData_t outputStructure;
|
||||
|
||||
int totalKeys, i;
|
||||
UInt32Char_t key;
|
||||
SMCVal_t val;
|
||||
|
||||
totalKeys = SMCReadIndexCount();
|
||||
for (i = 0; i < totalKeys; i++)
|
||||
{
|
||||
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(&val, 0, sizeof(SMCVal_t));
|
||||
|
||||
inputStructure.data8 = SMC_CMD_READ_INDEX;
|
||||
inputStructure.data32 = i;
|
||||
|
||||
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
|
||||
if (result != kIOReturnSuccess)
|
||||
continue;
|
||||
|
||||
_ultostr(key, outputStructure.key);
|
||||
|
||||
SMCReadKey(key, &val);
|
||||
printVal(val);
|
||||
}
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
kern_return_t SMCPrintFans(void)
|
||||
{
|
||||
kern_return_t result;
|
||||
SMCVal_t val;
|
||||
UInt32Char_t key;
|
||||
int totalFans, i;
|
||||
|
||||
result = SMCReadKey("FNum", &val);
|
||||
if (result != kIOReturnSuccess)
|
||||
return kIOReturnError;
|
||||
|
||||
totalFans = _strtoul((char *)val.bytes, val.dataSize, 10);
|
||||
printf("Total fans in system: %d\n", totalFans);
|
||||
|
||||
for (i = 0; i < totalFans; i++)
|
||||
{
|
||||
printf("\nFan #%d:\n", i);
|
||||
sprintf(key, "F%dID", i);
|
||||
SMCReadKey(key, &val);
|
||||
printf(" Fan ID : %s\n", val.bytes+4);
|
||||
sprintf(key, "F%dAc", i);
|
||||
SMCReadKey(key, &val);
|
||||
printf(" Actual speed : %.0f\n", _strtof(val.bytes, val.dataSize, 2));
|
||||
sprintf(key, "F%dMn", i);
|
||||
SMCReadKey(key, &val);
|
||||
printf(" Minimum speed: %.0f\n", _strtof(val.bytes, val.dataSize, 2));
|
||||
sprintf(key, "F%dMx", i);
|
||||
SMCReadKey(key, &val);
|
||||
printf(" Maximum speed: %.0f\n", _strtof(val.bytes, val.dataSize, 2));
|
||||
sprintf(key, "F%dSf", i);
|
||||
SMCReadKey(key, &val);
|
||||
printf(" Safe speed : %.0f\n", _strtof(val.bytes, val.dataSize, 2));
|
||||
sprintf(key, "F%dTg", i);
|
||||
SMCReadKey(key, &val);
|
||||
printf(" Target speed : %.0f\n", _strtof(val.bytes, val.dataSize, 2));
|
||||
SMCReadKey("FS! ", &val);
|
||||
if ((_strtoul((char *)val.bytes, 2, 16) & (1 << i)) == 0)
|
||||
printf(" Mode : auto\n");
|
||||
else
|
||||
printf(" Mode : forced\n");
|
||||
}
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
void usage(char* prog)
|
||||
{
|
||||
printf("Apple System Management Control (SMC) tool %s\n", VERSION);
|
||||
printf("Usage:\n");
|
||||
printf("%s [options]\n", prog);
|
||||
printf(" -f : fan info decoded\n");
|
||||
printf(" -h : help\n");
|
||||
printf(" -k <key> : key to manipulate\n");
|
||||
printf(" -l : list all keys and values\n");
|
||||
printf(" -r : read the value of a key\n");
|
||||
printf(" -w <value> : write the specified value to a key\n");
|
||||
printf(" -v : version\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
kern_return_t SMCWriteSimple(UInt32Char_t key, char *wvalue, io_connect_t conn)
|
||||
{
|
||||
kern_return_t result;
|
||||
SMCVal_t val;
|
||||
int i;
|
||||
char c[3];
|
||||
for (i = 0; i < strlen(wvalue); i++)
|
||||
{
|
||||
sprintf(c, "%c%c", wvalue[i * 2], wvalue[(i * 2) + 1]);
|
||||
val.bytes[i] = (int) strtol(c, NULL, 16);
|
||||
}
|
||||
val.dataSize = i / 2;
|
||||
sprintf(val.key, key);
|
||||
result = SMCWriteKey2(val, conn);
|
||||
if (result != kIOReturnSuccess)
|
||||
printf("Error: SMCWriteKey() = %08x\n", result);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double SMCGetTemperature(char *key)
|
||||
{
|
||||
SMCVal_t val;
|
||||
kern_return_t result;
|
||||
|
||||
result = SMCReadKey(key, &val);
|
||||
if (result == kIOReturnSuccess) {
|
||||
// read succeeded - check returned value
|
||||
if (val.dataSize > 0) {
|
||||
if (strcmp(val.dataType, DATATYPE_SP78) == 0) {
|
||||
// convert sp78 value to temperature
|
||||
int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1];
|
||||
return intValue / 256.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// read failed
|
||||
return 0.0;
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Apple System Management Control (SMC) Tool
|
||||
* Copyright (C) 2006 devnull
|
||||
* Portions Copyright (C) 2013 Michael Wilber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SMC_H__
|
||||
#define __SMC_H__
|
||||
#endif
|
||||
|
||||
#define VERSION "0.01"
|
||||
|
||||
#define OP_NONE 0
|
||||
#define OP_LIST 1
|
||||
#define OP_READ 2
|
||||
#define OP_READ_FAN 3
|
||||
#define OP_WRITE 4
|
||||
|
||||
#define KERNEL_INDEX_SMC 2
|
||||
|
||||
#define SMC_CMD_READ_BYTES 5
|
||||
#define SMC_CMD_WRITE_BYTES 6
|
||||
#define SMC_CMD_READ_INDEX 8
|
||||
#define SMC_CMD_READ_KEYINFO 9
|
||||
#define SMC_CMD_READ_PLIMIT 11
|
||||
#define SMC_CMD_READ_VERS 12
|
||||
|
||||
#define DATATYPE_FP1F "fp1f"
|
||||
#define DATATYPE_FP4C "fp4c"
|
||||
#define DATATYPE_FP5B "fp5b"
|
||||
#define DATATYPE_FP6A "fp6a"
|
||||
#define DATATYPE_FP79 "fp79"
|
||||
#define DATATYPE_FP88 "fp88"
|
||||
#define DATATYPE_FPA6 "fpa6"
|
||||
#define DATATYPE_FPC4 "fpc4"
|
||||
#define DATATYPE_FPE2 "fpe2"
|
||||
|
||||
#define DATATYPE_SP1E "sp1e"
|
||||
#define DATATYPE_SP3C "sp3c"
|
||||
#define DATATYPE_SP4B "sp4b"
|
||||
#define DATATYPE_SP5A "sp5a"
|
||||
#define DATATYPE_SP69 "sp69"
|
||||
#define DATATYPE_SP78 "sp78"
|
||||
#define DATATYPE_SP87 "sp87"
|
||||
#define DATATYPE_SP96 "sp96"
|
||||
#define DATATYPE_SPB4 "spb4"
|
||||
#define DATATYPE_SPF0 "spf0"
|
||||
|
||||
#define DATATYPE_UINT8 "ui8 "
|
||||
#define DATATYPE_UINT16 "ui16"
|
||||
#define DATATYPE_UINT32 "ui32"
|
||||
|
||||
#define DATATYPE_SI8 "si8 "
|
||||
#define DATATYPE_SI16 "si16"
|
||||
|
||||
#define DATATYPE_PWM "{pwm"
|
||||
|
||||
typedef struct {
|
||||
char major;
|
||||
char minor;
|
||||
char build;
|
||||
char reserved[1];
|
||||
UInt16 release;
|
||||
} SMCKeyData_vers_t;
|
||||
|
||||
typedef struct {
|
||||
UInt16 version;
|
||||
UInt16 length;
|
||||
UInt32 cpuPLimit;
|
||||
UInt32 gpuPLimit;
|
||||
UInt32 memPLimit;
|
||||
} SMCKeyData_pLimitData_t;
|
||||
|
||||
typedef struct {
|
||||
UInt32 dataSize;
|
||||
UInt32 dataType;
|
||||
char dataAttributes;
|
||||
} SMCKeyData_keyInfo_t;
|
||||
|
||||
typedef unsigned char SMCBytes_t[32];
|
||||
|
||||
typedef struct {
|
||||
UInt32 key;
|
||||
SMCKeyData_vers_t vers;
|
||||
SMCKeyData_pLimitData_t pLimitData;
|
||||
SMCKeyData_keyInfo_t keyInfo;
|
||||
char result;
|
||||
char status;
|
||||
char data8;
|
||||
UInt32 data32;
|
||||
SMCBytes_t bytes;
|
||||
} SMCKeyData_t;
|
||||
|
||||
typedef char UInt32Char_t[5];
|
||||
|
||||
typedef struct {
|
||||
UInt32Char_t key;
|
||||
UInt32 dataSize;
|
||||
UInt32Char_t dataType;
|
||||
SMCBytes_t bytes;
|
||||
} SMCVal_t;
|
||||
|
||||
UInt32 _strtoul(char *str, int size, int base);
|
||||
float _strtof(unsigned char *str, int size, int e);
|
||||
|
||||
// Exclude command-line only code from smcFanControl UI
|
||||
#ifdef CMD_TOOL
|
||||
|
||||
void smc_init();
|
||||
void smc_close();
|
||||
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val);
|
||||
kern_return_t SMCWriteSimple(UInt32Char_t key,char *wvalue,io_connect_t conn);
|
||||
|
||||
#endif //#ifdef CMD_TOOL
|
||||
|
||||
kern_return_t SMCOpen(io_connect_t *conn);
|
||||
kern_return_t SMCClose(io_connect_t conn);
|
||||
kern_return_t SMCReadKey2(UInt32Char_t key, SMCVal_t *val,io_connect_t conn);
|
||||
|
|
@ -10,7 +10,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
// TimesStat contains the amounts of time the CPU has spent performing different
|
|
@ -14,11 +14,11 @@ import (
|
|||
// sys/resource.h
|
||||
const (
|
||||
CPUser = 0
|
||||
CPNice = 1
|
||||
CPSys = 2
|
||||
CPIntr = 3
|
||||
CPIdle = 4
|
||||
CPUStates = 5
|
||||
cpNice = 1
|
||||
cpSys = 2
|
||||
cpIntr = 3
|
||||
cpIdle = 4
|
||||
cpUStates = 5
|
||||
)
|
||||
|
||||
// default value. from time.h
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
package cpu
|
||||
|
||||
import "github.com/shirou/gopsutil/internal/common"
|
||||
import "github.com/shirou/gopsutil/v3/internal/common"
|
||||
|
||||
func perCPUTimes() ([]TimesStat, error) {
|
||||
return []TimesStat{}, common.ErrNotImplementedError
|
|
@ -11,7 +11,7 @@ import (
|
|||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
|
@ -11,7 +11,7 @@ import (
|
|||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var ClocksPerSec = float64(100)
|
|
@ -13,27 +13,27 @@ import (
|
|||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// sys/sched.h
|
||||
var (
|
||||
CPUser = 0
|
||||
CPNice = 1
|
||||
CPSys = 2
|
||||
CPIntr = 3
|
||||
CPIdle = 4
|
||||
CPUStates = 5
|
||||
cpNice = 1
|
||||
cpSys = 2
|
||||
cpIntr = 3
|
||||
cpIdle = 4
|
||||
cpUStates = 5
|
||||
)
|
||||
|
||||
// sys/sysctl.h
|
||||
const (
|
||||
CTLKern = 1 // "high kernel": proc, limits
|
||||
CTLHw = 6 // CTL_HW
|
||||
SMT = 24 // HW_SMT
|
||||
KernCptime = 40 // KERN_CPTIME
|
||||
KernCptime2 = 71 // KERN_CPTIME2
|
||||
ctlKern = 1 // "high kernel": proc, limits
|
||||
ctlHw = 6 // CTL_HW
|
||||
sMT = 24 // HW_sMT
|
||||
kernCptime = 40 // KERN_CPTIME
|
||||
kernCptime2 = 71 // KERN_CPTIME2
|
||||
)
|
||||
|
||||
var ClocksPerSec = float64(128)
|
||||
|
@ -64,15 +64,15 @@ func init() {
|
|||
return
|
||||
}
|
||||
if version >= 6.4 {
|
||||
CPIntr = 4
|
||||
CPIdle = 5
|
||||
CPUStates = 6
|
||||
cpIntr = 4
|
||||
cpIdle = 5
|
||||
cpUStates = 6
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func smt() (bool, error) {
|
||||
mib := []int32{CTLHw, SMT}
|
||||
mib := []int32{ctlHw, sMT}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -116,12 +116,12 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
|||
j *= 2
|
||||
}
|
||||
|
||||
var cpuTimes = make([]int32, CPUStates)
|
||||
var cpuTimes = make([]int32, cpUStates)
|
||||
var mib []int32
|
||||
if percpu {
|
||||
mib = []int32{CTLKern, KernCptime2, int32(j)}
|
||||
mib = []int32{ctlKern, kernCptime2, int32(j)}
|
||||
} else {
|
||||
mib = []int32{CTLKern, KernCptime}
|
||||
mib = []int32{ctlKern, kernCptime}
|
||||
}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
|
@ -135,10 +135,10 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
|||
}
|
||||
c := TimesStat{
|
||||
User: float64(cpuTimes[CPUser]) / ClocksPerSec,
|
||||
Nice: float64(cpuTimes[CPNice]) / ClocksPerSec,
|
||||
System: float64(cpuTimes[CPSys]) / ClocksPerSec,
|
||||
Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec,
|
||||
Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec,
|
||||
Nice: float64(cpuTimes[cpNice]) / ClocksPerSec,
|
||||
System: float64(cpuTimes[cpSys]) / ClocksPerSec,
|
||||
Idle: float64(cpuTimes[cpIdle]) / ClocksPerSec,
|
||||
Irq: float64(cpuTimes[cpIntr]) / ClocksPerSec,
|
||||
}
|
||||
if percpu {
|
||||
c.CPU = fmt.Sprintf("cpu%d", j)
|
|
@ -8,7 +8,7 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ var (
|
|||
procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
|
||||
)
|
||||
|
||||
type Win32_Processor struct {
|
||||
type win32Processor struct {
|
||||
LoadPercentage *uint16
|
||||
Family uint16
|
||||
Manufacturer string
|
||||
|
@ -104,7 +104,7 @@ func Info() ([]InfoStat, error) {
|
|||
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
var dst []Win32_Processor
|
||||
var dst []win32Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
|
||||
return ret, err
|
||||
|
@ -242,7 +242,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
|||
}
|
||||
// physical cores https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L499
|
||||
// for the time being, try with unreliable and slow WMI call…
|
||||
var dst []Win32_Processor
|
||||
var dst []win32Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
|
||||
return 0, err
|
|
@ -0,0 +1,96 @@
|
|||
package disk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
||||
type UsageStat struct {
|
||||
Path string `json:"path"`
|
||||
Fstype string `json:"fstype"`
|
||||
Total uint64 `json:"total"`
|
||||
Free uint64 `json:"free"`
|
||||
Used uint64 `json:"used"`
|
||||
UsedPercent float64 `json:"usedPercent"`
|
||||
InodesTotal uint64 `json:"inodesTotal"`
|
||||
InodesUsed uint64 `json:"inodesUsed"`
|
||||
InodesFree uint64 `json:"inodesFree"`
|
||||
InodesUsedPercent float64 `json:"inodesUsedPercent"`
|
||||
}
|
||||
|
||||
type PartitionStat struct {
|
||||
Device string `json:"device"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
Fstype string `json:"fstype"`
|
||||
Opts []string `json:"opts"`
|
||||
}
|
||||
|
||||
type IOCountersStat struct {
|
||||
ReadCount uint64 `json:"readCount"`
|
||||
MergedReadCount uint64 `json:"mergedReadCount"`
|
||||
WriteCount uint64 `json:"writeCount"`
|
||||
MergedWriteCount uint64 `json:"mergedWriteCount"`
|
||||
ReadBytes uint64 `json:"readBytes"`
|
||||
WriteBytes uint64 `json:"writeBytes"`
|
||||
ReadTime uint64 `json:"readTime"`
|
||||
WriteTime uint64 `json:"writeTime"`
|
||||
IopsInProgress uint64 `json:"iopsInProgress"`
|
||||
IoTime uint64 `json:"ioTime"`
|
||||
WeightedIO uint64 `json:"weightedIO"`
|
||||
Name string `json:"name"`
|
||||
SerialNumber string `json:"serialNumber"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
func (d UsageStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (d PartitionStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
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...)
|
||||
}
|
||||
|
||||
// SerialNumber returns Serial Number of given device or empty string
|
||||
// on error. Name of device is expected, eg. /dev/sda
|
||||
func SerialNumber(name string) (string, error) {
|
||||
return SerialNumberWithContext(context.Background(), name)
|
||||
}
|
||||
|
||||
// Label returns label of given device or empty string on error.
|
||||
// Name of device is expected, eg. /dev/sda
|
||||
// Supports label based on devicemapper name
|
||||
// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
|
||||
func Label(name string) (string, error) {
|
||||
return LabelWithContext(context.Background(), name)
|
||||
}
|
|
@ -4,16 +4,13 @@ package disk
|
|||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/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
|
||||
|
||||
|
@ -26,54 +23,49 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
return ret, err
|
||||
}
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
opts := []string{"rw"}
|
||||
if stat.Flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
opts = []string{"ro"}
|
||||
}
|
||||
if stat.Flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
opts = append(opts, "sync")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
opts = append(opts, "noexec")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
opts = append(opts, "nosuid")
|
||||
}
|
||||
if stat.Flags&unix.MNT_UNION != 0 {
|
||||
opts += ",union"
|
||||
opts = append(opts, "union")
|
||||
}
|
||||
if stat.Flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
opts = append(opts, "async")
|
||||
}
|
||||
if stat.Flags&unix.MNT_DONTBROWSE != 0 {
|
||||
opts += ",nobrowse"
|
||||
opts = append(opts, "nobrowse")
|
||||
}
|
||||
if stat.Flags&unix.MNT_AUTOMOUNTED != 0 {
|
||||
opts += ",automounted"
|
||||
opts = append(opts, "automounted")
|
||||
}
|
||||
if stat.Flags&unix.MNT_JOURNALED != 0 {
|
||||
opts += ",journaled"
|
||||
opts = append(opts, "journaled")
|
||||
}
|
||||
if stat.Flags&unix.MNT_MULTILABEL != 0 {
|
||||
opts += ",multilabel"
|
||||
opts = append(opts, "multilabel")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
opts = append(opts, "noatime")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NODEV != 0 {
|
||||
opts += ",nodev"
|
||||
opts = append(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,13 @@ 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[:])
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
|
@ -14,13 +14,9 @@ import "C"
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/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)))
|
|
@ -6,13 +6,9 @@ package disk
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/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
|
||||
}
|
|
@ -5,29 +5,25 @@ package disk
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/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
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
|
@ -6,18 +6,15 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/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
|
||||
|
||||
|
@ -33,54 +30,54 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
}
|
||||
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
opts := []string{"rw"}
|
||||
if stat.Flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
opts = []string{"ro"}
|
||||
}
|
||||
if stat.Flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
opts = append(opts, "sync")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
opts = append(opts, "noexec")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
opts = append(opts, "nosuid")
|
||||
}
|
||||
if stat.Flags&unix.MNT_UNION != 0 {
|
||||
opts += ",union"
|
||||
opts = append(opts, "union")
|
||||
}
|
||||
if stat.Flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
opts = append(opts, "async")
|
||||
}
|
||||
if stat.Flags&unix.MNT_SUIDDIR != 0 {
|
||||
opts += ",suiddir"
|
||||
opts = append(opts, "suiddir")
|
||||
}
|
||||
if stat.Flags&unix.MNT_SOFTDEP != 0 {
|
||||
opts += ",softdep"
|
||||
opts = append(opts, "softdep")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOSYMFOLLOW != 0 {
|
||||
opts += ",nosymfollow"
|
||||
opts = append(opts, "nosymfollow")
|
||||
}
|
||||
if stat.Flags&unix.MNT_GJOURNAL != 0 {
|
||||
opts += ",gjournal"
|
||||
opts = append(opts, "gjournal")
|
||||
}
|
||||
if stat.Flags&unix.MNT_MULTILABEL != 0 {
|
||||
opts += ",multilabel"
|
||||
opts = append(opts, "multilabel")
|
||||
}
|
||||
if stat.Flags&unix.MNT_ACLS != 0 {
|
||||
opts += ",acls"
|
||||
opts = append(opts, "acls")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
opts = append(opts, "noatime")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOCLUSTERR != 0 {
|
||||
opts += ",noclusterr"
|
||||
opts = append(opts, "noclusterr")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOCLUSTERW != 0 {
|
||||
opts += ",noclusterw"
|
||||
opts = append(opts, "noclusterw")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NFS4ACLS != 0 {
|
||||
opts += ",nfsv4acls"
|
||||
opts = append(opts, "nfsv4acls")
|
||||
}
|
||||
|
||||
d := 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
|
||||
|
@ -117,13 +105,13 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
buf := []byte(r)
|
||||
length := len(buf)
|
||||
|
||||
count := int(uint64(length) / uint64(sizeOfDevstat))
|
||||
count := int(uint64(length) / uint64(sizeOfdevstat))
|
||||
|
||||
buf = buf[8:] // devstat.all has version in the head.
|
||||
// parse buf to Devstat
|
||||
// parse buf to devstat
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*sizeOfDevstat : i*sizeOfDevstat+sizeOfDevstat]
|
||||
d, err := parseDevstat(b)
|
||||
b := buf[i*sizeOfdevstat : i*sizeOfdevstat+sizeOfdevstat]
|
||||
d, err := parsedevstat(b)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -135,12 +123,12 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
}
|
||||
|
||||
ds := IOCountersStat{
|
||||
ReadCount: d.Operations[DEVSTAT_READ],
|
||||
WriteCount: d.Operations[DEVSTAT_WRITE],
|
||||
ReadBytes: d.Bytes[DEVSTAT_READ],
|
||||
WriteBytes: d.Bytes[DEVSTAT_WRITE],
|
||||
ReadTime: uint64(d.Duration[DEVSTAT_READ].Compute() * 1000),
|
||||
WriteTime: uint64(d.Duration[DEVSTAT_WRITE].Compute() * 1000),
|
||||
ReadCount: d.Operations[devstat_READ],
|
||||
WriteCount: d.Operations[devstat_WRITE],
|
||||
ReadBytes: d.Bytes[devstat_READ],
|
||||
WriteBytes: d.Bytes[devstat_WRITE],
|
||||
ReadTime: uint64(d.Duration[devstat_READ].Compute() * 1000),
|
||||
WriteTime: uint64(d.Duration[devstat_WRITE].Compute() * 1000),
|
||||
IoTime: uint64(d.Busy_time.Compute() * 1000),
|
||||
Name: name,
|
||||
}
|
||||
|
@ -150,15 +138,15 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (b Bintime) Compute() float64 {
|
||||
func (b bintime) Compute() float64 {
|
||||
BINTIME_SCALE := 5.42101086242752217003726400434970855712890625e-20
|
||||
return float64(b.Sec) + float64(b.Frac)*BINTIME_SCALE
|
||||
}
|
||||
|
||||
// BT2LD(time) ((long double)(time).sec + (time).frac * BINTIME_SCALE)
|
||||
|
||||
func parseDevstat(buf []byte) (Devstat, error) {
|
||||
var ds Devstat
|
||||
func parsedevstat(buf []byte) (devstat, error) {
|
||||
var ds devstat
|
||||
br := bytes.NewReader(buf)
|
||||
// err := binary.Read(br, binary.LittleEndian, &ds)
|
||||
err := common.Read(br, binary.LittleEndian, &ds)
|
||||
|
@ -172,3 +160,11 @@ func parseDevstat(buf []byte) (Devstat, error) {
|
|||
func getFsType(stat unix.Statfs_t) string {
|
||||
return common.ByteToString(stat.Fstypename[:])
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
|
@ -11,14 +11,14 @@ const (
|
|||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0xf0
|
||||
sizeOfdevstat = 0xf0
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -29,21 +29,21 @@ type (
|
|||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
Busy_from bintime
|
||||
Dev_links _Ctype_struct___0
|
||||
Device_number uint32
|
||||
Device_name [16]int8
|
||||
Unit_number int32
|
||||
Bytes [4]uint64
|
||||
Operations [4]uint64
|
||||
Duration [4]Bintime
|
||||
Busy_time Bintime
|
||||
Creation_time Bintime
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
|
@ -52,7 +52,7 @@ type Devstat struct {
|
|||
Id *byte
|
||||
Sequence1 uint32
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int32
|
||||
Frac uint64
|
||||
}
|
|
@ -11,14 +11,14 @@ const (
|
|||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0x120
|
||||
sizeOfdevstat = 0x120
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -29,21 +29,21 @@ type (
|
|||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
Busy_from bintime
|
||||
Dev_links _Ctype_struct___0
|
||||
Device_number uint32
|
||||
Device_name [16]int8
|
||||
Unit_number int32
|
||||
Bytes [4]uint64
|
||||
Operations [4]uint64
|
||||
Duration [4]Bintime
|
||||
Busy_time Bintime
|
||||
Creation_time Bintime
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
Tag_types [3]uint64
|
||||
|
@ -55,7 +55,7 @@ type Devstat struct {
|
|||
Sequence1 uint32
|
||||
Pad_cgo_2 [4]byte
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int64
|
||||
Frac uint64
|
||||
}
|
|
@ -11,14 +11,14 @@ const (
|
|||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0xf0
|
||||
sizeOfdevstat = 0xf0
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -29,21 +29,21 @@ type (
|
|||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
Busy_from bintime
|
||||
Dev_links _Ctype_struct___0
|
||||
Device_number uint32
|
||||
Device_name [16]int8
|
||||
Unit_number int32
|
||||
Bytes [4]uint64
|
||||
Operations [4]uint64
|
||||
Duration [4]Bintime
|
||||
Busy_time Bintime
|
||||
Creation_time Bintime
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
|
@ -52,7 +52,7 @@ type Devstat struct {
|
|||
Id *byte
|
||||
Sequence1 uint32
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int32
|
||||
Frac uint64
|
||||
}
|
|
@ -13,14 +13,14 @@ const (
|
|||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0x120
|
||||
sizeOfdevstat = 0x120
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -31,21 +31,21 @@ type (
|
|||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
Busy_from bintime
|
||||
Dev_links _Ctype_struct___0
|
||||
Device_number uint32
|
||||
Device_name [16]int8
|
||||
Unit_number int32
|
||||
Bytes [4]uint64
|
||||
Operations [4]uint64
|
||||
Duration [4]Bintime
|
||||
Busy_time Bintime
|
||||
Creation_time Bintime
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
|
@ -55,7 +55,7 @@ type Devstat struct {
|
|||
Sequence1 uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int64
|
||||
Frac uint64
|
||||
}
|
|
@ -13,12 +13,12 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
SectorSize = 512
|
||||
sectorSize = 512
|
||||
)
|
||||
const (
|
||||
// man statfs
|
||||
|
@ -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
|
||||
|
||||
|
@ -259,7 +252,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
Device: fields[0],
|
||||
Mountpoint: unescapeFstab(fields[1]),
|
||||
Fstype: fields[2],
|
||||
Opts: fields[3],
|
||||
Opts: strings.Fields(fields[3]),
|
||||
}
|
||||
|
||||
if !all {
|
||||
|
@ -281,7 +274,11 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
fields := strings.Fields(parts[0])
|
||||
blockDeviceID := fields[2]
|
||||
mountPoint := fields[4]
|
||||
mountOpts := fields[5]
|
||||
mountOpts := strings.Split(fields[5], ",")
|
||||
|
||||
if rootDir := fields[3]; rootDir != "" && rootDir != "/" {
|
||||
mountOpts = append(mountOpts, "bind")
|
||||
}
|
||||
|
||||
fields = strings.Fields(parts[1])
|
||||
fstype := fields[0]
|
||||
|
@ -346,10 +343,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)
|
||||
|
@ -421,8 +414,8 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
return ret, err
|
||||
}
|
||||
d := IOCountersStat{
|
||||
ReadBytes: rbytes * SectorSize,
|
||||
WriteBytes: wbytes * SectorSize,
|
||||
ReadBytes: rbytes * sectorSize,
|
||||
WriteBytes: wbytes * sectorSize,
|
||||
ReadCount: reads,
|
||||
WriteCount: writes,
|
||||
MergedReadCount: mergedReads,
|
||||
|
@ -438,25 +431,19 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
}
|
||||
d.Name = name
|
||||
|
||||
d.SerialNumber = GetDiskSerialNumber(name)
|
||||
d.Label = GetLabel(name)
|
||||
d.SerialNumber, _ = SerialNumberWithContext(ctx, name)
|
||||
d.Label, _ = LabelWithContext(ctx, name)
|
||||
|
||||
ret[name] = d
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// GetDiskSerialNumber returns Serial Number of given device or empty string
|
||||
// on error. Name of device is expected, eg. /dev/sda
|
||||
func GetDiskSerialNumber(name string) string {
|
||||
return GetDiskSerialNumberWithContext(context.Background(), name)
|
||||
}
|
||||
|
||||
func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
var stat unix.Stat_t
|
||||
err := unix.Stat(name, &stat)
|
||||
if err != nil {
|
||||
return ""
|
||||
return "", err
|
||||
}
|
||||
major := unix.Major(uint64(stat.Rdev))
|
||||
minor := unix.Minor(uint64(stat.Rdev))
|
||||
|
@ -468,7 +455,7 @@ func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
|||
for scanner.Scan() {
|
||||
values := strings.Split(scanner.Text(), "=")
|
||||
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
|
||||
return values[1]
|
||||
return values[1], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -479,28 +466,24 @@ func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
|||
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
|
||||
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
|
||||
if len(model) > 0 && len(serial) > 0 {
|
||||
return fmt.Sprintf("%s_%s", string(model), string(serial))
|
||||
return fmt.Sprintf("%s_%s", string(model), string(serial)), nil
|
||||
}
|
||||
return ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// GetLabel returns label of given device or empty string on error.
|
||||
// Name of device is expected, eg. /dev/sda
|
||||
// Supports label based on devicemapper name
|
||||
// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
|
||||
func GetLabel(name string) string {
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
// Try label based on devicemapper name
|
||||
dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
|
||||
|
||||
if !common.PathExists(dmname_filename) {
|
||||
return ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
dmname, err := ioutil.ReadFile(dmname_filename)
|
||||
if err != nil {
|
||||
return ""
|
||||
return "", err
|
||||
} else {
|
||||
return strings.TrimSpace(string(dmname))
|
||||
return strings.TrimSpace(string(dmname)), nil
|
||||
}
|
||||
}
|
||||
|
|
@ -6,16 +6,11 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"path"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/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
|
||||
|
||||
|
@ -31,33 +26,33 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
}
|
||||
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
opts := []string{"rw"}
|
||||
if stat.F_flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
opts = []string{"rw"}
|
||||
}
|
||||
if stat.F_flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
opts = append(opts, "sync")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
opts = append(opts, "noexec")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
opts = append(opts, "nosuid")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NODEV != 0 {
|
||||
opts += ",nodev"
|
||||
opts = append(opts, "nodev")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
opts = append(opts, "async")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_SOFTDEP != 0 {
|
||||
opts += ",softdep"
|
||||
opts = append(opts, "softdep")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
opts = append(opts, "noatime")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_WXALLOWED != 0 {
|
||||
opts += ",wxallowed"
|
||||
opts = append(opts, "wxallowed")
|
||||
}
|
||||
|
||||
d := 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)
|
||||
|
@ -166,3 +148,11 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
|||
func getFsType(stat unix.Statfs_t) string {
|
||||
return common.IntToString(stat.F_fstypename[:])
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
|
@ -6,10 +6,10 @@
|
|||
package disk
|
||||
|
||||
const (
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -34,4 +34,4 @@ type Timeval struct {
|
|||
}
|
||||
|
||||
type Diskstat struct{}
|
||||
type Bintime struct{}
|
||||
type bintime struct{}
|
|
@ -4,10 +4,10 @@
|
|||
package disk
|
||||
|
||||
const (
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -33,4 +33,4 @@ type Timeval struct {
|
|||
}
|
||||
|
||||
type Diskstat struct{}
|
||||
type Bintime struct{}
|
||||
type bintime struct{}
|
|
@ -10,7 +10,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -73,7 +69,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
Device: fields[0],
|
||||
Mountpoint: fields[1],
|
||||
Fstype: fields[2],
|
||||
Opts: fields[3],
|
||||
Opts: strings.Split(fields[3], ","),
|
||||
})
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
|
@ -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 {
|
||||
|
@ -125,3 +113,10 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
|||
|
||||
return usageStat, nil
|
||||
}
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
|
@ -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)
|
|
@ -9,7 +9,7 @@ import (
|
|||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -21,8 +21,8 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
FileFileCompression = int64(16) // 0x00000010
|
||||
FileReadOnlyVolume = int64(524288) // 0x00080000
|
||||
fileFileCompression = int64(16) // 0x00000010
|
||||
fileReadOnlyVolume = int64(524288) // 0x00080000
|
||||
)
|
||||
|
||||
// diskPerformance is an equivalent representation of DISK_PERFORMANCE in the Windows API.
|
||||
|
@ -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)
|
||||
|
@ -118,12 +110,12 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
|||
}
|
||||
return ret, err
|
||||
}
|
||||
opts := "rw"
|
||||
if lpFileSystemFlags&FileReadOnlyVolume != 0 {
|
||||
opts = "ro"
|
||||
opts := []string{"rw"}
|
||||
if lpFileSystemFlags&fileReadOnlyVolume != 0 {
|
||||
opts = []string{"ro"}
|
||||
}
|
||||
if lpFileSystemFlags&FileFileCompression != 0 {
|
||||
opts += ".compress"
|
||||
if lpFileSystemFlags&fileFileCompression != 0 {
|
||||
opts = append(opts, "compress")
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
|
@ -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 {
|
||||
|
@ -193,3 +181,11 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
}
|
||||
return drivemap, nil
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
@ -27,7 +27,7 @@ type InfoStat struct {
|
|||
KernelArch string `json:"kernelArch"` // native cpu architecture queried at runtime, as returned by `uname -m` or empty string in case of error
|
||||
VirtualizationSystem string `json:"virtualizationSystem"`
|
||||
VirtualizationRole string `json:"virtualizationRole"` // guest or host
|
||||
HostID string `json:"hostid"` // ex: uuid
|
||||
HostID string `json:"hostId"` // ex: uuid
|
||||
}
|
||||
|
||||
type UserStat struct {
|
||||
|
@ -39,7 +39,9 @@ type UserStat struct {
|
|||
|
||||
type TemperatureStat struct {
|
||||
SensorKey string `json:"sensorKey"`
|
||||
Temperature float64 `json:"sensorTemperature"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
High float64 `json:"sensorHigh"`
|
||||
Critical float64 `json:"sensorCritical"`
|
||||
}
|
||||
|
||||
func (h InfoStat) String() string {
|
|
@ -12,13 +12,13 @@ import (
|
|||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// from utmpx.h
|
||||
const USER_PROCESS = 7
|
||||
const user_PROCESS = 7
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
||||
uuid, err := unix.Sysctl("kern.uuid")
|
||||
|
@ -64,7 +64,7 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
|||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if u.Type != USER_PROCESS {
|
||||
if u.Type != user_PROCESS {
|
||||
continue
|
||||
}
|
||||
user := UserStat{
|
|
@ -6,7 +6,7 @@ package host
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
|
@ -5,7 +5,7 @@ package host
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
|
@ -12,8 +12,8 @@ import (
|
|||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
|
@ -15,11 +15,11 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type LSB struct {
|
||||
type lsbStruct struct {
|
||||
ID string
|
||||
Release string
|
||||
Codename string
|
||||
|
@ -27,7 +27,11 @@ type LSB struct {
|
|||
}
|
||||
|
||||
// from utmp.h
|
||||
const USER_PROCESS = 7
|
||||
const (
|
||||
user_PROCESS = 7
|
||||
|
||||
hostTemperatureScale = 1000.0
|
||||
)
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
||||
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
|
||||
|
@ -104,7 +108,7 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
|||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if u.Type != USER_PROCESS {
|
||||
if u.Type != user_PROCESS {
|
||||
continue
|
||||
}
|
||||
user := UserStat{
|
||||
|
@ -120,8 +124,8 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
|||
|
||||
}
|
||||
|
||||
func getLSB() (*LSB, error) {
|
||||
ret := &LSB{}
|
||||
func getlsbStruct() (*lsbStruct, error) {
|
||||
ret := &lsbStruct{}
|
||||
if common.PathExists(common.HostEtc("lsb-release")) {
|
||||
contents, err := common.ReadLines(common.HostEtc("lsb-release"))
|
||||
if err != nil {
|
||||
|
@ -175,9 +179,9 @@ func getLSB() (*LSB, error) {
|
|||
}
|
||||
|
||||
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
|
||||
lsb, err := getLSB()
|
||||
lsb, err := getlsbStruct()
|
||||
if err != nil {
|
||||
lsb = &LSB{}
|
||||
lsb = &lsbStruct{}
|
||||
}
|
||||
|
||||
if common.PathExists(common.HostEtc("oracle-release")) {
|
||||
|
@ -366,19 +370,27 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
|||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
var temperatures []TemperatureStat
|
||||
files, err := filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*"))
|
||||
if err != nil {
|
||||
var err error
|
||||
|
||||
var files []string
|
||||
|
||||
temperatures := make([]TemperatureStat, 0)
|
||||
|
||||
// Only the temp*_input file provides current temperature
|
||||
// value in millidegree Celsius as reported by the temperature to the device:
|
||||
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_input")); err != nil {
|
||||
return temperatures, err
|
||||
}
|
||||
|
||||
if len(files) == 0 {
|
||||
// CentOS has an intermediate /device directory:
|
||||
// https://github.com/giampaolo/psutil/issues/971
|
||||
files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/device/temp*_*"))
|
||||
if err != nil {
|
||||
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/device/temp*_input")); err != nil {
|
||||
return temperatures, err
|
||||
}
|
||||
}
|
||||
|
||||
var warns Warnings
|
||||
|
||||
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
|
||||
|
@ -413,6 +425,8 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
|
|||
return temperatures, warns.Reference()
|
||||
}
|
||||
|
||||
temperatures = make([]TemperatureStat, 0, len(files))
|
||||
|
||||
// example directory
|
||||
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
|
||||
// name temp1_input temp2_input temp3_input temp4_input temp5_input temp6_input temp7_input
|
||||
|
@ -420,44 +434,81 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
|
|||
// subsystem/ temp1_max temp2_max temp3_max temp4_max temp5_max temp6_max temp7_max
|
||||
// temp1_crit temp2_crit temp3_crit temp4_crit temp5_crit temp6_crit temp7_crit uevent
|
||||
for _, file := range files {
|
||||
filename := strings.Split(filepath.Base(file), "_")
|
||||
if filename[1] == "label" {
|
||||
// Do not try to read the temperature of the label file
|
||||
continue
|
||||
}
|
||||
var raw []byte
|
||||
|
||||
var temperature float64
|
||||
|
||||
// Get the base directory location
|
||||
directory := filepath.Dir(file)
|
||||
|
||||
// Get the base filename prefix like temp1
|
||||
basename := strings.Split(filepath.Base(file), "_")[0]
|
||||
|
||||
// Get the base path like <dir>/temp1
|
||||
basepath := filepath.Join(directory, basename)
|
||||
|
||||
// Get the label of the temperature you are reading
|
||||
var label string
|
||||
c, _ := ioutil.ReadFile(filepath.Join(filepath.Dir(file), filename[0]+"_label"))
|
||||
if c != nil {
|
||||
//format the label from "Core 0" to "core0_"
|
||||
label = fmt.Sprintf("%s_", strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(c))), " "), ""))
|
||||
label := ""
|
||||
|
||||
if raw, _ = ioutil.ReadFile(basepath + "_label"); len(raw) != 0 {
|
||||
// Format the label from "Core 0" to "core_0"
|
||||
label = strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(raw))), " "), "_")
|
||||
}
|
||||
|
||||
// Get the name of the temperature you are reading
|
||||
name, err := ioutil.ReadFile(filepath.Join(filepath.Dir(file), "name"))
|
||||
if err != nil {
|
||||
if raw, err = ioutil.ReadFile(filepath.Join(directory, "name")); err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(string(raw))
|
||||
|
||||
if label != "" {
|
||||
name = name + "_" + label
|
||||
}
|
||||
|
||||
// Get the temperature reading
|
||||
current, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
temperature, err := strconv.ParseFloat(strings.TrimSpace(string(current)), 64)
|
||||
if err != nil {
|
||||
if raw, err = ioutil.ReadFile(file); err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
tempName := strings.TrimSpace(strings.ToLower(string(strings.Join(filename[1:], ""))))
|
||||
if temperature, err = strconv.ParseFloat(strings.TrimSpace(string(raw)), 64); err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Add discovered temperature sensor to the list
|
||||
temperatures = append(temperatures, TemperatureStat{
|
||||
SensorKey: fmt.Sprintf("%s_%s%s", strings.TrimSpace(string(name)), label, tempName),
|
||||
Temperature: temperature / 1000.0,
|
||||
SensorKey: name,
|
||||
Temperature: temperature / hostTemperatureScale,
|
||||
High: optionalValueReadFromFile(basepath+"_max") / hostTemperatureScale,
|
||||
Critical: optionalValueReadFromFile(basepath+"_crit") / hostTemperatureScale,
|
||||
})
|
||||
}
|
||||
|
||||
return temperatures, warns.Reference()
|
||||
}
|
||||
|
||||
func optionalValueReadFromFile(filename string) float64 {
|
||||
var raw []byte
|
||||
|
||||
var err error
|
||||
|
||||
var value float64
|
||||
|
||||
// Check if file exists
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if raw, err = ioutil.ReadFile(filename); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if value, err = strconv.ParseFloat(strings.TrimSpace(string(raw)), 64); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
|
@ -11,8 +11,8 @@ import (
|
|||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
|
@ -12,7 +12,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
|
@ -13,8 +13,8 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
|
@ -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
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue