update and tidy go mod

This commit is contained in:
vcaesar 2019-07-30 13:40:45 -04:00
parent c66bdc1120
commit ea74787b10
217 changed files with 12543 additions and 5747 deletions

26
go.mod
View File

@ -3,23 +3,19 @@ module github.com/go-vgo/robotgo
require ( require (
github.com/BurntSushi/xgb v0.0.0-20160522221800-27f122750802 github.com/BurntSushi/xgb v0.0.0-20160522221800-27f122750802
github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/go-ole/go-ole v1.2.4 // indirect github.com/go-ole/go-ole v1.2.4 // indirect
github.com/lxn/win v0.0.0-20190502150424-4a44be4873a6 github.com/lxn/win v0.0.0-20190716185335-d1d36f0e4f48
github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776 // indirect
github.com/otiai10/gosseract v2.2.1+incompatible github.com/otiai10/gosseract v2.2.1+incompatible
github.com/robotn/gohook v0.0.0-20190414171059-39135b21e438 github.com/robotn/gohook v0.0.0-20190728181201-ec680ecf20e8
github.com/shirou/gopsutil v2.18.12+incompatible // indirect github.com/stretchr/testify v1.3.0 // indirect
// github.com/shirou/gopsutil v0.0.0-20190131151121-071446942108 // indirect github.com/vcaesar/gops v0.0.0-20190724160211-ed69882cab46
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect github.com/vcaesar/imgo v0.0.0-20190523174309-2cf5275c2a13
github.com/vcaesar/gops v0.0.0-20190507132250-5fc24a63c55a github.com/vcaesar/tt v0.0.0-20190713164158-ecee6bc61ac7
github.com/vcaesar/imgo v0.0.0-20181209162409-13af122cf2fa golang.org/x/image v0.0.0-20190729225735-1bd0cf576493
github.com/vcaesar/tt v0.0.0-20190414175154-71a843cbe853 golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 // indirect golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e // indirect
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09 // indirect
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872 // indirect
golang.org/x/text v0.3.2 // indirect
golang.org/x/tools v0.0.0-20190501045030-23463209683d // indirect
) )
//golang.org/x/image => github.com/golang/image v0.0.0-20181116024801-cd38e8056d9b //golang.org/x/image => github.com/golang/image v0.0.0-20181116024801-cd38e8056d9b

83
go.sum
View File

@ -1,56 +1,55 @@
bou.ke/monkey v1.0.1 h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U=
bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg=
github.com/BurntSushi/xgb v0.0.0-20160522221800-27f122750802 h1:otE7gFP0KwnPTKtMvPLOcWDZxx6rXYyJGlrXbhoD7og= github.com/BurntSushi/xgb v0.0.0-20160522221800-27f122750802 h1:otE7gFP0KwnPTKtMvPLOcWDZxx6rXYyJGlrXbhoD7og=
github.com/BurntSushi/xgb v0.0.0-20160522221800-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522221800-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e h1:4ZrkT/RzpnROylmoQL57iVUL57wGKTR5O6KpVnbm2tA= github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e h1:4ZrkT/RzpnROylmoQL57iVUL57wGKTR5O6KpVnbm2tA=
github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k= github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k=
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 h1:UUppSQnhf4Yc6xGxSkoQpPhb7RVzuv5Nb1mwJ5VId9s= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705/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/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/golang/image v0.0.0-20181116024801-cd38e8056d9b h1:560WQdaWjsfqNwVBNZLN3uPrHCoa0OiZkFIvb/x+PwE= github.com/lxn/win v0.0.0-20190716185335-d1d36f0e4f48 h1:J2doxiYgOxforcFE2tj6KyLIDF+fBUODRUVNf0EVdnI=
github.com/golang/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:W3cvIh6MZCq53QRt4EH8hvU9HPLAPXNxfcoJxCiaTV4= github.com/lxn/win v0.0.0-20190716185335-d1d36f0e4f48/go.mod h1:oO6+4g3P1GcPAG7LPffwn8Ye0cxW0goh0sUZ6+lRFPs=
github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb h1:W0jr+BhzUWF6woATVXwDdmDkouJfNJEiITOjtOEIlfI= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs=
github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb/go.mod h1:5JyrLPvD/ZdaYkT7IqKhsP5xt7aLjA99KXRtk4EIYDk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/lxn/win v0.0.0-20190311093451-0040366d7450 h1:jB6Qj4k3jLhRQ7QxW6aycyLQr5oGNvNWeGv/4+az2Qk= github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776 h1:o59bHXu8Ejas8Kq6pjoVJQ9/neN66SM8AKh6wI42BBs=
github.com/lxn/win v0.0.0-20190311093451-0040366d7450/go.mod h1:jACzEp9RV7NhfPJQkiCNTteU4nkZZVlvkNpYtVOZPfE= github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4=
github.com/lxn/win v0.0.0-20190502150424-4a44be4873a6 h1:HCqkYgg8DYJSSG/XTW4f/AzDsO6rgoBDJeedM/Pe1kw=
github.com/lxn/win v0.0.0-20190502150424-4a44be4873a6/go.mod h1:jACzEp9RV7NhfPJQkiCNTteU4nkZZVlvkNpYtVOZPfE=
github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I= github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I=
github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE= github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE=
github.com/robotn/gohook v0.0.0-20190413172657-5b9ae1915c78 h1:eQiF6mZ6ThSrUbFPev8VsTjDPYp8XN7DBfSOa4mAf/k= github.com/otiai10/mint v1.2.4 h1:DxYL0itZyPaR5Z9HILdxSoHx+gNs6Yx+neOGS3IVUk0=
github.com/robotn/gohook v0.0.0-20190413172657-5b9ae1915c78/go.mod h1:YD5RyCnUEY2xqtkkgeQVZ31UAfAnVPwUxpTE5cwSXg4= github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M=
github.com/robotn/gohook v0.0.0-20190414171059-39135b21e438 h1:/c4zm1y/TYtwZYJctjQPcipBTxe9aY6qeZNVlxm8i3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/robotn/gohook v0.0.0-20190414171059-39135b21e438/go.mod h1:YD5RyCnUEY2xqtkkgeQVZ31UAfAnVPwUxpTE5cwSXg4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v0.0.0-20190131151121-071446942108 h1:XXgDK65TPH+Qbo2sdYHldM5avclwThBXVYZHxroFkTQ= github.com/robotn/gohook v0.0.0-20190728181201-ec680ecf20e8 h1:ZfcFB1gHQWPtROZmnqN3/y5aKFaZ5Equ4qSGZzJFSf8=
github.com/shirou/gopsutil v0.0.0-20190131151121-071446942108/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/robotn/gohook v0.0.0-20190728181201-ec680ecf20e8/go.mod h1:YD5RyCnUEY2xqtkkgeQVZ31UAfAnVPwUxpTE5cwSXg4=
github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= github.com/shirou/gopsutil v2.19.6+incompatible h1:49/Gru26Lne9Cl3IoAVDZVM09hvkSrUodgIIsCVRwbs=
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v2.19.6+incompatible/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/vcaesar/gops v0.0.0-20190507132250-5fc24a63c55a h1:fJjUOUo83Fw38VZcX93P4bIVcRslXJSE9o40ejDygps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/vcaesar/gops v0.0.0-20190507132250-5fc24a63c55a/go.mod h1:3yObfyOwqFrEDS7UgoWd+DIYTcHdlsd8K1uKQz1lc6g= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/vcaesar/imgo v0.0.0-20181209162409-13af122cf2fa h1:kOg2u5TN+l2IBl4Q0Xm3bZRQ5gK3zGXRi/24XT8L7FI= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/vcaesar/imgo v0.0.0-20181209162409-13af122cf2fa/go.mod h1:D+Ywq+8bsOIg4nUk1lgHtPGxYxknhySi/HfZjG7VN/g= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/vcaesar/tt v0.0.0-20190311143935-d2abd51da7af/go.mod h1:xKkGp+ufbz/1DQmNxdbAMFqZJOVIJEX7dGvLZMhPIWg= github.com/vcaesar/gops v0.0.0-20190724160211-ed69882cab46 h1:zpU2Tr8aBfv+J6vH3NnAadcfThAFbRLGeYb4ww3ko38=
github.com/vcaesar/tt v0.0.0-20190414175154-71a843cbe853 h1:QpCUo1lQQ3E7kLp5+woEi23HZ5qsvwvXqIVv5VDOiAI= github.com/vcaesar/gops v0.0.0-20190724160211-ed69882cab46/go.mod h1:J9SDgZxjSePEBlF0yG9NjHftBbybmRPhLZIDbJz83Fw=
github.com/vcaesar/tt v0.0.0-20190414175154-71a843cbe853/go.mod h1:xKkGp+ufbz/1DQmNxdbAMFqZJOVIJEX7dGvLZMhPIWg= github.com/vcaesar/imgo v0.0.0-20190523174309-2cf5275c2a13 h1:BsisshViEpto+nl0UUMo06z9LmsgLKCRrJDAmN+wzLo=
github.com/vcaesar/imgo v0.0.0-20190523174309-2cf5275c2a13/go.mod h1:D+Ywq+8bsOIg4nUk1lgHtPGxYxknhySi/HfZjG7VN/g=
github.com/vcaesar/tt v0.0.0-20190713164158-ecee6bc61ac7 h1:a64ynLITFRQwdt9zAYtVN2AJuJHq0Mr7pYTtyKrGwFk=
github.com/vcaesar/tt v0.0.0-20190713164158-ecee6bc61ac7/go.mod h1:xKkGp+ufbz/1DQmNxdbAMFqZJOVIJEX7dGvLZMhPIWg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190729225735-1bd0cf576493 h1:hw8b4aUfc6J+8Ekj2V0VCmgBCGQ9azXN0lo/I/NSw1Q=
golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f h1:FO4MZ3N56GnxbqxGKqh+YTzUWQ2sDwtFQEZgLOxh9Jc= golang.org/x/image v0.0.0-20190729225735-1bd0cf576493/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872 h1:cGjJzUd8RgBw428LXP65YXni0aiGNA4Bl+ls8SmLOm8=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190501045030-23463209683d/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=

View File

@ -387,7 +387,7 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat
} }
f.Set(fArr) f.Set(fArr)
} }
case reflect.Uint8: case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
safeArray := prop.ToArray() safeArray := prop.ToArray()
if safeArray != nil { if safeArray != nil {
arr := safeArray.ToValueArray() arr := safeArray.ToValueArray()
@ -398,6 +398,17 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat
} }
f.Set(fArr) 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: default:
return &ErrFieldMismatch{ return &ErrFieldMismatch{
StructType: of.Type(), StructType: of.Type(),

2
vendor/github.com/lxn/win/AUTHORS generated vendored
View File

@ -26,7 +26,9 @@ Kevin Pors <krpors@gmail.com>
ktye <ktye@users.noreply.github.com> ktye <ktye@users.noreply.github.com>
mycaosf <mycaosf@gmail.com> mycaosf <mycaosf@gmail.com>
ryujimiya <ryujimiya236@gmail.com> ryujimiya <ryujimiya236@gmail.com>
Simon Rozman <simon@rozman.si>
Tiago Carvalho <sugoiuguu@tfwno.gf> Tiago Carvalho <sugoiuguu@tfwno.gf>
wsf01 <wf1337@sina.com> wsf01 <wf1337@sina.com>
gonutz gonutz
Cory Redmond <ace@ac3-servers.eu> Cory Redmond <ace@ac3-servers.eu>
Dmitry Bagdanov <dimbojob@gmail.com>

170
vendor/github.com/lxn/win/gdi32.go generated vendored
View File

@ -7,9 +7,10 @@
package win package win
import ( import (
"golang.org/x/sys/windows"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/sys/windows"
) )
// GetDeviceCaps index constants // GetDeviceCaps index constants
@ -1033,77 +1034,79 @@ var (
libmsimg32 *windows.LazyDLL libmsimg32 *windows.LazyDLL
// Functions // Functions
abortDoc *windows.LazyProc abortDoc *windows.LazyProc
addFontResourceEx *windows.LazyProc addFontResourceEx *windows.LazyProc
alphaBlend *windows.LazyProc addFontMemResourceEx *windows.LazyProc
bitBlt *windows.LazyProc alphaBlend *windows.LazyProc
choosePixelFormat *windows.LazyProc bitBlt *windows.LazyProc
closeEnhMetaFile *windows.LazyProc choosePixelFormat *windows.LazyProc
combineRgn *windows.LazyProc closeEnhMetaFile *windows.LazyProc
copyEnhMetaFile *windows.LazyProc combineRgn *windows.LazyProc
createBitmap *windows.LazyProc copyEnhMetaFile *windows.LazyProc
createCompatibleBitmap *windows.LazyProc createBitmap *windows.LazyProc
createBrushIndirect *windows.LazyProc createCompatibleBitmap *windows.LazyProc
createCompatibleDC *windows.LazyProc createBrushIndirect *windows.LazyProc
createDC *windows.LazyProc createCompatibleDC *windows.LazyProc
createDIBSection *windows.LazyProc createDC *windows.LazyProc
createFontIndirect *windows.LazyProc createDIBSection *windows.LazyProc
createEnhMetaFile *windows.LazyProc createFontIndirect *windows.LazyProc
createIC *windows.LazyProc createEnhMetaFile *windows.LazyProc
createPatternBrush *windows.LazyProc createIC *windows.LazyProc
createRectRgn *windows.LazyProc createPatternBrush *windows.LazyProc
deleteDC *windows.LazyProc createRectRgn *windows.LazyProc
deleteEnhMetaFile *windows.LazyProc deleteDC *windows.LazyProc
deleteObject *windows.LazyProc deleteEnhMetaFile *windows.LazyProc
ellipse *windows.LazyProc deleteObject *windows.LazyProc
endDoc *windows.LazyProc ellipse *windows.LazyProc
endPage *windows.LazyProc endDoc *windows.LazyProc
excludeClipRect *windows.LazyProc endPage *windows.LazyProc
extCreatePen *windows.LazyProc excludeClipRect *windows.LazyProc
fillRgn *windows.LazyProc extCreatePen *windows.LazyProc
gdiFlush *windows.LazyProc fillRgn *windows.LazyProc
getBkColor *windows.LazyProc gdiFlush *windows.LazyProc
getDeviceCaps *windows.LazyProc getBkColor *windows.LazyProc
getDIBits *windows.LazyProc getDeviceCaps *windows.LazyProc
getEnhMetaFile *windows.LazyProc getDIBits *windows.LazyProc
getEnhMetaFileHeader *windows.LazyProc getEnhMetaFile *windows.LazyProc
getObject *windows.LazyProc getEnhMetaFileHeader *windows.LazyProc
getPixel *windows.LazyProc getObject *windows.LazyProc
getRgnBox *windows.LazyProc getPixel *windows.LazyProc
getStockObject *windows.LazyProc getRgnBox *windows.LazyProc
getTextColor *windows.LazyProc getStockObject *windows.LazyProc
getTextExtentExPoint *windows.LazyProc getTextColor *windows.LazyProc
getTextExtentPoint32 *windows.LazyProc getTextExtentExPoint *windows.LazyProc
getTextMetrics *windows.LazyProc getTextExtentPoint32 *windows.LazyProc
getViewportOrgEx *windows.LazyProc getTextMetrics *windows.LazyProc
gradientFill *windows.LazyProc getViewportOrgEx *windows.LazyProc
intersectClipRect *windows.LazyProc gradientFill *windows.LazyProc
lineTo *windows.LazyProc intersectClipRect *windows.LazyProc
moveToEx *windows.LazyProc lineTo *windows.LazyProc
playEnhMetaFile *windows.LazyProc moveToEx *windows.LazyProc
polyline *windows.LazyProc playEnhMetaFile *windows.LazyProc
rectangle *windows.LazyProc polyline *windows.LazyProc
removeFontResourceEx *windows.LazyProc rectangle *windows.LazyProc
resetDC *windows.LazyProc removeFontResourceEx *windows.LazyProc
restoreDC *windows.LazyProc removeFontMemResourceEx *windows.LazyProc
roundRect *windows.LazyProc resetDC *windows.LazyProc
selectObject *windows.LazyProc restoreDC *windows.LazyProc
setBkColor *windows.LazyProc roundRect *windows.LazyProc
setBkMode *windows.LazyProc selectObject *windows.LazyProc
setBrushOrgEx *windows.LazyProc setBkColor *windows.LazyProc
setDIBits *windows.LazyProc setBkMode *windows.LazyProc
setPixel *windows.LazyProc setBrushOrgEx *windows.LazyProc
setPixelFormat *windows.LazyProc setDIBits *windows.LazyProc
setStretchBltMode *windows.LazyProc setPixel *windows.LazyProc
setTextColor *windows.LazyProc setPixelFormat *windows.LazyProc
setViewportOrgEx *windows.LazyProc setStretchBltMode *windows.LazyProc
saveDC *windows.LazyProc setTextColor *windows.LazyProc
startDoc *windows.LazyProc setViewportOrgEx *windows.LazyProc
startPage *windows.LazyProc saveDC *windows.LazyProc
stretchBlt *windows.LazyProc startDoc *windows.LazyProc
swapBuffers *windows.LazyProc startPage *windows.LazyProc
textOut *windows.LazyProc stretchBlt *windows.LazyProc
transparentBlt *windows.LazyProc swapBuffers *windows.LazyProc
textOut *windows.LazyProc
transparentBlt *windows.LazyProc
) )
func init() { func init() {
@ -1114,6 +1117,7 @@ func init() {
// Functions // Functions
abortDoc = libgdi32.NewProc("AbortDoc") abortDoc = libgdi32.NewProc("AbortDoc")
addFontResourceEx = libgdi32.NewProc("AddFontResourceExW") addFontResourceEx = libgdi32.NewProc("AddFontResourceExW")
addFontMemResourceEx = libgdi32.NewProc("AddFontMemResourceEx")
bitBlt = libgdi32.NewProc("BitBlt") bitBlt = libgdi32.NewProc("BitBlt")
choosePixelFormat = libgdi32.NewProc("ChoosePixelFormat") choosePixelFormat = libgdi32.NewProc("ChoosePixelFormat")
closeEnhMetaFile = libgdi32.NewProc("CloseEnhMetaFile") closeEnhMetaFile = libgdi32.NewProc("CloseEnhMetaFile")
@ -1161,6 +1165,7 @@ func init() {
polyline = libgdi32.NewProc("Polyline") polyline = libgdi32.NewProc("Polyline")
rectangle = libgdi32.NewProc("Rectangle") rectangle = libgdi32.NewProc("Rectangle")
removeFontResourceEx = libgdi32.NewProc("RemoveFontResourceExW") removeFontResourceEx = libgdi32.NewProc("RemoveFontResourceExW")
removeFontMemResourceEx = libgdi32.NewProc("RemoveFontMemResourceEx")
resetDC = libgdi32.NewProc("ResetDCW") resetDC = libgdi32.NewProc("ResetDCW")
restoreDC = libgdi32.NewProc("RestoreDC") restoreDC = libgdi32.NewProc("RestoreDC")
roundRect = libgdi32.NewProc("RoundRect") roundRect = libgdi32.NewProc("RoundRect")
@ -1204,6 +1209,18 @@ func AddFontResourceEx(lpszFilename *uint16, fl uint32, pdv unsafe.Pointer) int3
return int32(ret) return int32(ret)
} }
func AddFontMemResourceEx(pFileView uintptr, cjSize uint32, pvReserved unsafe.Pointer, pNumFonts *uint32) HANDLE {
ret, _, _ := syscall.Syscall6(addFontMemResourceEx.Addr(), 4,
pFileView,
uintptr(cjSize),
uintptr(pvReserved),
uintptr(unsafe.Pointer(pNumFonts)),
0,
0)
return HANDLE(ret)
}
func AlphaBlend(hdcDest HDC, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest int32, hdcSrc HDC, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc int32, ftn BLENDFUNCTION) bool { func AlphaBlend(hdcDest HDC, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest int32, hdcSrc HDC, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc int32, ftn BLENDFUNCTION) bool {
ret, _, _ := syscall.Syscall12(alphaBlend.Addr(), 11, ret, _, _ := syscall.Syscall12(alphaBlend.Addr(), 11,
uintptr(hdcDest), uintptr(hdcDest),
@ -1716,6 +1733,15 @@ func RemoveFontResourceEx(lpszFilename *uint16, fl uint32, pdv unsafe.Pointer) b
return ret != 0 return ret != 0
} }
func RemoveFontMemResourceEx(h HANDLE) bool {
ret, _, _ := syscall.Syscall(removeFontMemResourceEx.Addr(), 1,
uintptr(h),
0,
0)
return ret != 0
}
func ResetDC(hdc HDC, lpInitData *DEVMODE) HDC { func ResetDC(hdc HDC, lpInitData *DEVMODE) HDC {
ret, _, _ := syscall.Syscall(resetDC.Addr(), 2, ret, _, _ := syscall.Syscall(resetDC.Addr(), 2,
uintptr(hdc), uintptr(hdc),

3
vendor/github.com/lxn/win/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/lxn/win
go 1.12

View File

@ -30,7 +30,7 @@ const (
GMEM_FIXED = 0x0000 GMEM_FIXED = 0x0000
GMEM_MOVEABLE = 0x0002 GMEM_MOVEABLE = 0x0002
GMEM_ZEROINIT = 0x0040 GMEM_ZEROINIT = 0x0040
GPTR = 0x004 GPTR = GMEM_FIXED | GMEM_ZEROINIT
) )
// Predefined locale ids // Predefined locale ids
@ -62,8 +62,10 @@ var (
closeHandle *windows.LazyProc closeHandle *windows.LazyProc
createActCtx *windows.LazyProc createActCtx *windows.LazyProc
fileTimeToSystemTime *windows.LazyProc fileTimeToSystemTime *windows.LazyProc
findResource *windows.LazyProc
getConsoleTitle *windows.LazyProc getConsoleTitle *windows.LazyProc
getConsoleWindow *windows.LazyProc getConsoleWindow *windows.LazyProc
getCurrentThreadId *windows.LazyProc
getLastError *windows.LazyProc getLastError *windows.LazyProc
getLocaleInfo *windows.LazyProc getLocaleInfo *windows.LazyProc
getLogicalDriveStrings *windows.LazyProc getLogicalDriveStrings *windows.LazyProc
@ -80,7 +82,10 @@ var (
globalUnlock *windows.LazyProc globalUnlock *windows.LazyProc
moveMemory *windows.LazyProc moveMemory *windows.LazyProc
mulDiv *windows.LazyProc mulDiv *windows.LazyProc
loadResource *windows.LazyProc
lockResource *windows.LazyProc
setLastError *windows.LazyProc setLastError *windows.LazyProc
sizeofResource *windows.LazyProc
systemTimeToFileTime *windows.LazyProc systemTimeToFileTime *windows.LazyProc
) )
@ -94,6 +99,7 @@ type (
LANGID uint16 LANGID uint16
HMODULE uintptr HMODULE uintptr
HWINEVENTHOOK HANDLE HWINEVENTHOOK HANDLE
HRSRC uintptr
) )
type FILETIME struct { type FILETIME struct {
@ -142,8 +148,10 @@ func init() {
closeHandle = libkernel32.NewProc("CloseHandle") closeHandle = libkernel32.NewProc("CloseHandle")
createActCtx = libkernel32.NewProc("CreateActCtxW") createActCtx = libkernel32.NewProc("CreateActCtxW")
fileTimeToSystemTime = libkernel32.NewProc("FileTimeToSystemTime") fileTimeToSystemTime = libkernel32.NewProc("FileTimeToSystemTime")
findResource = libkernel32.NewProc("FindResourceW")
getConsoleTitle = libkernel32.NewProc("GetConsoleTitleW") getConsoleTitle = libkernel32.NewProc("GetConsoleTitleW")
getConsoleWindow = libkernel32.NewProc("GetConsoleWindow") getConsoleWindow = libkernel32.NewProc("GetConsoleWindow")
getCurrentThreadId = libkernel32.NewProc("GetCurrentThreadId")
getLastError = libkernel32.NewProc("GetLastError") getLastError = libkernel32.NewProc("GetLastError")
getLocaleInfo = libkernel32.NewProc("GetLocaleInfoW") getLocaleInfo = libkernel32.NewProc("GetLocaleInfoW")
getLogicalDriveStrings = libkernel32.NewProc("GetLogicalDriveStringsW") getLogicalDriveStrings = libkernel32.NewProc("GetLogicalDriveStringsW")
@ -160,7 +168,10 @@ func init() {
globalUnlock = libkernel32.NewProc("GlobalUnlock") globalUnlock = libkernel32.NewProc("GlobalUnlock")
moveMemory = libkernel32.NewProc("RtlMoveMemory") moveMemory = libkernel32.NewProc("RtlMoveMemory")
mulDiv = libkernel32.NewProc("MulDiv") mulDiv = libkernel32.NewProc("MulDiv")
loadResource = libkernel32.NewProc("LoadResource")
lockResource = libkernel32.NewProc("LockResource")
setLastError = libkernel32.NewProc("SetLastError") setLastError = libkernel32.NewProc("SetLastError")
sizeofResource = libkernel32.NewProc("SizeofResource")
systemTimeToFileTime = libkernel32.NewProc("SystemTimeToFileTime") systemTimeToFileTime = libkernel32.NewProc("SystemTimeToFileTime")
} }
@ -204,6 +215,15 @@ func FileTimeToSystemTime(lpFileTime *FILETIME, lpSystemTime *SYSTEMTIME) bool {
return ret != 0 return ret != 0
} }
func FindResource(hModule HMODULE, lpName, lpType *uint16) HRSRC {
ret, _, _ := syscall.Syscall(findResource.Addr(), 3,
uintptr(hModule),
uintptr(unsafe.Pointer(lpName)),
uintptr(unsafe.Pointer(lpType)))
return HRSRC(ret)
}
func GetConsoleTitle(lpConsoleTitle *uint16, nSize uint32) uint32 { func GetConsoleTitle(lpConsoleTitle *uint16, nSize uint32) uint32 {
ret, _, _ := syscall.Syscall(getConsoleTitle.Addr(), 2, ret, _, _ := syscall.Syscall(getConsoleTitle.Addr(), 2,
uintptr(unsafe.Pointer(lpConsoleTitle)), uintptr(unsafe.Pointer(lpConsoleTitle)),
@ -222,6 +242,15 @@ func GetConsoleWindow() HWND {
return HWND(ret) return HWND(ret)
} }
func GetCurrentThreadId() uint32 {
ret, _, _ := syscall.Syscall(getCurrentThreadId.Addr(), 0,
0,
0,
0)
return uint32(ret)
}
func GetLastError() uint32 { func GetLastError() uint32 {
ret, _, _ := syscall.Syscall(getLastError.Addr(), 0, ret, _, _ := syscall.Syscall(getLastError.Addr(), 0,
0, 0,
@ -318,12 +347,12 @@ func GetThreadUILanguage() LANGID {
return LANGID(ret) return LANGID(ret)
} }
func GetVersion() int64 { func GetVersion() uint32 {
ret, _, _ := syscall.Syscall(getVersion.Addr(), 0, ret, _, _ := syscall.Syscall(getVersion.Addr(), 0,
0, 0,
0, 0,
0) 0)
return int64(ret) return uint32(ret)
} }
func GlobalAlloc(uFlags uint32, dwBytes uintptr) HGLOBAL { func GlobalAlloc(uFlags uint32, dwBytes uintptr) HGLOBAL {
@ -378,6 +407,24 @@ func MulDiv(nNumber, nNumerator, nDenominator int32) int32 {
return int32(ret) return int32(ret)
} }
func LoadResource(hModule HMODULE, hResInfo HRSRC) HGLOBAL {
ret, _, _ := syscall.Syscall(loadResource.Addr(), 2,
uintptr(hModule),
uintptr(hResInfo),
0)
return HGLOBAL(ret)
}
func LockResource(hResData HGLOBAL) uintptr {
ret, _, _ := syscall.Syscall(lockResource.Addr(), 1,
uintptr(hResData),
0,
0)
return ret
}
func SetLastError(dwErrorCode uint32) { func SetLastError(dwErrorCode uint32) {
syscall.Syscall(setLastError.Addr(), 1, syscall.Syscall(setLastError.Addr(), 1,
uintptr(dwErrorCode), uintptr(dwErrorCode),
@ -385,6 +432,15 @@ func SetLastError(dwErrorCode uint32) {
0) 0)
} }
func SizeofResource(hModule HMODULE, hResInfo HRSRC) uint32 {
ret, _, _ := syscall.Syscall(sizeofResource.Addr(), 2,
uintptr(hModule),
uintptr(hResInfo),
0)
return uint32(ret)
}
func SystemTimeToFileTime(lpSystemTime *SYSTEMTIME, lpFileTime *FILETIME) bool { func SystemTimeToFileTime(lpSystemTime *SYSTEMTIME, lpFileTime *FILETIME) bool {
ret, _, _ := syscall.Syscall(systemTimeToFileTime.Addr(), 2, ret, _, _ := syscall.Syscall(systemTimeToFileTime.Addr(), 2,
uintptr(unsafe.Pointer(lpSystemTime)), uintptr(unsafe.Pointer(lpSystemTime)),

View File

@ -20,6 +20,7 @@ const (
// ListView messages // ListView messages
const ( const (
LVM_FIRST = 0x1000 LVM_FIRST = 0x1000
LVM_SETBKCOLOR = LVM_FIRST + 1
LVM_SETIMAGELIST = LVM_FIRST + 3 LVM_SETIMAGELIST = LVM_FIRST + 3
LVM_GETITEM = LVM_FIRST + 75 LVM_GETITEM = LVM_FIRST + 75
LVM_SETITEM = LVM_FIRST + 76 LVM_SETITEM = LVM_FIRST + 76

60
vendor/github.com/lxn/win/shell32.go generated vendored
View File

@ -82,11 +82,14 @@ const (
// NotifyIcon flags // NotifyIcon flags
const ( const (
NIF_MESSAGE = 0x00000001 NIF_MESSAGE = 0x00000001
NIF_ICON = 0x00000002 NIF_ICON = 0x00000002
NIF_TIP = 0x00000004 NIF_TIP = 0x00000004
NIF_STATE = 0x00000008 NIF_STATE = 0x00000008
NIF_INFO = 0x00000010 NIF_INFO = 0x00000010
NIF_GUID = 0x00000020
NIF_REALTIME = 0x00000040
NIF_SHOWTIP = 0x00000080
) )
// NotifyIcon messages // NotifyIcon messages
@ -106,15 +109,33 @@ const (
// NotifyIcon info flags // NotifyIcon info flags
const ( const (
NIIF_NONE = 0x00000000 NIIF_NONE = 0x00000000
NIIF_INFO = 0x00000001 NIIF_INFO = 0x00000001
NIIF_WARNING = 0x00000002 NIIF_WARNING = 0x00000002
NIIF_ERROR = 0x00000003 NIIF_ERROR = 0x00000003
NIIF_USER = 0x00000004 NIIF_USER = 0x00000004
NIIF_NOSOUND = 0x00000010 NIIF_NOSOUND = 0x00000010
NIIF_LARGE_ICON = 0x00000020
NIIF_RESPECT_QUIET_TIME = 0x00000080
) )
const NOTIFYICON_VERSION = 3 // NotifyIcon notifications
const (
NIN_SELECT = WM_USER + 0
NIN_KEYSELECT = WM_USER + 1
NIN_BALLOONSHOW = WM_USER + 2
NIN_BALLOONHIDE = WM_USER + 3
NIN_BALLOONTIMEOUT = WM_USER + 4
NIN_BALLOONUSERCLICK = WM_USER + 5
NIN_POPUPOPEN = WM_USER + 6
NIN_POPUPCLOSE = WM_USER + 7
)
// NotifyIcon versions
const (
NOTIFYICON_VERSION = 3
NOTIFYICON_VERSION_4 = 4
)
// SHGetFileInfo flags // SHGetFileInfo flags
const ( const (
@ -263,6 +284,7 @@ type NOTIFYICONDATA struct {
SzInfoTitle [64]uint16 SzInfoTitle [64]uint16
DwInfoFlags uint32 DwInfoFlags uint32
GuidItem syscall.GUID GuidItem syscall.GUID
HBalloonIcon HICON
} }
type SHFILEINFO struct { type SHFILEINFO struct {
@ -302,6 +324,7 @@ var (
dragQueryFile *windows.LazyProc dragQueryFile *windows.LazyProc
extractIcon *windows.LazyProc extractIcon *windows.LazyProc
shBrowseForFolder *windows.LazyProc shBrowseForFolder *windows.LazyProc
shDefExtractIcon *windows.LazyProc
shGetFileInfo *windows.LazyProc shGetFileInfo *windows.LazyProc
shGetPathFromIDList *windows.LazyProc shGetPathFromIDList *windows.LazyProc
shGetSpecialFolderPath *windows.LazyProc shGetSpecialFolderPath *windows.LazyProc
@ -321,6 +344,7 @@ func init() {
dragQueryFile = libshell32.NewProc("DragQueryFileW") dragQueryFile = libshell32.NewProc("DragQueryFileW")
extractIcon = libshell32.NewProc("ExtractIconW") extractIcon = libshell32.NewProc("ExtractIconW")
shBrowseForFolder = libshell32.NewProc("SHBrowseForFolderW") shBrowseForFolder = libshell32.NewProc("SHBrowseForFolderW")
shDefExtractIcon = libshell32.NewProc("SHDefExtractIconW")
shGetFileInfo = libshell32.NewProc("SHGetFileInfoW") shGetFileInfo = libshell32.NewProc("SHGetFileInfoW")
shGetPathFromIDList = libshell32.NewProc("SHGetPathFromIDListW") shGetPathFromIDList = libshell32.NewProc("SHGetPathFromIDListW")
shGetSpecialFolderPath = libshell32.NewProc("SHGetSpecialFolderPathW") shGetSpecialFolderPath = libshell32.NewProc("SHGetSpecialFolderPathW")
@ -376,6 +400,18 @@ func SHBrowseForFolder(lpbi *BROWSEINFO) uintptr {
return ret return ret
} }
func SHDefExtractIcon(pszIconFile *uint16, iIndex int32, uFlags uint32, phiconLarge, phiconSmall *HICON, nIconSize uint32) HRESULT {
ret, _, _ := syscall.Syscall6(shDefExtractIcon.Addr(), 6,
uintptr(unsafe.Pointer(pszIconFile)),
uintptr(iIndex),
uintptr(uFlags),
uintptr(unsafe.Pointer(phiconLarge)),
uintptr(unsafe.Pointer(phiconSmall)),
uintptr(nIconSize))
return HRESULT(ret)
}
func SHGetFileInfo(pszPath *uint16, dwFileAttributes uint32, psfi *SHFILEINFO, cbFileInfo, uFlags uint32) uintptr { func SHGetFileInfo(pszPath *uint16, dwFileAttributes uint32, psfi *SHFILEINFO, cbFileInfo, uFlags uint32) uintptr {
ret, _, _ := syscall.Syscall6(shGetFileInfo.Addr(), 5, ret, _, _ := syscall.Syscall6(shGetFileInfo.Addr(), 5,
uintptr(unsafe.Pointer(pszPath)), uintptr(unsafe.Pointer(pszPath)),

11
vendor/github.com/lxn/win/shobj.go generated vendored
View File

@ -60,3 +60,14 @@ func (obj *ITaskbarList3) SetProgressState(hwnd HWND, state int) HRESULT {
uintptr(state)) uintptr(state))
return HRESULT(ret) return HRESULT(ret)
} }
func (obj *ITaskbarList3) SetOverlayIcon(hwnd HWND, icon HICON, description *uint16) HRESULT {
ret, _, _ := syscall.Syscall6(obj.LpVtbl.SetOverlayIcon, 4,
uintptr(unsafe.Pointer(obj)),
uintptr(hwnd),
uintptr(icon),
uintptr(unsafe.Pointer(description)),
0,
0)
return HRESULT(ret)
}

423
vendor/github.com/lxn/win/user32.go generated vendored
View File

@ -1026,6 +1026,7 @@ const (
// SystemParametersInfo actions // SystemParametersInfo actions
const ( const (
SPI_GETNONCLIENTMETRICS = 0x0029 SPI_GETNONCLIENTMETRICS = 0x0029
SPI_GETHIGHCONTRAST = 0x0042
) )
// Dialog styles // Dialog styles
@ -1070,6 +1071,13 @@ const (
WA_INACTIVE = 0 WA_INACTIVE = 0
) )
// Owner drawing actions
const (
ODA_DRAWENTIRE = 0x0001
ODA_FOCUS = 0x0002
ODA_SELECT = 0x0004
)
// Owner drawing states // Owner drawing states
const ( const (
ODS_CHECKED = 0x0001 ODS_CHECKED = 0x0001
@ -1327,6 +1335,52 @@ const (
AW_VER_NEGATIVE = 0x00000008 AW_VER_NEGATIVE = 0x00000008
) )
// Session ending constants
const (
ENDSESSION_CLOSEAPP = 0x00000001
ENDSESSION_CRITICAL = 0x40000000
ENDSESSION_LOGOFF = 0x80000000
)
// ChangeWindowMessageFilterEx constants
const (
MSGFLT_RESET = 0
MSGFLT_ALLOW = 1
MSGFLT_DISALLOW = 2
MSGFLTINFO_NONE = 0
MSGFLTINFO_ALREADYALLOWED_FORWND = 1
MSGFLTINFO_ALREADYDISALLOWED_FORWND = 2
MSGFLTINFO_ALLOWED_HIGHER = 3
)
// TRACKMOUSEEVENT flags
const (
TME_CANCEL = 0x80000000
TME_HOVER = 0x00000001
TME_LEAVE = 0x00000002
TME_NONCLIENT = 0x00000010
TME_QUERY = 0x40000000
)
// HIGHCONTRAST flags
const (
HCF_HIGHCONTRASTON = 0x00000001
HCF_AVAILABLE = 0x00000002
HCF_HOTKEYACTIVE = 0x00000004
HCF_CONFIRMHOTKEY = 0x00000008
HCF_HOTKEYSOUND = 0x00000010
HCF_INDICATOR = 0x00000020
HCF_HOTKEYAVAILABLE = 0x00000040
)
// EDITWORDBREAKPROC codes
const (
WB_LEFT = 0
WB_RIGHT = 1
WB_ISDELIMITER = 2
)
type NMBCDROPDOWN struct { type NMBCDROPDOWN struct {
Hdr NMHDR Hdr NMHDR
RcButton RECT RcButton RECT
@ -1434,6 +1488,11 @@ type CREATESTRUCT struct {
ExStyle uint32 ExStyle uint32
} }
type CHANGEFILTERSTRUCT struct {
size uint32
extStatus uint32
}
type WNDCLASSEX struct { type WNDCLASSEX struct {
CbSize uint32 CbSize uint32
Style uint32 Style uint32
@ -1595,6 +1654,19 @@ type WINDOWPOS struct {
Flags uint32 Flags uint32
} }
type TRACKMOUSEEVENT struct {
CbSize uint32
DwFlags uint32
HwndTrack HWND
DwHoverTime uint32
}
type HIGHCONTRAST struct {
CbSize uint32
DwFlags uint32
LpszDefaultScheme *uint16
}
func GET_X_LPARAM(lp uintptr) int32 { func GET_X_LPARAM(lp uintptr) int32 {
return int32(int16(LOWORD(uint32(lp)))) return int32(int16(LOWORD(uint32(lp))))
} }
@ -1608,126 +1680,136 @@ var (
libuser32 *windows.LazyDLL libuser32 *windows.LazyDLL
// Functions // Functions
addClipboardFormatListener *windows.LazyProc addClipboardFormatListener *windows.LazyProc
adjustWindowRect *windows.LazyProc adjustWindowRect *windows.LazyProc
animateWindow *windows.LazyProc attachThreadInput *windows.LazyProc
beginDeferWindowPos *windows.LazyProc animateWindow *windows.LazyProc
beginPaint *windows.LazyProc beginDeferWindowPos *windows.LazyProc
bringWindowToTop *windows.LazyProc beginPaint *windows.LazyProc
callWindowProc *windows.LazyProc bringWindowToTop *windows.LazyProc
checkMenuRadioItem *windows.LazyProc callWindowProc *windows.LazyProc
clientToScreen *windows.LazyProc changeWindowMessageFilterEx *windows.LazyProc
closeClipboard *windows.LazyProc checkMenuRadioItem *windows.LazyProc
createDialogParam *windows.LazyProc clientToScreen *windows.LazyProc
createIconIndirect *windows.LazyProc closeClipboard *windows.LazyProc
createMenu *windows.LazyProc createDialogParam *windows.LazyProc
createPopupMenu *windows.LazyProc createIconIndirect *windows.LazyProc
createWindowEx *windows.LazyProc createMenu *windows.LazyProc
deferWindowPos *windows.LazyProc createPopupMenu *windows.LazyProc
defWindowProc *windows.LazyProc createWindowEx *windows.LazyProc
destroyIcon *windows.LazyProc deferWindowPos *windows.LazyProc
destroyMenu *windows.LazyProc defWindowProc *windows.LazyProc
destroyWindow *windows.LazyProc destroyIcon *windows.LazyProc
dialogBoxParam *windows.LazyProc destroyMenu *windows.LazyProc
dispatchMessage *windows.LazyProc destroyWindow *windows.LazyProc
drawIconEx *windows.LazyProc dialogBoxParam *windows.LazyProc
drawMenuBar *windows.LazyProc dispatchMessage *windows.LazyProc
drawFocusRect *windows.LazyProc drawIconEx *windows.LazyProc
drawTextEx *windows.LazyProc drawMenuBar *windows.LazyProc
emptyClipboard *windows.LazyProc drawFocusRect *windows.LazyProc
enableWindow *windows.LazyProc drawTextEx *windows.LazyProc
endDeferWindowPos *windows.LazyProc emptyClipboard *windows.LazyProc
endDialog *windows.LazyProc enableWindow *windows.LazyProc
endPaint *windows.LazyProc endDeferWindowPos *windows.LazyProc
enumChildWindows *windows.LazyProc endDialog *windows.LazyProc
findWindow *windows.LazyProc endPaint *windows.LazyProc
getActiveWindow *windows.LazyProc enumChildWindows *windows.LazyProc
getAncestor *windows.LazyProc findWindow *windows.LazyProc
getCaretPos *windows.LazyProc getActiveWindow *windows.LazyProc
getClassName *windows.LazyProc getAncestor *windows.LazyProc
getClientRect *windows.LazyProc getCaretPos *windows.LazyProc
getClipboardData *windows.LazyProc getClassName *windows.LazyProc
getCursorPos *windows.LazyProc getClientRect *windows.LazyProc
getDC *windows.LazyProc getClipboardData *windows.LazyProc
getDesktopWindow *windows.LazyProc getCursorPos *windows.LazyProc
getDpiForWindow *windows.LazyProc getDC *windows.LazyProc
getFocus *windows.LazyProc getDesktopWindow *windows.LazyProc
getForegroundWindow *windows.LazyProc getDlgItem *windows.LazyProc
getKeyState *windows.LazyProc getDpiForWindow *windows.LazyProc
getMenuInfo *windows.LazyProc getFocus *windows.LazyProc
getMessage *windows.LazyProc getForegroundWindow *windows.LazyProc
getMonitorInfo *windows.LazyProc getIconInfo *windows.LazyProc
getParent *windows.LazyProc getKeyState *windows.LazyProc
getRawInputData *windows.LazyProc getMenuInfo *windows.LazyProc
getScrollInfo *windows.LazyProc getMessage *windows.LazyProc
getSysColor *windows.LazyProc getMonitorInfo *windows.LazyProc
getSysColorBrush *windows.LazyProc getParent *windows.LazyProc
getSystemMetrics *windows.LazyProc getRawInputData *windows.LazyProc
getSystemMetricsForDpi *windows.LazyProc getScrollInfo *windows.LazyProc
getWindow *windows.LazyProc getSysColor *windows.LazyProc
getWindowLong *windows.LazyProc getSysColorBrush *windows.LazyProc
getWindowLongPtr *windows.LazyProc getSystemMenu *windows.LazyProc
getWindowPlacement *windows.LazyProc getSystemMetrics *windows.LazyProc
getWindowRect *windows.LazyProc getSystemMetricsForDpi *windows.LazyProc
insertMenuItem *windows.LazyProc getWindow *windows.LazyProc
invalidateRect *windows.LazyProc getWindowLong *windows.LazyProc
isChild *windows.LazyProc getWindowLongPtr *windows.LazyProc
isClipboardFormatAvailable *windows.LazyProc getWindowPlacement *windows.LazyProc
isDialogMessage *windows.LazyProc getWindowRect *windows.LazyProc
isWindowEnabled *windows.LazyProc getWindowThreadProcessId *windows.LazyProc
isWindowVisible *windows.LazyProc insertMenuItem *windows.LazyProc
killTimer *windows.LazyProc invalidateRect *windows.LazyProc
loadCursor *windows.LazyProc isChild *windows.LazyProc
loadIcon *windows.LazyProc isClipboardFormatAvailable *windows.LazyProc
loadImage *windows.LazyProc isDialogMessage *windows.LazyProc
loadMenu *windows.LazyProc isIconic *windows.LazyProc
loadString *windows.LazyProc isWindowEnabled *windows.LazyProc
messageBeep *windows.LazyProc isWindowVisible *windows.LazyProc
messageBox *windows.LazyProc isZoomed *windows.LazyProc
monitorFromWindow *windows.LazyProc killTimer *windows.LazyProc
moveWindow *windows.LazyProc loadCursor *windows.LazyProc
unregisterClass *windows.LazyProc loadIcon *windows.LazyProc
openClipboard *windows.LazyProc loadImage *windows.LazyProc
peekMessage *windows.LazyProc loadMenu *windows.LazyProc
postMessage *windows.LazyProc loadString *windows.LazyProc
postQuitMessage *windows.LazyProc messageBeep *windows.LazyProc
registerClassEx *windows.LazyProc messageBox *windows.LazyProc
registerRawInputDevices *windows.LazyProc monitorFromWindow *windows.LazyProc
registerWindowMessage *windows.LazyProc moveWindow *windows.LazyProc
releaseCapture *windows.LazyProc unregisterClass *windows.LazyProc
releaseDC *windows.LazyProc openClipboard *windows.LazyProc
removeMenu *windows.LazyProc peekMessage *windows.LazyProc
screenToClient *windows.LazyProc postMessage *windows.LazyProc
sendDlgItemMessage *windows.LazyProc postQuitMessage *windows.LazyProc
sendInput *windows.LazyProc registerClassEx *windows.LazyProc
sendMessage *windows.LazyProc registerRawInputDevices *windows.LazyProc
setActiveWindow *windows.LazyProc registerWindowMessage *windows.LazyProc
setCapture *windows.LazyProc releaseCapture *windows.LazyProc
setClipboardData *windows.LazyProc releaseDC *windows.LazyProc
setCursor *windows.LazyProc removeMenu *windows.LazyProc
setCursorPos *windows.LazyProc screenToClient *windows.LazyProc
setFocus *windows.LazyProc sendDlgItemMessage *windows.LazyProc
setForegroundWindow *windows.LazyProc sendInput *windows.LazyProc
setMenu *windows.LazyProc sendMessage *windows.LazyProc
setMenuInfo *windows.LazyProc setActiveWindow *windows.LazyProc
setMenuItemInfo *windows.LazyProc setCapture *windows.LazyProc
setParent *windows.LazyProc setClipboardData *windows.LazyProc
setRect *windows.LazyProc setCursor *windows.LazyProc
setScrollInfo *windows.LazyProc setCursorPos *windows.LazyProc
setTimer *windows.LazyProc setFocus *windows.LazyProc
setWinEventHook *windows.LazyProc setForegroundWindow *windows.LazyProc
setWindowLong *windows.LazyProc setMenu *windows.LazyProc
setWindowLongPtr *windows.LazyProc setMenuDefaultItem *windows.LazyProc
setWindowPlacement *windows.LazyProc setMenuInfo *windows.LazyProc
setWindowPos *windows.LazyProc setMenuItemInfo *windows.LazyProc
showWindow *windows.LazyProc setParent *windows.LazyProc
systemParametersInfo *windows.LazyProc setRect *windows.LazyProc
trackPopupMenuEx *windows.LazyProc setScrollInfo *windows.LazyProc
translateMessage *windows.LazyProc setTimer *windows.LazyProc
unhookWinEvent *windows.LazyProc setWinEventHook *windows.LazyProc
updateWindow *windows.LazyProc setWindowLong *windows.LazyProc
windowFromDC *windows.LazyProc setWindowLongPtr *windows.LazyProc
windowFromPoint *windows.LazyProc setWindowPlacement *windows.LazyProc
setWindowPos *windows.LazyProc
showWindow *windows.LazyProc
systemParametersInfo *windows.LazyProc
trackMouseEvent *windows.LazyProc
trackPopupMenuEx *windows.LazyProc
translateMessage *windows.LazyProc
unhookWinEvent *windows.LazyProc
updateWindow *windows.LazyProc
windowFromDC *windows.LazyProc
windowFromPoint *windows.LazyProc
) )
func init() { func init() {
@ -1739,11 +1821,13 @@ func init() {
// Functions // Functions
addClipboardFormatListener = libuser32.NewProc("AddClipboardFormatListener") addClipboardFormatListener = libuser32.NewProc("AddClipboardFormatListener")
adjustWindowRect = libuser32.NewProc("AdjustWindowRect") adjustWindowRect = libuser32.NewProc("AdjustWindowRect")
attachThreadInput = libuser32.NewProc("AttachThreadInput")
animateWindow = libuser32.NewProc("AnimateWindow") animateWindow = libuser32.NewProc("AnimateWindow")
beginDeferWindowPos = libuser32.NewProc("BeginDeferWindowPos") beginDeferWindowPos = libuser32.NewProc("BeginDeferWindowPos")
beginPaint = libuser32.NewProc("BeginPaint") beginPaint = libuser32.NewProc("BeginPaint")
bringWindowToTop = libuser32.NewProc("BringWindowToTop") bringWindowToTop = libuser32.NewProc("BringWindowToTop")
callWindowProc = libuser32.NewProc("CallWindowProcW") callWindowProc = libuser32.NewProc("CallWindowProcW")
changeWindowMessageFilterEx = libuser32.NewProc("ChangeWindowMessageFilterEx")
checkMenuRadioItem = libuser32.NewProc("CheckMenuRadioItem") checkMenuRadioItem = libuser32.NewProc("CheckMenuRadioItem")
clientToScreen = libuser32.NewProc("ClientToScreen") clientToScreen = libuser32.NewProc("ClientToScreen")
closeClipboard = libuser32.NewProc("CloseClipboard") closeClipboard = libuser32.NewProc("CloseClipboard")
@ -1779,9 +1863,11 @@ func init() {
getCursorPos = libuser32.NewProc("GetCursorPos") getCursorPos = libuser32.NewProc("GetCursorPos")
getDC = libuser32.NewProc("GetDC") getDC = libuser32.NewProc("GetDC")
getDesktopWindow = libuser32.NewProc("GetDesktopWindow") getDesktopWindow = libuser32.NewProc("GetDesktopWindow")
getDlgItem = libuser32.NewProc("GetDlgItem")
getDpiForWindow = libuser32.NewProc("GetDpiForWindow") getDpiForWindow = libuser32.NewProc("GetDpiForWindow")
getFocus = libuser32.NewProc("GetFocus") getFocus = libuser32.NewProc("GetFocus")
getForegroundWindow = libuser32.NewProc("GetForegroundWindow") getForegroundWindow = libuser32.NewProc("GetForegroundWindow")
getIconInfo = libuser32.NewProc("GetIconInfo")
getKeyState = libuser32.NewProc("GetKeyState") getKeyState = libuser32.NewProc("GetKeyState")
getMenuInfo = libuser32.NewProc("GetMenuInfo") getMenuInfo = libuser32.NewProc("GetMenuInfo")
getMessage = libuser32.NewProc("GetMessageW") getMessage = libuser32.NewProc("GetMessageW")
@ -1791,6 +1877,7 @@ func init() {
getScrollInfo = libuser32.NewProc("GetScrollInfo") getScrollInfo = libuser32.NewProc("GetScrollInfo")
getSysColor = libuser32.NewProc("GetSysColor") getSysColor = libuser32.NewProc("GetSysColor")
getSysColorBrush = libuser32.NewProc("GetSysColorBrush") getSysColorBrush = libuser32.NewProc("GetSysColorBrush")
getSystemMenu = libuser32.NewProc("GetSystemMenu")
getSystemMetrics = libuser32.NewProc("GetSystemMetrics") getSystemMetrics = libuser32.NewProc("GetSystemMetrics")
getSystemMetricsForDpi = libuser32.NewProc("GetSystemMetricsForDpi") getSystemMetricsForDpi = libuser32.NewProc("GetSystemMetricsForDpi")
getWindow = libuser32.NewProc("GetWindow") getWindow = libuser32.NewProc("GetWindow")
@ -1803,13 +1890,16 @@ func init() {
} }
getWindowPlacement = libuser32.NewProc("GetWindowPlacement") getWindowPlacement = libuser32.NewProc("GetWindowPlacement")
getWindowRect = libuser32.NewProc("GetWindowRect") getWindowRect = libuser32.NewProc("GetWindowRect")
getWindowThreadProcessId = libuser32.NewProc("GetWindowThreadProcessId")
insertMenuItem = libuser32.NewProc("InsertMenuItemW") insertMenuItem = libuser32.NewProc("InsertMenuItemW")
invalidateRect = libuser32.NewProc("InvalidateRect") invalidateRect = libuser32.NewProc("InvalidateRect")
isChild = libuser32.NewProc("IsChild") isChild = libuser32.NewProc("IsChild")
isClipboardFormatAvailable = libuser32.NewProc("IsClipboardFormatAvailable") isClipboardFormatAvailable = libuser32.NewProc("IsClipboardFormatAvailable")
isDialogMessage = libuser32.NewProc("IsDialogMessageW") isDialogMessage = libuser32.NewProc("IsDialogMessageW")
isIconic = libuser32.NewProc("IsIconic")
isWindowEnabled = libuser32.NewProc("IsWindowEnabled") isWindowEnabled = libuser32.NewProc("IsWindowEnabled")
isWindowVisible = libuser32.NewProc("IsWindowVisible") isWindowVisible = libuser32.NewProc("IsWindowVisible")
isZoomed = libuser32.NewProc("IsZoomed")
killTimer = libuser32.NewProc("KillTimer") killTimer = libuser32.NewProc("KillTimer")
loadCursor = libuser32.NewProc("LoadCursorW") loadCursor = libuser32.NewProc("LoadCursorW")
loadIcon = libuser32.NewProc("LoadIconW") loadIcon = libuser32.NewProc("LoadIconW")
@ -1843,6 +1933,7 @@ func init() {
setFocus = libuser32.NewProc("SetFocus") setFocus = libuser32.NewProc("SetFocus")
setForegroundWindow = libuser32.NewProc("SetForegroundWindow") setForegroundWindow = libuser32.NewProc("SetForegroundWindow")
setMenu = libuser32.NewProc("SetMenu") setMenu = libuser32.NewProc("SetMenu")
setMenuDefaultItem = libuser32.NewProc("SetMenuDefaultItem")
setMenuInfo = libuser32.NewProc("SetMenuInfo") setMenuInfo = libuser32.NewProc("SetMenuInfo")
setMenuItemInfo = libuser32.NewProc("SetMenuItemInfoW") setMenuItemInfo = libuser32.NewProc("SetMenuItemInfoW")
setRect = libuser32.NewProc("SetRect") setRect = libuser32.NewProc("SetRect")
@ -1861,6 +1952,7 @@ func init() {
setWindowPos = libuser32.NewProc("SetWindowPos") setWindowPos = libuser32.NewProc("SetWindowPos")
showWindow = libuser32.NewProc("ShowWindow") showWindow = libuser32.NewProc("ShowWindow")
systemParametersInfo = libuser32.NewProc("SystemParametersInfoW") systemParametersInfo = libuser32.NewProc("SystemParametersInfoW")
trackMouseEvent = libuser32.NewProc("TrackMouseEvent")
trackPopupMenuEx = libuser32.NewProc("TrackPopupMenuEx") trackPopupMenuEx = libuser32.NewProc("TrackPopupMenuEx")
translateMessage = libuser32.NewProc("TranslateMessage") translateMessage = libuser32.NewProc("TranslateMessage")
unhookWinEvent = libuser32.NewProc("UnhookWinEvent") unhookWinEvent = libuser32.NewProc("UnhookWinEvent")
@ -1891,6 +1983,15 @@ func AdjustWindowRect(lpRect *RECT, dwStyle uint32, bMenu bool) bool {
return ret != 0 return ret != 0
} }
func AttachThreadInput(idAttach int32, idAttachTo int32, fAttach bool) bool {
ret, _, _ := syscall.Syscall(attachThreadInput.Addr(), 3,
uintptr(idAttach),
uintptr(idAttachTo),
uintptr(BoolToBOOL(fAttach)))
return ret != 0
}
func AnimateWindow(hwnd HWND, dwTime, dwFlags uint32) bool { func AnimateWindow(hwnd HWND, dwTime, dwFlags uint32) bool {
ret, _, _ := syscall.Syscall(animateWindow.Addr(), 3, ret, _, _ := syscall.Syscall(animateWindow.Addr(), 3,
uintptr(hwnd), uintptr(hwnd),
@ -1909,6 +2010,15 @@ func BeginDeferWindowPos(nNumWindows int32) HDWP {
return HDWP(ret) return HDWP(ret)
} }
func GetWindowThreadProcessId(hwnd HWND, processId *uint32) uint32 {
ret, _, _ := syscall.Syscall(getWindowThreadProcessId.Addr(), 2,
uintptr(hwnd),
uintptr(unsafe.Pointer(processId)),
0)
return uint32(ret)
}
func BeginPaint(hwnd HWND, lpPaint *PAINTSTRUCT) HDC { func BeginPaint(hwnd HWND, lpPaint *PAINTSTRUCT) HDC {
ret, _, _ := syscall.Syscall(beginPaint.Addr(), 2, ret, _, _ := syscall.Syscall(beginPaint.Addr(), 2,
uintptr(hwnd), uintptr(hwnd),
@ -1938,6 +2048,17 @@ func CallWindowProc(lpPrevWndFunc uintptr, hWnd HWND, Msg uint32, wParam, lParam
return ret return ret
} }
func ChangeWindowMessageFilterEx(hwnd HWND, msg uint32, action uint32, changeFilterStruct *CHANGEFILTERSTRUCT) bool {
ret, _, _ := syscall.Syscall6(changeWindowMessageFilterEx.Addr(), 4,
uintptr(hwnd),
uintptr(msg),
uintptr(action),
uintptr(unsafe.Pointer(changeFilterStruct)),
0,
0)
return ret != 0
}
func CheckMenuRadioItem(hmenu HMENU, first, last, check, flags uint32) bool { func CheckMenuRadioItem(hmenu HMENU, first, last, check, flags uint32) bool {
ret, _, _ := syscall.Syscall6(checkMenuRadioItem.Addr(), 5, ret, _, _ := syscall.Syscall6(checkMenuRadioItem.Addr(), 5,
uintptr(hmenu), uintptr(hmenu),
@ -2292,6 +2413,15 @@ func GetDC(hWnd HWND) HDC {
return HDC(ret) return HDC(ret)
} }
func GetDlgItem(hDlg HWND, nIDDlgItem int32) HWND {
ret, _, _ := syscall.Syscall(getDlgItem.Addr(), 2,
uintptr(hDlg),
uintptr(nIDDlgItem),
0)
return HWND(ret)
}
func GetDpiForWindow(hwnd HWND) uint32 { func GetDpiForWindow(hwnd HWND) uint32 {
if getDpiForWindow.Find() != nil { if getDpiForWindow.Find() != nil {
hdc := GetDC(hwnd) hdc := GetDC(hwnd)
@ -2326,6 +2456,15 @@ func GetForegroundWindow() HWND {
return HWND(ret) return HWND(ret)
} }
func GetIconInfo(hicon HICON, piconinfo *ICONINFO) bool {
ret, _, _ := syscall.Syscall(getIconInfo.Addr(), 2,
uintptr(hicon),
uintptr(unsafe.Pointer(piconinfo)),
0)
return ret != 0
}
func GetKeyState(nVirtKey int32) int16 { func GetKeyState(nVirtKey int32) int16 {
ret, _, _ := syscall.Syscall(getKeyState.Addr(), 1, ret, _, _ := syscall.Syscall(getKeyState.Addr(), 1,
uintptr(nVirtKey), uintptr(nVirtKey),
@ -2413,6 +2552,14 @@ func GetSysColorBrush(nIndex int) HBRUSH {
return HBRUSH(ret) return HBRUSH(ret)
} }
func GetSystemMenu(hWnd HWND, revert bool) HMENU {
ret, _, _ := syscall.Syscall(getSystemMenu.Addr(), 2,
uintptr(hWnd),
uintptr(BoolToBOOL(revert)),
0)
return HMENU(ret)
}
func GetSystemMetrics(nIndex int32) int32 { func GetSystemMetrics(nIndex int32) int32 {
ret, _, _ := syscall.Syscall(getSystemMetrics.Addr(), 1, ret, _, _ := syscall.Syscall(getSystemMetrics.Addr(), 1,
uintptr(nIndex), uintptr(nIndex),
@ -2528,6 +2675,15 @@ func IsDialogMessage(hWnd HWND, msg *MSG) bool {
return ret != 0 return ret != 0
} }
func IsIconic(hWnd HWND) bool {
ret, _, _ := syscall.Syscall(isIconic.Addr(), 1,
uintptr(hWnd),
0,
0)
return ret != 0
}
func IsWindowEnabled(hWnd HWND) bool { func IsWindowEnabled(hWnd HWND) bool {
ret, _, _ := syscall.Syscall(isWindowEnabled.Addr(), 1, ret, _, _ := syscall.Syscall(isWindowEnabled.Addr(), 1,
uintptr(hWnd), uintptr(hWnd),
@ -2546,6 +2702,15 @@ func IsWindowVisible(hWnd HWND) bool {
return ret != 0 return ret != 0
} }
func IsZoomed(hWnd HWND) bool {
ret, _, _ := syscall.Syscall(isZoomed.Addr(), 1,
uintptr(hWnd),
0,
0)
return ret != 0
}
func KillTimer(hWnd HWND, uIDEvent uintptr) bool { func KillTimer(hWnd HWND, uIDEvent uintptr) bool {
ret, _, _ := syscall.Syscall(killTimer.Addr(), 2, ret, _, _ := syscall.Syscall(killTimer.Addr(), 2,
uintptr(hWnd), uintptr(hWnd),
@ -2880,6 +3045,15 @@ func SetMenu(hWnd HWND, hMenu HMENU) bool {
return ret != 0 return ret != 0
} }
func SetMenuDefaultItem(hMenu HMENU, uItem uint32, fByPosition bool) bool {
ret, _, _ := syscall.Syscall(setMenuDefaultItem.Addr(), 3,
uintptr(hMenu),
uintptr(uItem),
uintptr(BoolToBOOL(fByPosition)))
return ret != 0
}
func SetMenuInfo(hmenu HMENU, lpcmi *MENUINFO) bool { func SetMenuInfo(hmenu HMENU, lpcmi *MENUINFO) bool {
ret, _, _ := syscall.Syscall(setMenuInfo.Addr(), 2, ret, _, _ := syscall.Syscall(setMenuInfo.Addr(), 2,
uintptr(hmenu), uintptr(hmenu),
@ -3029,6 +3203,15 @@ func SystemParametersInfo(uiAction, uiParam uint32, pvParam unsafe.Pointer, fWin
return ret != 0 return ret != 0
} }
func TrackMouseEvent(lpEventTrack *TRACKMOUSEEVENT) bool {
ret, _, _ := syscall.Syscall(trackMouseEvent.Addr(), 1,
uintptr(unsafe.Pointer(lpEventTrack)),
0,
0)
return ret != 0
}
func TrackPopupMenuEx(hMenu HMENU, fuFlags uint32, x, y int32, hWnd HWND, lptpm *TPMPARAMS) BOOL { func TrackPopupMenuEx(hMenu HMENU, fuFlags uint32, x, y int32, hWnd HWND, lptpm *TPMPARAMS) BOOL {
ret, _, _ := syscall.Syscall6(trackPopupMenuEx.Addr(), 6, ret, _, _ := syscall.Syscall6(trackPopupMenuEx.Addr(), 6,
uintptr(hMenu), uintptr(hMenu),

36
vendor/github.com/lxn/win/uxtheme.go generated vendored
View File

@ -7,9 +7,16 @@
package win package win
import ( import (
"golang.org/x/sys/windows"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/sys/windows"
)
// TMT_COLOR property ids
const (
TMT_FILLCOLOR = 3802
TMT_TEXTCOLOR = 3803
) )
// CheckBox parts // CheckBox parts
@ -22,6 +29,19 @@ const (
CBS_UNCHECKEDNORMAL = 1 CBS_UNCHECKEDNORMAL = 1
) )
// ListBox parts
const (
LBCP_ITEM = 5
)
// LBCP_ITEM states
const (
LBPSI_HOT = 1
LBPSI_HOTSELECTED = 2
LBPSI_SELECTED = 3
LBPSI_SELECTEDNOTFOCUS = 4
)
// LISTVIEW parts // LISTVIEW parts
const ( const (
LVP_LISTITEM = 1 LVP_LISTITEM = 1
@ -145,6 +165,7 @@ var (
closeThemeData *windows.LazyProc closeThemeData *windows.LazyProc
drawThemeBackground *windows.LazyProc drawThemeBackground *windows.LazyProc
drawThemeTextEx *windows.LazyProc drawThemeTextEx *windows.LazyProc
getThemeColor *windows.LazyProc
getThemePartSize *windows.LazyProc getThemePartSize *windows.LazyProc
getThemeTextExtent *windows.LazyProc getThemeTextExtent *windows.LazyProc
isAppThemed *windows.LazyProc isAppThemed *windows.LazyProc
@ -160,6 +181,7 @@ func init() {
closeThemeData = libuxtheme.NewProc("CloseThemeData") closeThemeData = libuxtheme.NewProc("CloseThemeData")
drawThemeBackground = libuxtheme.NewProc("DrawThemeBackground") drawThemeBackground = libuxtheme.NewProc("DrawThemeBackground")
drawThemeTextEx = libuxtheme.NewProc("DrawThemeTextEx") drawThemeTextEx = libuxtheme.NewProc("DrawThemeTextEx")
getThemeColor = libuxtheme.NewProc("GetThemeColor")
getThemePartSize = libuxtheme.NewProc("GetThemePartSize") getThemePartSize = libuxtheme.NewProc("GetThemePartSize")
getThemeTextExtent = libuxtheme.NewProc("GetThemeTextExtent") getThemeTextExtent = libuxtheme.NewProc("GetThemeTextExtent")
isAppThemed = libuxtheme.NewProc("IsAppThemed") isAppThemed = libuxtheme.NewProc("IsAppThemed")
@ -206,6 +228,18 @@ func DrawThemeTextEx(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pszText *u
return HRESULT(ret) return HRESULT(ret)
} }
func GetThemeColor(hTheme HTHEME, iPartId, iStateId, iPropId int32, pColor *COLORREF) HRESULT {
ret, _, _ := syscall.Syscall6(getThemeColor.Addr(), 5,
uintptr(hTheme),
uintptr(iPartId),
uintptr(iStateId),
uintptr(iPropId),
uintptr(unsafe.Pointer(pColor)),
0)
return HRESULT(ret)
}
func GetThemePartSize(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, prc *RECT, eSize THEMESIZE, psz *SIZE) HRESULT { func GetThemePartSize(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, prc *RECT, eSize THEMESIZE, psz *SIZE) HRESULT {
ret, _, _ := syscall.Syscall9(getThemePartSize.Addr(), 7, ret, _, _ := syscall.Syscall9(getThemePartSize.Addr(), 7,
uintptr(hTheme), uintptr(hTheme),

5
vendor/github.com/lxn/win/win.go generated vendored
View File

@ -7,15 +7,10 @@
package win package win
import ( import (
"runtime"
"syscall" "syscall"
"unsafe" "unsafe"
) )
func init() {
runtime.LockOSThread()
}
const ( const (
S_OK = 0x00000000 S_OK = 0x00000000
S_FALSE = 0x00000001 S_FALSE = 0x00000001

View File

@ -20,7 +20,7 @@ func main() {
defer hook.End() defer hook.End()
for ev := range EvChan { for ev := range EvChan {
fmt.Println(ev) fmt.Println("hook: ", ev)
} }
} }
``` ```

View File

@ -34,7 +34,7 @@ environment:
PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH%
# - COMPILER: MINGW_W64 # - COMPILER: MINGW_W64
# ARCHITECTURE: x64 # ARCHITECTURE: x64
GOVERSION: 1.12.4 GOVERSION: 1.12.7
# GOPATH: c:\gopath # GOPATH: c:\gopath
# scripts that run after cloning repository # scripts that run after cloning repository

View File

@ -29,7 +29,7 @@ func base() {
defer hook.End() defer hook.End()
for ev := range EvChan { for ev := range EvChan {
fmt.Println(ev) fmt.Println("hook: ", ev)
} }
} }

View File

@ -20,7 +20,7 @@ func go_send(s *C.char) {
err := json.Unmarshal(str, &out) err := json.Unmarshal(str, &out)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal("json.Unmarshal error is: ", err)
} }
if out.Keychar != CharUndefined { if out.Keychar != CharUndefined {
@ -32,7 +32,7 @@ func go_send(s *C.char) {
// todo bury this deep into the C lib so that the time is correct // todo bury this deep into the C lib so that the time is correct
out.When = time.Now() // at least it's consistent out.When = time.Now() // at least it's consistent
if err != nil { if err != nil {
log.Fatal(err) log.Fatal("json.Unmarshal error is: ", err)
} }
// todo: maybe make non-bloking // todo: maybe make non-bloking

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -28,7 +27,6 @@ type TimesStat struct {
Steal float64 `json:"steal"` Steal float64 `json:"steal"`
Guest float64 `json:"guest"` Guest float64 `json:"guest"`
GuestNice float64 `json:"guestNice"` GuestNice float64 `json:"guestNice"`
Stolen float64 `json:"stolen"`
} }
type InfoStat struct { type InfoStat struct {
@ -63,14 +61,11 @@ func init() {
lastCPUPercent.Unlock() lastCPUPercent.Unlock()
} }
// Counts returns the number of physical or logical cores in the system
func Counts(logical bool) (int, error) { func Counts(logical bool) (int, error) {
return CountsWithContext(context.Background(), logical) return CountsWithContext(context.Background(), logical)
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}
func (c TimesStat) String() string { func (c TimesStat) String() string {
v := []string{ v := []string{
`"cpu":"` + c.CPU + `"`, `"cpu":"` + c.CPU + `"`,
@ -84,7 +79,6 @@ func (c TimesStat) String() string {
`"steal":` + strconv.FormatFloat(c.Steal, 'f', 1, 64), `"steal":` + strconv.FormatFloat(c.Steal, 'f', 1, 64),
`"guest":` + strconv.FormatFloat(c.Guest, 'f', 1, 64), `"guest":` + strconv.FormatFloat(c.Guest, 'f', 1, 64),
`"guestNice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64), `"guestNice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64),
`"stolen":` + strconv.FormatFloat(c.Stolen, 'f', 1, 64),
} }
return `{` + strings.Join(v, ",") + `}` return `{` + strings.Join(v, ",") + `}`
@ -93,7 +87,7 @@ func (c TimesStat) String() string {
// Total returns the total number of seconds in a CPUTimesStat // Total returns the total number of seconds in a CPUTimesStat
func (c TimesStat) Total() float64 { func (c TimesStat) Total() float64 {
total := c.User + c.System + c.Nice + c.Iowait + c.Irq + c.Softirq + c.Steal + total := c.User + c.System + c.Nice + c.Iowait + c.Irq + c.Softirq + c.Steal +
c.Guest + c.GuestNice + c.Idle + c.Stolen c.Guest + c.GuestNice + c.Idle
return total return total
} }
@ -104,7 +98,7 @@ func (c InfoStat) String() string {
func getAllBusy(t TimesStat) (float64, float64) { func getAllBusy(t TimesStat) (float64, float64) {
busy := t.User + t.System + t.Nice + t.Iowait + t.Irq + busy := t.User + t.System + t.Nice + t.Iowait + t.Irq +
t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen t.Softirq + t.Steal + t.Guest + t.GuestNice
return busy + t.Idle, busy return busy + t.Idle, busy
} }

View File

@ -4,9 +4,10 @@ package cpu
import ( import (
"context" "context"
"os/exec"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/sys/unix"
) )
// sys/resource.h // sys/resource.h
@ -41,75 +42,62 @@ func Info() ([]InfoStat, error) {
func InfoWithContext(ctx context.Context) ([]InfoStat, error) { func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
var ret []InfoStat var ret []InfoStat
sysctl, err := exec.LookPath("/usr/sbin/sysctl")
if err != nil {
return ret, err
}
out, err := invoke.CommandWithContext(ctx, sysctl, "machdep.cpu")
if err != nil {
return ret, err
}
c := InfoStat{} c := InfoStat{}
for _, line := range strings.Split(string(out), "\n") { c.ModelName, _ = unix.Sysctl("machdep.cpu.brand_string")
values := strings.Fields(line) family, _ := unix.SysctlUint32("machdep.cpu.family")
if len(values) < 1 { c.Family = strconv.FormatUint(uint64(family), 10)
continue model, _ := unix.SysctlUint32("machdep.cpu.model")
} c.Model = strconv.FormatUint(uint64(model), 10)
stepping, _ := unix.SysctlUint32("machdep.cpu.stepping")
t, err := strconv.ParseInt(values[1], 10, 64) c.Stepping = int32(stepping)
// err is not checked here because some value is string. features, err := unix.Sysctl("machdep.cpu.features")
if strings.HasPrefix(line, "machdep.cpu.brand_string") { if err == nil {
c.ModelName = strings.Join(values[1:], " ") for _, v := range strings.Fields(features) {
} else if strings.HasPrefix(line, "machdep.cpu.family") { c.Flags = append(c.Flags, strings.ToLower(v))
c.Family = values[1]
} else if strings.HasPrefix(line, "machdep.cpu.model") {
c.Model = values[1]
} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
if err != nil {
return ret, err
}
c.Stepping = int32(t)
} else if strings.HasPrefix(line, "machdep.cpu.features") {
for _, v := range values[1:] {
c.Flags = append(c.Flags, strings.ToLower(v))
}
} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") {
for _, v := range values[1:] {
c.Flags = append(c.Flags, strings.ToLower(v))
}
} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") {
for _, v := range values[1:] {
c.Flags = append(c.Flags, strings.ToLower(v))
}
} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
if err != nil {
return ret, err
}
c.Cores = int32(t)
} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
if err != nil {
return ret, err
}
c.CacheSize = int32(t)
} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
c.VendorID = values[1]
} }
} }
leaf7Features, err := unix.Sysctl("machdep.cpu.leaf7_features")
if err == nil {
for _, v := range strings.Fields(leaf7Features) {
c.Flags = append(c.Flags, strings.ToLower(v))
}
}
extfeatures, err := unix.Sysctl("machdep.cpu.extfeatures")
if err == nil {
for _, v := range strings.Fields(extfeatures) {
c.Flags = append(c.Flags, strings.ToLower(v))
}
}
cores, _ := unix.SysctlUint32("machdep.cpu.core_count")
c.Cores = int32(cores)
cacheSize, _ := unix.SysctlUint32("machdep.cpu.cache.size")
c.CacheSize = int32(cacheSize)
c.VendorID, _ = unix.Sysctl("machdep.cpu.vendor")
// Use the rated frequency of the CPU. This is a static value and does not // Use the rated frequency of the CPU. This is a static value and does not
// account for low power or Turbo Boost modes. // account for low power or Turbo Boost modes.
out, err = invoke.CommandWithContext(ctx, sysctl, "hw.cpufrequency") cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency")
if err != nil { if err != nil {
return ret, err return ret, err
} }
c.Mhz = float64(cpuFrequency) / 1000000.0
values := strings.Fields(string(out))
hz, err := strconv.ParseFloat(values[1], 64)
if err != nil {
return ret, err
}
c.Mhz = hz / 1000000.0
return append(ret, c), nil return append(ret, c), nil
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
var cpuArgument string
if logical {
cpuArgument = "hw.logicalcpu"
} else {
cpuArgument = "hw.physicalcpu"
}
count, err := unix.SysctlUint32(cpuArgument)
if err != nil {
return 0, err
}
return int(count), nil
}

View File

@ -4,6 +4,7 @@ package cpu
import ( import (
"context" "context"
"runtime"
"github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/internal/common"
) )
@ -23,3 +24,7 @@ func Info() ([]InfoStat, error) {
func InfoWithContext(ctx context.Context) ([]InfoStat, error) { func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return []InfoStat{}, common.ErrNotImplementedError return []InfoStat{}, common.ErrNotImplementedError
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}

View File

@ -6,6 +6,7 @@ import (
"os/exec" "os/exec"
"reflect" "reflect"
"regexp" "regexp"
"runtime"
"strconv" "strconv"
"strings" "strings"
"unsafe" "unsafe"
@ -25,7 +26,7 @@ var cpuTimesSize int
var emptyTimes cpuTimes var emptyTimes cpuTimes
func init() { func init() {
getconf, err := exec.LookPath("/usr/bin/getconf") getconf, err := exec.LookPath("getconf")
if err != nil { if err != nil {
return return
} }
@ -166,3 +167,7 @@ func parseDmesgBoot(fileName string) (InfoStat, int, error) {
return c, cpuNum, nil return c, cpuNum, nil
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}

View File

@ -0,0 +1,9 @@
package cpu
type cpuTimes struct {
User uint32
Nice uint32
Sys uint32
Intr uint32
Idle uint32
}

View File

@ -16,7 +16,7 @@ import (
var CPUTick = float64(100) var CPUTick = float64(100)
func init() { func init() {
getconf, err := exec.LookPath("/usr/bin/getconf") getconf, err := exec.LookPath("getconf")
if err != nil { if err != nil {
return return
} }
@ -282,3 +282,71 @@ func parseStatLine(line string) (*TimesStat, error) {
return ct, nil return ct, nil
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
if logical {
ret := 0
// https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L599
procCpuinfo := common.HostProc("cpuinfo")
lines, err := common.ReadLines(procCpuinfo)
if err == nil {
for _, line := range lines {
line = strings.ToLower(line)
if strings.HasPrefix(line, "processor") {
ret++
}
}
}
if ret == 0 {
procStat := common.HostProc("stat")
lines, err = common.ReadLines(procStat)
if err != nil {
return 0, err
}
for _, line := range lines {
if len(line) >= 4 && strings.HasPrefix(line, "cpu") && '0' <= line[3] && line[3] <= '9' { // `^cpu\d` regexp matching
ret++
}
}
}
return ret, nil
}
// physical cores https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L628
filename := common.HostProc("cpuinfo")
lines, err := common.ReadLines(filename)
if err != nil {
return 0, err
}
mapping := make(map[int]int)
currentInfo := make(map[string]int)
for _, line := range lines {
line = strings.ToLower(strings.TrimSpace(line))
if line == "" {
// new section
id, okID := currentInfo["physical id"]
cores, okCores := currentInfo["cpu cores"]
if okID && okCores {
mapping[id] = cores
}
currentInfo = make(map[string]int)
continue
}
fields := strings.Split(line, ":")
if len(fields) < 2 {
continue
}
fields[0] = strings.TrimSpace(fields[0])
if fields[0] == "physical id" || fields[0] == "cpu cores" {
val, err := strconv.Atoi(strings.TrimSpace(fields[1]))
if err != nil {
continue
}
currentInfo[fields[0]] = val
}
}
ret := 0
for _, v := range mapping {
ret += v
}
return ret, nil
}

View File

@ -8,15 +8,17 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"os/exec" "os/exec"
"runtime"
"strconv" "strconv"
"strings" "strings"
"syscall"
"github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/internal/common"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
// sys/sched.h // sys/sched.h
const ( var (
CPUser = 0 CPUser = 0
CPNice = 1 CPNice = 1
CPSys = 2 CPSys = 2
@ -28,6 +30,9 @@ const (
// sys/sysctl.h // sys/sysctl.h
const ( const (
CTLKern = 1 // "high kernel": proc, limits CTLKern = 1 // "high kernel": proc, limits
CTLHw = 6 // CTL_HW
SMT = 24 // HW_SMT
NCpuOnline = 25 // HW_NCPUONLINE
KernCptime = 40 // KERN_CPTIME KernCptime = 40 // KERN_CPTIME
KernCptime2 = 71 // KERN_CPTIME2 KernCptime2 = 71 // KERN_CPTIME2
) )
@ -35,18 +40,52 @@ const (
var ClocksPerSec = float64(128) var ClocksPerSec = float64(128)
func init() { func init() {
getconf, err := exec.LookPath("/usr/bin/getconf") func() {
if err != nil { getconf, err := exec.LookPath("getconf")
return if err != nil {
} return
out, err := invoke.Command(getconf, "CLK_TCK")
// ignore errors
if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil {
ClocksPerSec = float64(i)
} }
out, err := invoke.Command(getconf, "CLK_TCK")
// ignore errors
if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil {
ClocksPerSec = float64(i)
}
}
}()
func() {
v, err := unix.Sysctl("kern.osrelease") // can't reuse host.PlatformInformation because of circular import
if err != nil {
return
}
v = strings.ToLower(v)
version, err := strconv.ParseFloat(v, 64)
if err != nil {
return
}
if version >= 6.4 {
CPIntr = 4
CPIdle = 5
CPUStates = 6
}
}()
}
func smt() (bool, error) {
mib := []int32{CTLHw, SMT}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return false, err
} }
var ret bool
br := bytes.NewReader(buf)
if err := binary.Read(br, binary.LittleEndian, &ret); err != nil {
return false, err
}
return ret, nil
} }
func Times(percpu bool) ([]TimesStat, error) { func Times(percpu bool) ([]TimesStat, error) {
@ -63,13 +102,27 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
ncpu = 1 ncpu = 1
} }
smt, err := smt()
if err == syscall.EOPNOTSUPP {
// if hw.smt is not applicable for this platform (e.g. i386),
// pretend it's enabled
smt = true
} else if err != nil {
return nil, err
}
for i := 0; i < ncpu; i++ { for i := 0; i < ncpu; i++ {
var cpuTimes [CPUStates]int64 j := i
if !smt {
j *= 2
}
var cpuTimes = make([]int32, CPUStates)
var mib []int32 var mib []int32
if percpu { if percpu {
mib = []int32{CTLKern, KernCptime} mib = []int32{CTLKern, KernCptime2, int32(j)}
} else { } else {
mib = []int32{CTLKern, KernCptime2, int32(i)} mib = []int32{CTLKern, KernCptime}
} }
buf, _, err := common.CallSyscall(mib) buf, _, err := common.CallSyscall(mib)
if err != nil { if err != nil {
@ -88,10 +141,10 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec, Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec,
Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec, Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec,
} }
if !percpu { if percpu {
c.CPU = "cpu-total" c.CPU = fmt.Sprintf("cpu%d", j)
} else { } else {
c.CPU = fmt.Sprintf("cpu%d", i) c.CPU = "cpu-total"
} }
ret = append(ret, c) ret = append(ret, c)
} }
@ -106,14 +159,37 @@ func Info() ([]InfoStat, error) {
func InfoWithContext(ctx context.Context) ([]InfoStat, error) { func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
var ret []InfoStat var ret []InfoStat
var err error
c := InfoStat{} c := InfoStat{}
v, err := unix.Sysctl("hw.model") var u32 uint32
if u32, err = unix.SysctlUint32("hw.cpuspeed"); err != nil {
return nil, err
}
c.Mhz = float64(u32)
mib := []int32{CTLHw, NCpuOnline}
buf, _, err := common.CallSyscall(mib)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.ModelName = v
var ncpu int32
br := bytes.NewReader(buf)
err = binary.Read(br, binary.LittleEndian, &ncpu)
if err != nil {
return nil, err
}
c.Cores = ncpu
if c.ModelName, err = unix.Sysctl("hw.model"); err != nil {
return nil, err
}
return append(ret, c), nil return append(ret, c), nil
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}

View File

@ -6,17 +6,16 @@ import (
"fmt" "fmt"
"os/exec" "os/exec"
"regexp" "regexp"
"runtime"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"github.com/shirou/gopsutil/internal/common"
) )
var ClocksPerSec = float64(128) var ClocksPerSec = float64(128)
func init() { func init() {
getconf, err := exec.LookPath("/usr/bin/getconf") getconf, err := exec.LookPath("getconf")
if err != nil { if err != nil {
return return
} }
@ -30,12 +29,97 @@ func init() {
} }
} }
//sum all values in a float64 map with float64 keys
func msum(x map[float64]float64) float64 {
total := 0.0
for _, y := range x {
total += y
}
return total
}
func Times(percpu bool) ([]TimesStat, error) { func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu) return TimesWithContext(context.Background(), percpu)
} }
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
return []TimesStat{}, common.ErrNotImplementedError kstatSys, err := exec.LookPath("kstat")
if err != nil {
return nil, fmt.Errorf("cannot find kstat: %s", err)
}
cpu := make(map[float64]float64)
idle := make(map[float64]float64)
user := make(map[float64]float64)
kern := make(map[float64]float64)
iowt := make(map[float64]float64)
//swap := make(map[float64]float64)
kstatSysOut, err := invoke.CommandWithContext(ctx, kstatSys, "-p", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/")
if err != nil {
return nil, fmt.Errorf("cannot execute kstat: %s", err)
}
re := regexp.MustCompile(`[:\s]+`)
for _, line := range strings.Split(string(kstatSysOut), "\n") {
fields := re.Split(line, -1)
if fields[0] != "cpu_stat" {
continue
}
cpuNumber, err := strconv.ParseFloat(fields[1], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse cpu number: %s", err)
}
cpu[cpuNumber] = cpuNumber
switch fields[3] {
case "idle":
idle[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse idle: %s", err)
}
case "user":
user[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse user: %s", err)
}
case "kernel":
kern[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse kernel: %s", err)
}
case "iowait":
iowt[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse iowait: %s", err)
}
//not sure how this translates, don't report, add to kernel, something else?
/*case "swap":
swap[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse swap: %s", err)
} */
}
}
ret := make([]TimesStat, 0, len(cpu))
if percpu {
for _, c := range cpu {
ct := &TimesStat{
CPU: fmt.Sprintf("cpu%d", int(cpu[c])),
Idle: idle[c] / ClocksPerSec,
User: user[c] / ClocksPerSec,
System: kern[c] / ClocksPerSec,
Iowait: iowt[c] / ClocksPerSec,
}
ret = append(ret, *ct)
}
} else {
ct := &TimesStat{
CPU: "cpu-total",
Idle: msum(idle) / ClocksPerSec,
User: msum(user) / ClocksPerSec,
System: msum(kern) / ClocksPerSec,
Iowait: msum(iowt) / ClocksPerSec,
}
ret = append(ret, *ct)
}
return ret, nil
} }
func Info() ([]InfoStat, error) { func Info() ([]InfoStat, error) {
@ -43,7 +127,7 @@ func Info() ([]InfoStat, error) {
} }
func InfoWithContext(ctx context.Context) ([]InfoStat, error) { func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
psrInfo, err := exec.LookPath("/usr/sbin/psrinfo") psrInfo, err := exec.LookPath("psrinfo")
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot find psrinfo: %s", err) return nil, fmt.Errorf("cannot find psrinfo: %s", err)
} }
@ -52,7 +136,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return nil, fmt.Errorf("cannot execute psrinfo: %s", err) return nil, fmt.Errorf("cannot execute psrinfo: %s", err)
} }
isaInfo, err := exec.LookPath("/usr/bin/isainfo") isaInfo, err := exec.LookPath("isainfo")
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot find isainfo: %s", err) return nil, fmt.Errorf("cannot find isainfo: %s", err)
} }
@ -196,3 +280,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
} }
return result, nil return result, nil
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}

View File

@ -5,6 +5,7 @@ package cpu
import ( import (
"context" "context"
"fmt" "fmt"
"runtime"
"unsafe" "unsafe"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
@ -23,18 +24,18 @@ type Win32_Processor struct {
MaxClockSpeed uint32 MaxClockSpeed uint32
} }
type win32_PerfRawData_Counters_ProcessorInformation struct { // SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
Name string // defined in windows api doc with the following
PercentDPCTime uint64 // https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntquerysysteminformation#system_processor_performance_information
PercentIdleTime uint64 // additional fields documented here
PercentUserTime uint64 // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/processor_performance.htm
PercentProcessorTime uint64 type win32_SystemProcessorPerformanceInformation struct {
PercentInterruptTime uint64 IdleTime int64 // idle time in 100ns (this is not a filetime).
PercentPriorityTime uint64 KernelTime int64 // kernel time in 100ns. kernel time includes idle time. (this is not a filetime).
PercentPrivilegedTime uint64 UserTime int64 // usertime in 100ns (this is not a filetime).
InterruptsPerSec uint32 DpcTime int64 // dpc time in 100ns (this is not a filetime).
ProcessorFrequency uint32 InterruptTime int64 // interrupt time in 100ns
DPCRate uint32 InterruptCount uint32
} }
// Win32_PerfFormattedData_PerfOS_System struct to have count of processes and processor queue length // Win32_PerfFormattedData_PerfOS_System struct to have count of processes and processor queue length
@ -45,6 +46,13 @@ type Win32_PerfFormattedData_PerfOS_System struct {
const ( const (
win32_TicksPerSecond = 10000000.0 win32_TicksPerSecond = 10000000.0
// systemProcessorPerformanceInformationClass information class to query with NTQuerySystemInformation
// https://processhacker.sourceforge.io/doc/ntexapi_8h.html#ad5d815b48e8f4da1ef2eb7a2f18a54e0
win32_SystemProcessorPerformanceInformationClass = 8
// size of systemProcessorPerformanceInfoSize in memory
win32_SystemProcessorPerformanceInfoSize = uint32(unsafe.Sizeof(win32_SystemProcessorPerformanceInformation{}))
) )
// Times returns times stat per cpu and combined for all CPUs // Times returns times stat per cpu and combined for all CPUs
@ -54,7 +62,7 @@ func Times(percpu bool) ([]TimesStat, error) {
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
if percpu { if percpu {
return perCPUTimesWithContext(ctx) return perCPUTimes()
} }
var ret []TimesStat var ret []TimesStat
@ -120,20 +128,6 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return ret, nil return ret, nil
} }
// PerfInfo returns the performance counter's instance value for ProcessorInformation.
// Name property is the key by which overall, per cpu and per core metric is known.
func perfInfoWithContext(ctx context.Context) ([]win32_PerfRawData_Counters_ProcessorInformation, error) {
var ret []win32_PerfRawData_Counters_ProcessorInformation
q := wmi.CreateQuery(&ret, "WHERE NOT Name LIKE '%_Total'")
err := common.WMIQueryWithContext(ctx, q, &ret)
if err != nil {
return []win32_PerfRawData_Counters_ProcessorInformation{}, err
}
return ret, err
}
// ProcInfo returns processes count and processor queue length in the system. // ProcInfo returns processes count and processor queue length in the system.
// There is a single queue for processor even on multiprocessors systems. // There is a single queue for processor even on multiprocessors systems.
func ProcInfo() ([]Win32_PerfFormattedData_PerfOS_System, error) { func ProcInfo() ([]Win32_PerfFormattedData_PerfOS_System, error) {
@ -151,21 +145,62 @@ func ProcInfoWithContext(ctx context.Context) ([]Win32_PerfFormattedData_PerfOS_
} }
// perCPUTimes returns times stat per cpu, per core and overall for all CPUs // perCPUTimes returns times stat per cpu, per core and overall for all CPUs
func perCPUTimesWithContext(ctx context.Context) ([]TimesStat, error) { func perCPUTimes() ([]TimesStat, error) {
var ret []TimesStat var ret []TimesStat
stats, err := perfInfoWithContext(ctx) stats, err := perfInfo()
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, v := range stats { for core, v := range stats {
c := TimesStat{ c := TimesStat{
CPU: v.Name, CPU: fmt.Sprintf("cpu%d", core),
User: float64(v.PercentUserTime) / win32_TicksPerSecond, User: float64(v.UserTime) / win32_TicksPerSecond,
System: float64(v.PercentPrivilegedTime) / win32_TicksPerSecond, System: float64(v.KernelTime-v.IdleTime) / win32_TicksPerSecond,
Idle: float64(v.PercentIdleTime) / win32_TicksPerSecond, Idle: float64(v.IdleTime) / win32_TicksPerSecond,
Irq: float64(v.PercentInterruptTime) / win32_TicksPerSecond, Irq: float64(v.InterruptTime) / win32_TicksPerSecond,
} }
ret = append(ret, c) ret = append(ret, c)
} }
return ret, nil return ret, nil
} }
// makes call to Windows API function to retrieve performance information for each core
func perfInfo() ([]win32_SystemProcessorPerformanceInformation, error) {
// Make maxResults large for safety.
// We can't invoke the api call with a results array that's too small.
// If we have more than 2056 cores on a single host, then it's probably the future.
maxBuffer := 2056
// buffer for results from the windows proc
resultBuffer := make([]win32_SystemProcessorPerformanceInformation, maxBuffer)
// size of the buffer in memory
bufferSize := uintptr(win32_SystemProcessorPerformanceInfoSize) * uintptr(maxBuffer)
// size of the returned response
var retSize uint32
// Invoke windows api proc.
// The returned err from the windows dll proc will always be non-nil even when successful.
// See https://godoc.org/golang.org/x/sys/windows#LazyProc.Call for more information
retCode, _, err := common.ProcNtQuerySystemInformation.Call(
win32_SystemProcessorPerformanceInformationClass, // System Information Class -> SystemProcessorPerformanceInformation
uintptr(unsafe.Pointer(&resultBuffer[0])), // pointer to first element in result buffer
bufferSize, // size of the buffer in memory
uintptr(unsafe.Pointer(&retSize)), // pointer to the size of the returned results the windows proc will set this
)
// check return code for errors
if retCode != 0 {
return nil, fmt.Errorf("call to NtQuerySystemInformation returned %d. err: %s", retCode, err.Error())
}
// calculate the number of returned elements based on the returned size
numReturnedElements := retSize / win32_SystemProcessorPerformanceInfoSize
// trim results to the number of returned elements
resultBuffer = resultBuffer[:numReturnedElements]
return resultBuffer, nil
}
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}

View File

@ -1,53 +0,0 @@
package host
import (
"encoding/json"
"github.com/shirou/gopsutil/internal/common"
)
var invoke common.Invoker = common.Invoke{}
// A HostInfoStat describes the host status.
// This is not in the psutil but it useful.
type InfoStat struct {
Hostname string `json:"hostname"`
Uptime uint64 `json:"uptime"`
BootTime uint64 `json:"bootTime"`
Procs uint64 `json:"procs"` // number of processes
OS string `json:"os"` // ex: freebsd, linux
Platform string `json:"platform"` // ex: ubuntu, linuxmint
PlatformFamily string `json:"platformFamily"` // ex: debian, rhel
PlatformVersion string `json:"platformVersion"` // version of the complete OS
KernelVersion string `json:"kernelVersion"` // version of the OS kernel (if available)
VirtualizationSystem string `json:"virtualizationSystem"`
VirtualizationRole string `json:"virtualizationRole"` // guest or host
HostID string `json:"hostid"` // ex: uuid
}
type UserStat struct {
User string `json:"user"`
Terminal string `json:"terminal"`
Host string `json:"host"`
Started int `json:"started"`
}
type TemperatureStat struct {
SensorKey string `json:"sensorKey"`
Temperature float64 `json:"sensorTemperature"`
}
func (h InfoStat) String() string {
s, _ := json.Marshal(h)
return string(s)
}
func (u UserStat) String() string {
s, _ := json.Marshal(u)
return string(s)
}
func (t TemperatureStat) String() string {
s, _ := json.Marshal(t)
return string(s)
}

View File

@ -1,232 +0,0 @@
// +build darwin
package host
import (
"bytes"
"context"
"encoding/binary"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"sync/atomic"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/process"
)
// from utmpx.h
const USER_PROCESS = 7
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
PlatformFamily: "darwin",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
kernelVersion, err := KernelVersionWithContext(ctx)
if err == nil {
ret.KernelVersion = kernelVersion
}
platform, family, pver, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = pver
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
values, err := common.DoSysctrlWithContext(ctx, "kern.uuid")
if err == nil && len(values) == 1 && values[0] != "" {
ret.HostID = strings.ToLower(values[0])
}
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
values, err := common.DoSysctrlWithContext(ctx, "kern.boottime")
if err != nil {
return 0, err
}
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1)
boottime, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return 0, err
}
t = uint64(boottime)
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
utmpfile := "/var/run/utmpx"
var ret []UserStat
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
u := Utmpx{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u Utmpx
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil {
continue
}
if u.Type != USER_PROCESS {
continue
}
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Tv.Sec),
}
ret = append(ret, user)
}
return ret, nil
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform := ""
family := ""
pver := ""
sw_vers, err := exec.LookPath("sw_vers")
if err != nil {
return "", "", "", err
}
uname, err := exec.LookPath("uname")
if err != nil {
return "", "", "", err
}
out, err := invoke.CommandWithContext(ctx, uname, "-s")
if err == nil {
platform = strings.ToLower(strings.TrimSpace(string(out)))
}
out, err = invoke.CommandWithContext(ctx, sw_vers, "-productVersion")
if err == nil {
pver = strings.ToLower(strings.TrimSpace(string(out)))
}
return platform, family, pver, nil
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
uname, err := exec.LookPath("uname")
if err != nil {
return "", err
}
out, err := invoke.CommandWithContext(ctx, uname, "-r")
if err != nil {
return "", err
}
version := strings.ToLower(strings.TrimSpace(string(out)))
return version, err
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}

View File

@ -1,19 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_darwin.go
package host
type Utmpx struct {
User [256]int8
ID [4]int8
Line [32]int8
Pid int32
Type int16
Pad_cgo_0 [6]byte
Tv Timeval
Host [256]int8
Pad [16]uint32
}
type Timeval struct {
Sec int32
}

View File

@ -1,19 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_darwin.go
package host
type Utmpx struct {
User [256]int8
ID [4]int8
Line [32]int8
Pid int32
Type int16
Pad_cgo_0 [6]byte
Tv Timeval
Host [256]int8
Pad [16]uint32
}
type Timeval struct {
Sec int32
}

View File

@ -1,65 +0,0 @@
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows
package host
import (
"context"
"github.com/shirou/gopsutil/internal/common"
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
return nil, common.ErrNotImplementedError
}
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
return 0, common.ErrNotImplementedError
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
return 0, common.ErrNotImplementedError
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return []UserStat{}, common.ErrNotImplementedError
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
return "", "", "", common.ErrNotImplementedError
}

View File

@ -1,245 +0,0 @@
// +build freebsd
package host
import (
"bytes"
"context"
"encoding/binary"
"io/ioutil"
"os"
"runtime"
"strings"
"sync/atomic"
"syscall"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/process"
"golang.org/x/sys/unix"
)
const (
UTNameSize = 16 /* see MAXLOGNAME in <sys/param.h> */
UTLineSize = 8
UTHostSize = 16
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
PlatformFamily: "freebsd",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
ret.KernelVersion = version
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
hostid, err := unix.Sysctl("kern.hostuuid")
if err == nil && hostid != "" {
ret.HostID = strings.ToLower(hostid)
}
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
buf, err := unix.SysctlRaw("kern.boottime")
if err != nil {
return 0, err
}
tv := *(*syscall.Timeval)(unsafe.Pointer((&buf[0])))
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
return t, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
utmpfile := "/var/run/utx.active"
if !common.PathExists(utmpfile) {
utmpfile = "/var/run/utmp" // before 9.0
return getUsersFromUtmp(utmpfile)
}
var ret []UserStat
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
entrySize := sizeOfUtmpx
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*sizeOfUtmpx : (i+1)*sizeOfUtmpx]
var u Utmpx
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil || u.Type != 4 {
continue
}
sec := (binary.LittleEndian.Uint32(u.Tv.Sec[:])) / 2 // TODO:
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(sec),
}
ret = append(ret, user)
}
return ret, nil
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform, err := unix.Sysctl("kern.ostype")
if err != nil {
return "", "", "", err
}
version, err := unix.Sysctl("kern.osrelease")
if err != nil {
return "", "", "", err
}
return strings.ToLower(platform), "", strings.ToLower(version), nil
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
// before 9.0
func getUsersFromUtmp(utmpfile string) ([]UserStat, error) {
var ret []UserStat
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
u := Utmp{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u Utmp
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil || u.Time == 0 {
continue
}
user := UserStat{
User: common.IntToString(u.Name[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Time),
}
ret = append(ret, user)
}
return ret, nil
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, err := PlatformInformation()
return version, err
}

View File

@ -1,43 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmpx = 197 // TODO why should 197
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type Utmp struct {
Line [8]int8
Name [16]int8
Host [16]int8
Time int32
}
type Utmpx struct {
Type int16
Tv Timeval
Id [8]int8
Pid int32
User [32]int8
Line [16]int8
Host [125]int8
// X__ut_spare [64]int8
}
type Timeval struct {
Sec [4]byte
Usec [3]byte
}

View File

@ -1,44 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmpx = 197 // TODO: why should 197, not 0x118
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type Utmp struct {
Line [8]int8
Name [16]int8
Host [16]int8
Time int32
}
type Utmpx struct {
Type int16
Tv Timeval
Id [8]int8
Pid int32
User [32]int8
Line [16]int8
Host [125]int8
// Host [128]int8
// X__ut_spare [64]int8
}
type Timeval struct {
Sec [4]byte
Usec [3]byte
}

View File

@ -1,44 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmpx = 197 // TODO: why should 197, not 0x118
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type Utmp struct {
Line [8]int8
Name [16]int8
Host [16]int8
Time int32
}
type Utmpx struct {
Type int16
Tv Timeval
Id [8]int8
Pid int32
User [32]int8
Line [16]int8
Host [125]int8
// Host [128]int8
// X__ut_spare [64]int8
}
type Timeval struct {
Sec [4]byte
Usec [3]byte
}

View File

@ -1,682 +0,0 @@
// +build linux
package host
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/shirou/gopsutil/internal/common"
)
type LSB struct {
ID string
Release string
Codename string
Description string
}
// from utmp.h
const USER_PROCESS = 7
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
kernelVersion, err := KernelVersion()
if err == nil {
ret.KernelVersion = kernelVersion
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
if numProcs, err := common.NumProcs(); err == nil {
ret.Procs = numProcs
}
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
machineID := common.HostEtc("machine-id")
switch {
// In order to read this file, needs to be supported by kernel/arch and run as root
// so having fallback is important
case common.PathExists(sysProductUUID):
lines, err := common.ReadLines(sysProductUUID)
if err == nil && len(lines) > 0 && lines[0] != "" {
ret.HostID = strings.ToLower(lines[0])
break
}
fallthrough
// Fallback on GNU Linux systems with systemd, readable by everyone
case common.PathExists(machineID):
lines, err := common.ReadLines(machineID)
if err == nil && len(lines) > 0 && len(lines[0]) == 32 {
st := lines[0]
ret.HostID = fmt.Sprintf("%s-%s-%s-%s-%s", st[0:8], st[8:12], st[12:16], st[16:20], st[20:32])
break
}
fallthrough
// Not stable between reboot, but better than nothing
default:
values, err := common.DoSysctrl("kernel.random.boot_id")
if err == nil && len(values) == 1 && values[0] != "" {
ret.HostID = strings.ToLower(values[0])
}
}
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
// BootTime returns the system boot time expressed in seconds since the epoch.
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
system, role, err := Virtualization()
if err != nil {
return 0, err
}
statFile := "stat"
if system == "lxc" && role == "guest" {
// if lxc, /proc/uptime is used.
statFile = "uptime"
} else if system == "docker" && role == "guest" {
// also docker, guest
statFile = "uptime"
}
filename := common.HostProc(statFile)
lines, err := common.ReadLines(filename)
if err != nil {
return 0, err
}
if statFile == "stat" {
for _, line := range lines {
if strings.HasPrefix(line, "btime") {
f := strings.Fields(line)
if len(f) != 2 {
return 0, fmt.Errorf("wrong btime format")
}
b, err := strconv.ParseInt(f[1], 10, 64)
if err != nil {
return 0, err
}
t = uint64(b)
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
}
} else if statFile == "uptime" {
if len(lines) != 1 {
return 0, fmt.Errorf("wrong uptime format")
}
f := strings.Fields(lines[0])
b, err := strconv.ParseFloat(f[0], 64)
if err != nil {
return 0, err
}
t = uint64(time.Now().Unix()) - uint64(b)
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
return 0, fmt.Errorf("could not find btime")
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
utmpfile := common.HostVar("run/utmp")
file, err := os.Open(utmpfile)
if err != nil {
return nil, err
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
count := len(buf) / sizeOfUtmp
ret := make([]UserStat, 0, count)
for i := 0; i < count; i++ {
b := buf[i*sizeOfUtmp : (i+1)*sizeOfUtmp]
var u utmp
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil {
continue
}
if u.Type != USER_PROCESS {
continue
}
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Tv.Sec),
}
ret = append(ret, user)
}
return ret, nil
}
func getOSRelease() (platform string, version string, err error) {
contents, err := common.ReadLines(common.HostEtc("os-release"))
if err != nil {
return "", "", nil // return empty
}
for _, line := range contents {
field := strings.Split(line, "=")
if len(field) < 2 {
continue
}
switch field[0] {
case "ID": // use ID for lowercase
platform = field[1]
case "VERSION":
version = field[1]
}
}
return platform, version, nil
}
func getLSB() (*LSB, error) {
ret := &LSB{}
if common.PathExists(common.HostEtc("lsb-release")) {
contents, err := common.ReadLines(common.HostEtc("lsb-release"))
if err != nil {
return ret, err // return empty
}
for _, line := range contents {
field := strings.Split(line, "=")
if len(field) < 2 {
continue
}
switch field[0] {
case "DISTRIB_ID":
ret.ID = field[1]
case "DISTRIB_RELEASE":
ret.Release = field[1]
case "DISTRIB_CODENAME":
ret.Codename = field[1]
case "DISTRIB_DESCRIPTION":
ret.Description = field[1]
}
}
} else if common.PathExists("/usr/bin/lsb_release") {
lsb_release, err := exec.LookPath("/usr/bin/lsb_release")
if err != nil {
return ret, err
}
out, err := invoke.Command(lsb_release)
if err != nil {
return ret, err
}
for _, line := range strings.Split(string(out), "\n") {
field := strings.Split(line, ":")
if len(field) < 2 {
continue
}
switch field[0] {
case "Distributor ID":
ret.ID = field[1]
case "Release":
ret.Release = field[1]
case "Codename":
ret.Codename = field[1]
case "Description":
ret.Description = field[1]
}
}
}
return ret, nil
}
func PlatformInformation() (platform string, family string, version string, err error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
lsb, err := getLSB()
if err != nil {
lsb = &LSB{}
}
if common.PathExists(common.HostEtc("oracle-release")) {
platform = "oracle"
contents, err := common.ReadLines(common.HostEtc("oracle-release"))
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists(common.HostEtc("enterprise-release")) {
platform = "oracle"
contents, err := common.ReadLines(common.HostEtc("enterprise-release"))
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists(common.HostEtc("slackware-version")) {
platform = "slackware"
contents, err := common.ReadLines(common.HostEtc("slackware-version"))
if err == nil {
version = getSlackwareVersion(contents)
}
} else if common.PathExists(common.HostEtc("debian_version")) {
if lsb.ID == "Ubuntu" {
platform = "ubuntu"
version = lsb.Release
} else if lsb.ID == "LinuxMint" {
platform = "linuxmint"
version = lsb.Release
} else {
if common.PathExists("/usr/bin/raspi-config") {
platform = "raspbian"
} else {
platform = "debian"
}
contents, err := common.ReadLines(common.HostEtc("debian_version"))
if err == nil {
version = contents[0]
}
}
} else if common.PathExists(common.HostEtc("redhat-release")) {
contents, err := common.ReadLines(common.HostEtc("redhat-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtc("system-release")) {
contents, err := common.ReadLines(common.HostEtc("system-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtc("gentoo-release")) {
platform = "gentoo"
contents, err := common.ReadLines(common.HostEtc("gentoo-release"))
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists(common.HostEtc("SuSE-release")) {
contents, err := common.ReadLines(common.HostEtc("SuSE-release"))
if err == nil {
version = getSuseVersion(contents)
platform = getSusePlatform(contents)
}
// TODO: slackware detecion
} else if common.PathExists(common.HostEtc("arch-release")) {
platform = "arch"
version = lsb.Release
} else if common.PathExists(common.HostEtc("alpine-release")) {
platform = "alpine"
contents, err := common.ReadLines(common.HostEtc("alpine-release"))
if err == nil && len(contents) > 0 {
version = contents[0]
}
} else if common.PathExists(common.HostEtc("os-release")) {
p, v, err := getOSRelease()
if err == nil {
platform = p
version = v
}
} else if lsb.ID == "RedHat" {
platform = "redhat"
version = lsb.Release
} else if lsb.ID == "Amazon" {
platform = "amazon"
version = lsb.Release
} else if lsb.ID == "ScientificSL" {
platform = "scientific"
version = lsb.Release
} else if lsb.ID == "XenServer" {
platform = "xenserver"
version = lsb.Release
} else if lsb.ID != "" {
platform = strings.ToLower(lsb.ID)
version = lsb.Release
}
switch platform {
case "debian", "ubuntu", "linuxmint", "raspbian":
family = "debian"
case "fedora":
family = "fedora"
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm":
family = "rhel"
case "suse", "opensuse":
family = "suse"
case "gentoo":
family = "gentoo"
case "slackware":
family = "slackware"
case "arch":
family = "arch"
case "exherbo":
family = "exherbo"
case "alpine":
family = "alpine"
case "coreos":
family = "coreos"
}
return platform, family, version, nil
}
func KernelVersion() (version string, err error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (version string, err error) {
filename := common.HostProc("sys/kernel/osrelease")
if common.PathExists(filename) {
contents, err := common.ReadLines(filename)
if err != nil {
return "", err
}
if len(contents) > 0 {
version = contents[0]
}
}
return version, nil
}
func getSlackwareVersion(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
c = strings.Replace(c, "slackware ", "", 1)
return c
}
func getRedhatishVersion(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
if strings.Contains(c, "rawhide") {
return "rawhide"
}
if matches := regexp.MustCompile(`release (\d[\d.]*)`).FindStringSubmatch(c); matches != nil {
return matches[1]
}
return ""
}
func getRedhatishPlatform(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
if strings.Contains(c, "red hat") {
return "redhat"
}
f := strings.Split(c, " ")
return f[0]
}
func getSuseVersion(contents []string) string {
version := ""
for _, line := range contents {
if matches := regexp.MustCompile(`VERSION = ([\d.]+)`).FindStringSubmatch(line); matches != nil {
version = matches[1]
} else if matches := regexp.MustCompile(`PATCHLEVEL = ([\d]+)`).FindStringSubmatch(line); matches != nil {
version = version + "." + matches[1]
}
}
return version
}
func getSusePlatform(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
if strings.Contains(c, "opensuse") {
return "opensuse"
}
return "suse"
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
var system string
var role string
filename := common.HostProc("xen")
if common.PathExists(filename) {
system = "xen"
role = "guest" // assume guest
if common.PathExists(filepath.Join(filename, "capabilities")) {
contents, err := common.ReadLines(filepath.Join(filename, "capabilities"))
if err == nil {
if common.StringsContains(contents, "control_d") {
role = "host"
}
}
}
}
filename = common.HostProc("modules")
if common.PathExists(filename) {
contents, err := common.ReadLines(filename)
if err == nil {
if common.StringsContains(contents, "kvm") {
system = "kvm"
role = "host"
} else if common.StringsContains(contents, "vboxdrv") {
system = "vbox"
role = "host"
} else if common.StringsContains(contents, "vboxguest") {
system = "vbox"
role = "guest"
} else if common.StringsContains(contents, "vmware") {
system = "vmware"
role = "guest"
}
}
}
filename = common.HostProc("cpuinfo")
if common.PathExists(filename) {
contents, err := common.ReadLines(filename)
if err == nil {
if common.StringsContains(contents, "QEMU Virtual CPU") ||
common.StringsContains(contents, "Common KVM processor") ||
common.StringsContains(contents, "Common 32-bit KVM processor") {
system = "kvm"
role = "guest"
}
}
}
filename = common.HostProc()
if common.PathExists(filepath.Join(filename, "bc", "0")) {
system = "openvz"
role = "host"
} else if common.PathExists(filepath.Join(filename, "vz")) {
system = "openvz"
role = "guest"
}
// not use dmidecode because it requires root
if common.PathExists(filepath.Join(filename, "self", "status")) {
contents, err := common.ReadLines(filepath.Join(filename, "self", "status"))
if err == nil {
if common.StringsContains(contents, "s_context:") ||
common.StringsContains(contents, "VxID:") {
system = "linux-vserver"
}
// TODO: guest or host
}
}
if common.PathExists(filepath.Join(filename, "self", "cgroup")) {
contents, err := common.ReadLines(filepath.Join(filename, "self", "cgroup"))
if err == nil {
if common.StringsContains(contents, "lxc") {
system = "lxc"
role = "guest"
} else if common.StringsContains(contents, "docker") {
system = "docker"
role = "guest"
} else if common.StringsContains(contents, "machine-rkt") {
system = "rkt"
role = "guest"
} else if common.PathExists("/usr/bin/lxc-version") {
system = "lxc"
role = "host"
}
}
}
if common.PathExists(common.HostEtc("os-release")) {
p, _, err := getOSRelease()
if err == nil && p == "coreos" {
system = "rkt" // Is it true?
role = "host"
}
}
return system, role, nil
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
var temperatures []TemperatureStat
files, err := filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*"))
if 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 {
return temperatures, err
}
}
// 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
// power/ temp1_label temp2_label temp3_label temp4_label temp5_label temp6_label temp7_label
// 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
}
// 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))), " "), ""))
}
// Get the name of the tempearture you are reading
name, err := ioutil.ReadFile(filepath.Join(filepath.Dir(file), "name"))
if err != nil {
return temperatures, err
}
// Get the temperature reading
current, err := ioutil.ReadFile(file)
if err != nil {
return temperatures, err
}
temperature, err := strconv.ParseFloat(strings.TrimSpace(string(current)), 64)
if err != nil {
continue
}
tempName := strings.TrimSpace(strings.ToLower(string(strings.Join(filename[1:], ""))))
temperatures = append(temperatures, TemperatureStat{
SensorKey: fmt.Sprintf("%s_%s%s", strings.TrimSpace(string(name)), label, tempName),
Temperature: temperature / 1000.0,
})
}
return temperatures, nil
}

View File

@ -1,45 +0,0 @@
// ATTENTION - FILE MANUAL FIXED AFTER CGO.
// Fixed line: Tv _Ctype_struct_timeval -> Tv UtTv
// Created by cgo -godefs, MANUAL FIXED
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
ID [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv UtTv
Addr_v6 [4]int32
X__unused [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type UtTv struct {
Sec int32
Usec int32
}

View File

@ -1,48 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv _Ctype_struct___0
Addr_v6 [4]int32
X__glibc_reserved [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int64
Usec int64
}
type _Ctype_struct___0 struct {
Sec int32
Usec int32
}

View File

@ -1,43 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go | sed "s/uint8/int8/g"
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__glibc_reserved [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int32
Usec int32
}

View File

@ -1,43 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__glibc_reserved [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int64
Usec int64
}

View File

@ -1,43 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__unused [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int32
Usec int32
}

View File

@ -1,43 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__unused [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int32
Usec int32
}

View File

@ -1,43 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__unused [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int32
Usec int32
}

View File

@ -1,43 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__unused [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int32
Usec int32
}

View File

@ -1,45 +0,0 @@
// +build linux
// +build ppc64le
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__glibc_reserved [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int64
Usec int64
}

View File

@ -1,45 +0,0 @@
// +build linux
// +build s390x
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__glibc_reserved [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int64
Usec int64
}

View File

@ -1,195 +0,0 @@
// +build openbsd
package host
import (
"bytes"
"context"
"encoding/binary"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/process"
)
const (
UTNameSize = 32 /* see MAXLOGNAME in <sys/param.h> */
UTLineSize = 8
UTHostSize = 16
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
PlatformFamily: "openbsd",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
return ret, nil
}
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
val, err := common.DoSysctrl("kern.boottime")
if err != nil {
return 0, err
}
boottime, err := strconv.ParseUint(val[0], 10, 64)
if err != nil {
return 0, err
}
return boottime, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform := ""
family := ""
version := ""
uname, err := exec.LookPath("uname")
if err != nil {
return "", "", "", err
}
out, err := invoke.CommandWithContext(ctx, uname, "-s")
if err == nil {
platform = strings.ToLower(strings.TrimSpace(string(out)))
}
out, err = invoke.CommandWithContext(ctx, uname, "-r")
if err == nil {
version = strings.ToLower(strings.TrimSpace(string(out)))
}
return platform, family, version, nil
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
var ret []UserStat
utmpfile := "/var/run/utmp"
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
u := Utmp{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u Utmp
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil || u.Time == 0 {
continue
}
user := UserStat{
User: common.IntToString(u.Name[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Time),
}
ret = append(ret, user)
}
return ret, nil
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, err := PlatformInformation()
return version, err
}

View File

@ -1,31 +0,0 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_openbsd.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x130
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type Utmp struct {
Line [8]int8
Name [32]int8
Host [256]int8
Time int64
}
type Timeval struct {
Sec int64
Usec int64
}

View File

@ -1,248 +0,0 @@
package host
import (
"bufio"
"bytes"
"context"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"runtime"
"strconv"
"strings"
"time"
"github.com/shirou/gopsutil/internal/common"
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
result := &InfoStat{
OS: runtime.GOOS,
}
hostname, err := os.Hostname()
if err != nil {
return nil, err
}
result.Hostname = hostname
// Parse versions from output of `uname(1)`
uname, err := exec.LookPath("/usr/bin/uname")
if err != nil {
return nil, err
}
out, err := invoke.CommandWithContext(ctx, uname, "-srv")
if err != nil {
return nil, err
}
fields := strings.Fields(string(out))
if len(fields) >= 1 {
result.PlatformFamily = fields[0]
}
if len(fields) >= 2 {
result.KernelVersion = fields[1]
}
if len(fields) == 3 {
result.PlatformVersion = fields[2]
}
// Find distribution name from /etc/release
fh, err := os.Open("/etc/release")
if err != nil {
return nil, err
}
defer fh.Close()
sc := bufio.NewScanner(fh)
if sc.Scan() {
line := strings.TrimSpace(sc.Text())
switch {
case strings.HasPrefix(line, "SmartOS"):
result.Platform = "SmartOS"
case strings.HasPrefix(line, "OpenIndiana"):
result.Platform = "OpenIndiana"
case strings.HasPrefix(line, "OmniOS"):
result.Platform = "OmniOS"
case strings.HasPrefix(line, "Open Storage"):
result.Platform = "NexentaStor"
case strings.HasPrefix(line, "Solaris"):
result.Platform = "Solaris"
case strings.HasPrefix(line, "Oracle Solaris"):
result.Platform = "Solaris"
default:
result.Platform = strings.Fields(line)[0]
}
}
switch result.Platform {
case "SmartOS":
// If everything works, use the current zone ID as the HostID if present.
zonename, err := exec.LookPath("/usr/bin/zonename")
if err == nil {
out, err := invoke.CommandWithContext(ctx, zonename)
if err == nil {
sc := bufio.NewScanner(bytes.NewReader(out))
for sc.Scan() {
line := sc.Text()
// If we're in the global zone, rely on the hostname.
if line == "global" {
hostname, err := os.Hostname()
if err == nil {
result.HostID = hostname
}
} else {
result.HostID = strings.TrimSpace(line)
break
}
}
}
}
}
// If HostID is still empty, use hostid(1), which can lie to callers but at
// this point there are no hardware facilities available. This behavior
// matches that of other supported OSes.
if result.HostID == "" {
hostID, err := exec.LookPath("/usr/bin/hostid")
if err == nil {
out, err := invoke.CommandWithContext(ctx, hostID)
if err == nil {
sc := bufio.NewScanner(bytes.NewReader(out))
for sc.Scan() {
line := sc.Text()
result.HostID = strings.TrimSpace(line)
break
}
}
}
}
// Find the boot time and calculate uptime relative to it
bootTime, err := BootTime()
if err != nil {
return nil, err
}
result.BootTime = bootTime
result.Uptime = uptimeSince(bootTime)
// Count number of processes based on the number of entries in /proc
dirs, err := ioutil.ReadDir("/proc")
if err != nil {
return nil, err
}
result.Procs = uint64(len(dirs))
return result, nil
}
var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
kstat, err := exec.LookPath("/usr/bin/kstat")
if err != nil {
return 0, err
}
out, err := invoke.CommandWithContext(ctx, kstat, "-p", "unix:0:system_misc:boot_time")
if err != nil {
return 0, err
}
kstats := kstatMatch.FindAllStringSubmatch(string(out), -1)
if len(kstats) != 1 {
return 0, fmt.Errorf("expected 1 kstat, found %d", len(kstats))
}
return strconv.ParseUint(kstats[0][2], 10, 64)
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
bootTime, err := BootTime()
if err != nil {
return 0, err
}
return uptimeSince(bootTime), nil
}
func uptimeSince(since uint64) uint64 {
return uint64(time.Now().Unix()) - since
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return []UserStat{}, common.ErrNotImplementedError
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
// Parse versions from output of `uname(1)`
uname, err := exec.LookPath("/usr/bin/uname")
if err != nil {
return "", err
}
out, err := invoke.CommandWithContext(ctx, uname, "-srv")
if err != nil {
return "", err
}
fields := strings.Fields(string(out))
if len(fields) >= 2 {
return fields[1], nil
}
return "", fmt.Errorf("could not get kernel version")
}
func PlatformInformation() (platform string, family string, version string, err error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
/* This is not finished yet at all. Please contribute! */
version, err = KernelVersion()
if err != nil {
return "", "", "", err
}
return "solaris", "solaris", version, nil
}

View File

@ -1,295 +0,0 @@
// +build windows
package host
import (
"context"
"fmt"
"math"
"os"
"runtime"
"strings"
"sync/atomic"
"syscall"
"time"
"unsafe"
"github.com/StackExchange/wmi"
"github.com/shirou/gopsutil/internal/common"
process "github.com/shirou/gopsutil/process"
"golang.org/x/sys/windows"
)
var (
procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
procGetTickCount32 = common.Modkernel32.NewProc("GetTickCount")
procGetTickCount64 = common.Modkernel32.NewProc("GetTickCount64")
procRtlGetVersion = common.ModNt.NewProc("RtlGetVersion")
)
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
type osVersionInfoExW struct {
dwOSVersionInfoSize uint32
dwMajorVersion uint32
dwMinorVersion uint32
dwBuildNumber uint32
dwPlatformId uint32
szCSDVersion [128]uint16
wServicePackMajor uint16
wServicePackMinor uint16
wSuiteMask uint16
wProductType uint8
wReserved uint8
}
type msAcpi_ThermalZoneTemperature struct {
Active bool
CriticalTripPoint uint32
CurrentTemperature uint32
InstanceName string
}
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
}
{
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
}
{
platform, family, version, err := PlatformInformationWithContext(ctx)
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
} else {
return ret, err
}
}
{
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime, _ = Uptime()
}
}
{
hostID, err := getMachineGuid()
if err == nil {
ret.HostID = strings.ToLower(hostID)
}
}
{
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
}
return ret, nil
}
func getMachineGuid() (string, error) {
// there has been reports of issues on 32bit using golang.org/x/sys/windows/registry, see https://github.com/shirou/gopsutil/pull/312#issuecomment-277422612
// for rationale of using windows.RegOpenKeyEx/RegQueryValueEx instead of registry.OpenKey/GetStringValue
var h windows.Handle
err := windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Cryptography`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
if err != nil {
return "", err
}
defer windows.RegCloseKey(h)
const windowsRegBufLen = 74 // len(`{`) + len(`abcdefgh-1234-456789012-123345456671` * 2) + len(`}`) // 2 == bytes/UTF16
const uuidLen = 36
var regBuf [windowsRegBufLen]uint16
bufLen := uint32(windowsRegBufLen)
var valType uint32
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`MachineGuid`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
if err != nil {
return "", err
}
hostID := windows.UTF16ToString(regBuf[:])
hostIDLen := len(hostID)
if hostIDLen != uuidLen {
return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
}
return hostID, nil
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
procGetTickCount := procGetTickCount64
err := procGetTickCount64.Find()
if err != nil {
procGetTickCount = procGetTickCount32 // handle WinXP, but keep in mind that "the time will wrap around to zero if the system is run continuously for 49.7 days." from MSDN
}
r1, _, lastErr := syscall.Syscall(procGetTickCount.Addr(), 0, 0, 0, 0)
if lastErr != 0 {
return 0, lastErr
}
return uint64((time.Duration(r1) * time.Millisecond).Seconds()), nil
}
func bootTimeFromUptime(up uint64) uint64 {
return uint64(time.Now().Unix()) - up
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
up, err := Uptime()
if err != nil {
return 0, err
}
t = bootTimeFromUptime(up)
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
func PlatformInformation() (platform string, family string, version string, err error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
// GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest
// RtlGetVersion bypasses this lying layer and returns the true Windows version
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
var osInfo osVersionInfoExW
osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
if ret != 0 {
return
}
// Platform
var h windows.Handle // like getMachineGuid(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx
err = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Windows NT\CurrentVersion`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
if err != nil {
return
}
defer windows.RegCloseKey(h)
var bufLen uint32
var valType uint32
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, nil, &bufLen)
if err != nil {
return
}
regBuf := make([]uint16, bufLen/2+1)
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
if err != nil {
return
}
platform = windows.UTF16ToString(regBuf[:])
if !strings.HasPrefix(platform, "Microsoft") {
platform = "Microsoft " + platform
}
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CSDVersion`), nil, &valType, nil, &bufLen) // append Service Pack number, only on success
if err == nil { // don't return an error if only the Service Pack retrieval fails
regBuf = make([]uint16, bufLen/2+1)
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CSDVersion`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
if err == nil {
platform += " " + windows.UTF16ToString(regBuf[:])
}
}
// PlatformFamily
switch osInfo.wProductType {
case 1:
family = "Standalone Workstation"
case 2:
family = "Server (Domain Controller)"
case 3:
family = "Server"
}
// Platform Version
version = fmt.Sprintf("%d.%d.%d Build %d", osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, osInfo.dwBuildNumber)
return platform, family, version, nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
var ret []UserStat
return ret, nil
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
var ret []TemperatureStat
var dst []msAcpi_ThermalZoneTemperature
q := wmi.CreateQuery(&dst, "")
if err := common.WMIQueryWithContext(ctx, q, &dst, nil, "root/wmi"); err != nil {
return ret, err
}
for _, v := range dst {
ts := TemperatureStat{
SensorKey: v.InstanceName,
Temperature: kelvinToCelsius(v.CurrentTemperature, 2),
}
ret = append(ret, ts)
}
return ret, nil
}
func kelvinToCelsius(temp uint32, n int) float64 {
// wmi return temperature Kelvin * 10, so need to divide the result by 10,
// and then minus 273.15 to get °Celsius.
t := float64(temp/10) - 273.15
n10 := math.Pow10(n)
return math.Trunc((t+0.5/n10)*n10) / n10
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, err := PlatformInformation()
return version, err
}

View File

@ -1,17 +0,0 @@
// +build ignore
// plus hand editing about timeval
/*
Input to cgo -godefs.
*/
package host
/*
#include <sys/time.h>
#include <utmpx.h>
*/
import "C"
type Utmpx C.struct_utmpx
type Timeval C.struct_timeval

View File

@ -1,44 +0,0 @@
// +build ignore
/*
Input to cgo -godefs.
*/
package host
/*
#define KERNEL
#include <sys/types.h>
#include <sys/time.h>
#include <utmpx.h>
enum {
sizeofPtr = sizeof(void*),
};
*/
import "C"
// Machine characteristics; for internal use.
const (
sizeofPtr = C.sizeofPtr
sizeofShort = C.sizeof_short
sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong
sizeOfUtmpx = C.sizeof_struct_utmpx
)
// Basic types
type (
_C_short C.short
_C_int C.int
_C_long C.long
_C_long_long C.longlong
)
type Utmp C.struct_utmp
type Utmpx C.struct_utmpx
type Timeval C.struct_timeval

View File

@ -1,42 +0,0 @@
// +build ignore
/*
Input to cgo -godefs.
*/
package host
/*
#include <sys/types.h>
#include <utmp.h>
enum {
sizeofPtr = sizeof(void*),
};
*/
import "C"
// Machine characteristics; for internal use.
const (
sizeofPtr = C.sizeofPtr
sizeofShort = C.sizeof_short
sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong
sizeOfUtmp = C.sizeof_struct_utmp
)
// Basic types
type (
_C_short C.short
_C_int C.int
_C_long C.long
_C_long_long C.longlong
)
type utmp C.struct_utmp
type exit_status C.struct_exit_status
type timeval C.struct_timeval

View File

@ -1,43 +0,0 @@
// +build ignore
/*
Input to cgo -godefs.
*/
package host
/*
#define KERNEL
#include <sys/types.h>
#include <sys/time.h>
#include <utmp.h>
enum {
sizeofPtr = sizeof(void*),
};
*/
import "C"
// Machine characteristics; for internal use.
const (
sizeofPtr = C.sizeofPtr
sizeofShort = C.sizeof_short
sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong
sizeOfUtmp = C.sizeof_struct_utmp
)
// Basic types
type (
_C_short C.short
_C_int C.int
_C_long C.long
_C_long_long C.longlong
)
type Utmp C.struct_utmp
type Timeval C.struct_timeval

View File

@ -213,6 +213,12 @@ func ReadInts(filename string) ([]int64, error) {
return ret, nil return ret, nil
} }
// Parse Hex to uint32 without error
func HexToUint32(hex string) uint32 {
vv, _ := strconv.ParseUint(hex, 16, 32)
return uint32(vv)
}
// Parse to int32 without error // Parse to int32 without error
func mustParseInt32(val string) int32 { func mustParseInt32(val string) int32 {
vv, _ := strconv.ParseInt(val, 10, 32) vv, _ := strconv.ParseInt(val, 10, 32)
@ -332,49 +338,6 @@ func HostRun(combineWith ...string) string {
return GetEnv("HOST_RUN", "/run", combineWith...) return GetEnv("HOST_RUN", "/run", combineWith...)
} }
// https://gist.github.com/kylelemons/1525278
func Pipeline(cmds ...*exec.Cmd) ([]byte, []byte, error) {
// Require at least one command
if len(cmds) < 1 {
return nil, nil, nil
}
// Collect the output from the command(s)
var output bytes.Buffer
var stderr bytes.Buffer
last := len(cmds) - 1
for i, cmd := range cmds[:last] {
var err error
// Connect each command's stdin to the previous command's stdout
if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil {
return nil, nil, err
}
// Connect each command's stderr to a buffer
cmd.Stderr = &stderr
}
// Connect the output and error for the last command
cmds[last].Stdout, cmds[last].Stderr = &output, &stderr
// Start each command
for _, cmd := range cmds {
if err := cmd.Start(); err != nil {
return output.Bytes(), stderr.Bytes(), err
}
}
// Wait for each command to complete
for _, cmd := range cmds {
if err := cmd.Wait(); err != nil {
return output.Bytes(), stderr.Bytes(), err
}
}
// Return the pipeline output and the collected standard error
return output.Bytes(), stderr.Bytes(), nil
}
// getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running // getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running
// sysctl commands (see DoSysctrl). // sysctl commands (see DoSysctrl).
func getSysctrlEnv(env []string) []string { func getSysctrlEnv(env []string) []string {

View File

@ -13,7 +13,7 @@ import (
) )
func DoSysctrlWithContext(ctx context.Context, mib string) ([]string, error) { func DoSysctrlWithContext(ctx context.Context, mib string) ([]string, error) {
sysctl, err := exec.LookPath("/usr/sbin/sysctl") sysctl, err := exec.LookPath("sysctl")
if err != nil { if err != nil {
return []string{}, err return []string{}, err
} }

View File

@ -3,6 +3,7 @@
package common package common
import ( import (
"fmt"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
@ -11,8 +12,23 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
func SysctlUint(mib string) (uint64, error) {
buf, err := unix.SysctlRaw(mib)
if err != nil {
return 0, err
}
if len(buf) == 8 { // 64 bit
return *(*uint64)(unsafe.Pointer(&buf[0])), nil
}
if len(buf) == 4 { // 32bit
t := *(*uint32)(unsafe.Pointer(&buf[0]))
return uint64(t), nil
}
return 0, fmt.Errorf("unexpected size: %s, %d", mib, len(buf))
}
func DoSysctrl(mib string) ([]string, error) { func DoSysctrl(mib string) ([]string, error) {
sysctl, err := exec.LookPath("/sbin/sysctl") sysctl, err := exec.LookPath("sysctl")
if err != nil { if err != nil {
return []string{}, err return []string{}, err
} }

View File

@ -3,13 +3,19 @@
package common package common
import ( import (
"context"
"fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strconv"
"strings" "strings"
"sync/atomic"
"time"
) )
func DoSysctrl(mib string) ([]string, error) { func DoSysctrl(mib string) ([]string, error) {
sysctl, err := exec.LookPath("/sbin/sysctl") sysctl, err := exec.LookPath("sysctl")
if err != nil { if err != nil {
return []string{}, err return []string{}, err
} }
@ -39,3 +45,212 @@ func NumProcs() (uint64, error) {
} }
return uint64(len(list)), err return uint64(len(list)), err
} }
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
system, role, err := Virtualization()
if err != nil {
return 0, err
}
statFile := "stat"
if system == "lxc" && role == "guest" {
// if lxc, /proc/uptime is used.
statFile = "uptime"
} else if system == "docker" && role == "guest" {
// also docker, guest
statFile = "uptime"
}
filename := HostProc(statFile)
lines, err := ReadLines(filename)
if err != nil {
return 0, err
}
if statFile == "stat" {
for _, line := range lines {
if strings.HasPrefix(line, "btime") {
f := strings.Fields(line)
if len(f) != 2 {
return 0, fmt.Errorf("wrong btime format")
}
b, err := strconv.ParseInt(f[1], 10, 64)
if err != nil {
return 0, err
}
t = uint64(b)
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
}
} else if statFile == "uptime" {
if len(lines) != 1 {
return 0, fmt.Errorf("wrong uptime format")
}
f := strings.Fields(lines[0])
b, err := strconv.ParseFloat(f[0], 64)
if err != nil {
return 0, err
}
t = uint64(time.Now().Unix()) - uint64(b)
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
return 0, fmt.Errorf("could not find btime")
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
var system string
var role string
filename := HostProc("xen")
if PathExists(filename) {
system = "xen"
role = "guest" // assume guest
if PathExists(filepath.Join(filename, "capabilities")) {
contents, err := ReadLines(filepath.Join(filename, "capabilities"))
if err == nil {
if StringsContains(contents, "control_d") {
role = "host"
}
}
}
}
filename = HostProc("modules")
if PathExists(filename) {
contents, err := ReadLines(filename)
if err == nil {
if StringsContains(contents, "kvm") {
system = "kvm"
role = "host"
} else if StringsContains(contents, "vboxdrv") {
system = "vbox"
role = "host"
} else if StringsContains(contents, "vboxguest") {
system = "vbox"
role = "guest"
} else if StringsContains(contents, "vmware") {
system = "vmware"
role = "guest"
}
}
}
filename = HostProc("cpuinfo")
if PathExists(filename) {
contents, err := ReadLines(filename)
if err == nil {
if StringsContains(contents, "QEMU Virtual CPU") ||
StringsContains(contents, "Common KVM processor") ||
StringsContains(contents, "Common 32-bit KVM processor") {
system = "kvm"
role = "guest"
}
}
}
filename = HostProc("bus/pci/devices")
if PathExists(filename) {
contents, err := ReadLines(filename)
if err == nil {
if StringsContains(contents, "virtio-pci") {
role = "guest"
}
}
}
filename = HostProc()
if PathExists(filepath.Join(filename, "bc", "0")) {
system = "openvz"
role = "host"
} else if PathExists(filepath.Join(filename, "vz")) {
system = "openvz"
role = "guest"
}
// not use dmidecode because it requires root
if PathExists(filepath.Join(filename, "self", "status")) {
contents, err := ReadLines(filepath.Join(filename, "self", "status"))
if err == nil {
if StringsContains(contents, "s_context:") ||
StringsContains(contents, "VxID:") {
system = "linux-vserver"
}
// TODO: guest or host
}
}
if PathExists(filepath.Join(filename, "self", "cgroup")) {
contents, err := ReadLines(filepath.Join(filename, "self", "cgroup"))
if err == nil {
if StringsContains(contents, "lxc") {
system = "lxc"
role = "guest"
} else if StringsContains(contents, "docker") {
system = "docker"
role = "guest"
} else if StringsContains(contents, "machine-rkt") {
system = "rkt"
role = "guest"
} else if PathExists("/usr/bin/lxc-version") {
system = "lxc"
role = "host"
}
}
}
if PathExists(HostEtc("os-release")) {
p, _, err := GetOSRelease()
if err == nil && p == "coreos" {
system = "rkt" // Is it true?
role = "host"
}
}
return system, role, nil
}
func GetOSRelease() (platform string, version string, err error) {
contents, err := ReadLines(HostEtc("os-release"))
if err != nil {
return "", "", nil // return empty
}
for _, line := range contents {
field := strings.Split(line, "=")
if len(field) < 2 {
continue
}
switch field[0] {
case "ID": // use ID for lowercase
platform = trimQuotes(field[1])
case "VERSION":
version = trimQuotes(field[1])
}
}
return platform, version, nil
}
// Remove quotes of the source string
func trimQuotes(s string) string {
if len(s) >= 2 {
if s[0] == '"' && s[len(s)-1] == '"' {
return s[1 : len(s)-1]
}
}
return s
}

View File

@ -12,7 +12,7 @@ import (
) )
func DoSysctrl(mib string) ([]string, error) { func DoSysctrl(mib string) ([]string, error) {
sysctl, err := exec.LookPath("/sbin/sysctl") sysctl, err := exec.LookPath("sysctl")
if err != nil { if err != nil {
return []string{}, err return []string{}, err
} }

View File

@ -23,7 +23,7 @@ func CallLsofWithContext(ctx context.Context, invoke Invoker, pid int32, args ..
} }
out, err := invoke.CommandWithContext(ctx, lsof, cmd...) out, err := invoke.CommandWithContext(ctx, lsof, cmd...)
if err != nil { if err != nil {
// if no pid found, lsof returnes code 1. // if no pid found, lsof returns code 1.
if err.Error() == "exit status 1" && len(out) == 0 { if err.Error() == "exit status 1" && len(out) == 0 {
return []string{}, nil return []string{}, nil
} }

View File

@ -4,6 +4,9 @@ package common
import ( import (
"context" "context"
"path/filepath"
"strings"
"syscall"
"unsafe" "unsafe"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
@ -59,6 +62,8 @@ var (
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData") PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue") PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery") PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
procQueryDosDeviceW = Modkernel32.NewProc("QueryDosDeviceW")
) )
type FILETIME struct { type FILETIME struct {
@ -133,3 +138,23 @@ func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, con
return err return err
} }
} }
// Convert paths using native DOS format like:
// "\Device\HarddiskVolume1\Windows\systemew\file.txt"
// into:
// "C:\Windows\systemew\file.txt"
func ConvertDOSPath(p string) string {
rawDrive := strings.Join(strings.Split(p, `\`)[:3], `\`)
for d := 'A'; d <= 'Z'; d++ {
szDeviceName := string(d) + ":"
szTarget := make([]uint16, 512)
ret, _, _ := procQueryDosDeviceW.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(szDeviceName))),
uintptr(unsafe.Pointer(&szTarget[0])),
uintptr(len(szTarget)))
if ret != 0 && windows.UTF16ToString(szTarget[:]) == rawDrive {
return filepath.Join(szDeviceName, p[len(rawDrive):])
}
}
return p
}

View File

@ -84,6 +84,9 @@ type SwapMemoryStat struct {
UsedPercent float64 `json:"usedPercent"` UsedPercent float64 `json:"usedPercent"`
Sin uint64 `json:"sin"` Sin uint64 `json:"sin"`
Sout uint64 `json:"sout"` Sout uint64 `json:"sout"`
PgIn uint64 `json:"pgin"`
PgOut uint64 `json:"pgout"`
PgFault uint64 `json:"pgfault"`
} }
func (m VirtualMemoryStat) String() string { func (m VirtualMemoryStat) String() string {

View File

@ -5,10 +5,9 @@ package mem
import ( import (
"context" "context"
"encoding/binary" "encoding/binary"
"strconv" "fmt"
"strings" "unsafe"
"github.com/shirou/gopsutil/internal/common"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -27,46 +26,42 @@ func getHwMemsize() (uint64, error) {
return total, nil return total, nil
} }
// xsw_usage in sys/sysctl.h
type swapUsage struct {
Total uint64
Avail uint64
Used uint64
Pagesize int32
Encrypted bool
}
// SwapMemory returns swapinfo. // SwapMemory returns swapinfo.
func SwapMemory() (*SwapMemoryStat, error) { func SwapMemory() (*SwapMemoryStat, error) {
return SwapMemoryWithContext(context.Background()) return SwapMemoryWithContext(context.Background())
} }
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
// https://github.com/yanllearnn/go-osstat/blob/ae8a279d26f52ec946a03698c7f50a26cfb427e3/memory/memory_darwin.go
var ret *SwapMemoryStat var ret *SwapMemoryStat
swapUsage, err := common.DoSysctrlWithContext(ctx, "vm.swapusage") value, err := unix.SysctlRaw("vm.swapusage")
if err != nil { if err != nil {
return ret, err return ret, err
} }
if len(value) != 32 {
total := strings.Replace(swapUsage[2], "M", "", 1) return ret, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", value, len(value))
used := strings.Replace(swapUsage[5], "M", "", 1)
free := strings.Replace(swapUsage[8], "M", "", 1)
total_v, err := strconv.ParseFloat(total, 64)
if err != nil {
return nil, err
}
used_v, err := strconv.ParseFloat(used, 64)
if err != nil {
return nil, err
}
free_v, err := strconv.ParseFloat(free, 64)
if err != nil {
return nil, err
} }
swap := (*swapUsage)(unsafe.Pointer(&value[0]))
u := float64(0) u := float64(0)
if total_v != 0 { if swap.Total != 0 {
u = ((total_v - free_v) / total_v) * 100.0 u = ((float64(swap.Total) - float64(swap.Avail)) / float64(swap.Total)) * 100.0
} }
// vm.swapusage shows "M", multiply 1024 * 1024 to convert bytes.
ret = &SwapMemoryStat{ ret = &SwapMemoryStat{
Total: uint64(total_v * 1024 * 1024), Total: swap.Total,
Used: uint64(used_v * 1024 * 1024), Used: swap.Used,
Free: uint64(free_v * 1024 * 1024), Free: swap.Avail,
UsedPercent: u, UsedPercent: u,
} }

View File

@ -8,6 +8,8 @@ import (
"unsafe" "unsafe"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"github.com/shirou/gopsutil/internal/common"
) )
func VirtualMemory() (*VirtualMemoryStat, error) { func VirtualMemory() (*VirtualMemoryStat, error) {
@ -15,58 +17,59 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
} }
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
pageSize, err := unix.SysctlUint32("vm.stats.vm.v_page_size") pageSize, err := common.SysctlUint("vm.stats.vm.v_page_size")
if err != nil { if err != nil {
return nil, err return nil, err
} }
physmem, err := unix.SysctlUint64("hw.physmem") physmem, err := common.SysctlUint("hw.physmem")
if err != nil { if err != nil {
return nil, err return nil, err
} }
free, err := unix.SysctlUint32("vm.stats.vm.v_free_count")
free, err := common.SysctlUint("vm.stats.vm.v_free_count")
if err != nil { if err != nil {
return nil, err return nil, err
} }
active, err := unix.SysctlUint32("vm.stats.vm.v_active_count") active, err := common.SysctlUint("vm.stats.vm.v_active_count")
if err != nil { if err != nil {
return nil, err return nil, err
} }
inactive, err := unix.SysctlUint32("vm.stats.vm.v_inactive_count") inactive, err := common.SysctlUint("vm.stats.vm.v_inactive_count")
if err != nil { if err != nil {
return nil, err return nil, err
} }
buffers, err := unix.SysctlUint64("vfs.bufspace") buffers, err := common.SysctlUint("vfs.bufspace")
if err != nil { if err != nil {
return nil, err return nil, err
} }
wired, err := unix.SysctlUint32("vm.stats.vm.v_wire_count") wired, err := common.SysctlUint("vm.stats.vm.v_wire_count")
if err != nil { if err != nil {
return nil, err return nil, err
} }
var cached, laundry uint32 var cached, laundry uint64
osreldate, _ := unix.SysctlUint32("kern.osreldate") osreldate, _ := common.SysctlUint("kern.osreldate")
if osreldate < 1102000 { if osreldate < 1102000 {
cached, err = unix.SysctlUint32("vm.stats.vm.v_cache_count") cached, err = common.SysctlUint("vm.stats.vm.v_cache_count")
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
laundry, err = unix.SysctlUint32("vm.stats.vm.v_laundry_count") laundry, err = common.SysctlUint("vm.stats.vm.v_laundry_count")
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
p := uint64(pageSize) p := pageSize
ret := &VirtualMemoryStat{ ret := &VirtualMemoryStat{
Total: uint64(physmem), Total: physmem,
Free: uint64(free) * p, Free: free * p,
Active: uint64(active) * p, Active: active * p,
Inactive: uint64(inactive) * p, Inactive: inactive * p,
Cached: uint64(cached) * p, Cached: cached * p,
Buffers: uint64(buffers), Buffers: buffers,
Wired: uint64(wired) * p, Wired: wired * p,
Laundry: uint64(laundry) * p, Laundry: laundry * p,
} }
ret.Available = ret.Inactive + ret.Cached + ret.Free + ret.Laundry ret.Available = ret.Inactive + ret.Cached + ret.Free + ret.Laundry
@ -84,11 +87,22 @@ func SwapMemory() (*SwapMemoryStat, error) {
// Constants from vm/vm_param.h // Constants from vm/vm_param.h
// nolint: golint // nolint: golint
const ( const (
XSWDEV_VERSION = 1 XSWDEV_VERSION11 = 1
XSWDEV_VERSION = 2
) )
// Types from vm/vm_param.h // Types from vm/vm_param.h
type xswdev struct { type xswdev struct {
Version uint32 // Version is the version
Dev uint64 // Dev is the device identifier
Flags int32 // Flags is the swap flags applied to the device
NBlks int32 // NBlks is the total number of blocks
Used int32 // Used is the number of blocks used
}
// xswdev11 is a compatibility for under FreeBSD 11
// sys/vm/swap_pager.c
type xswdev11 struct {
Version uint32 // Version is the version Version uint32 // Version is the version
Dev uint32 // Dev is the device identifier Dev uint32 // Dev is the device identifier
Flags int32 // Flags is the swap flags applied to the device Flags int32 // Flags is the swap flags applied to the device
@ -98,7 +112,7 @@ type xswdev struct {
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
// FreeBSD can have multiple swap devices so we total them up // FreeBSD can have multiple swap devices so we total them up
i, err := unix.SysctlUint32("vm.nswapdev") i, err := common.SysctlUint("vm.nswapdev")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -109,11 +123,11 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
c := int(i) c := int(i)
i, err = unix.SysctlUint32("vm.stats.vm.v_page_size") i, err = common.SysctlUint("vm.stats.vm.v_page_size")
if err != nil { if err != nil {
return nil, err return nil, err
} }
pageSize := uint64(i) pageSize := i
var buf []byte var buf []byte
s := &SwapMemoryStat{} s := &SwapMemoryStat{}
@ -123,12 +137,23 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
return nil, err return nil, err
} }
// first, try to parse with version 2
xsw := (*xswdev)(unsafe.Pointer(&buf[0])) xsw := (*xswdev)(unsafe.Pointer(&buf[0]))
if xsw.Version != XSWDEV_VERSION { if xsw.Version == XSWDEV_VERSION11 {
// this is version 1, so try to parse again
xsw := (*xswdev11)(unsafe.Pointer(&buf[0]))
if xsw.Version != XSWDEV_VERSION11 {
return nil, errors.New("xswdev version mismatch(11)")
}
s.Total += uint64(xsw.NBlks)
s.Used += uint64(xsw.Used)
} else if xsw.Version != XSWDEV_VERSION {
return nil, errors.New("xswdev version mismatch") return nil, errors.New("xswdev version mismatch")
} else {
s.Total += uint64(xsw.NBlks)
s.Used += uint64(xsw.Used)
} }
s.Total += uint64(xsw.NBlks)
s.Used += uint64(xsw.Used)
} }
if s.Total != 0 { if s.Total != 0 {

View File

@ -4,6 +4,8 @@ package mem
import ( import (
"context" "context"
"math"
"os"
"strconv" "strconv"
"strings" "strings"
@ -11,6 +13,11 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
type VirtualMemoryExStat struct {
ActiveFile uint64 `json:"activefile"`
InactiveFile uint64 `json:"inactivefile"`
}
func VirtualMemory() (*VirtualMemoryStat, error) { func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background()) return VirtualMemoryWithContext(context.Background())
} }
@ -18,10 +25,16 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
filename := common.HostProc("meminfo") filename := common.HostProc("meminfo")
lines, _ := common.ReadLines(filename) lines, _ := common.ReadLines(filename)
// flag if MemAvailable is in /proc/meminfo (kernel 3.14+) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
memavail := false memavail := false
activeFile := false // "Active(file)" not available: 2.6.28 / Dec 2008
inactiveFile := false // "Inactive(file)" not available: 2.6.28 / Dec 2008
sReclaimable := false // "SReclaimable:" not available: 2.6.19 / Nov 2006
ret := &VirtualMemoryStat{} ret := &VirtualMemoryStat{}
retEx := &VirtualMemoryExStat{}
for _, line := range lines { for _, line := range lines {
fields := strings.Split(line, ":") fields := strings.Split(line, ":")
if len(fields) != 2 { if len(fields) != 2 {
@ -51,6 +64,12 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
ret.Active = t * 1024 ret.Active = t * 1024
case "Inactive": case "Inactive":
ret.Inactive = t * 1024 ret.Inactive = t * 1024
case "Active(file)":
activeFile = true
retEx.ActiveFile = t * 1024
case "InActive(file)":
inactiveFile = true
retEx.InactiveFile = t * 1024
case "Writeback": case "Writeback":
ret.Writeback = t * 1024 ret.Writeback = t * 1024
case "WritebackTmp": case "WritebackTmp":
@ -62,6 +81,7 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
case "Slab": case "Slab":
ret.Slab = t * 1024 ret.Slab = t * 1024
case "SReclaimable": case "SReclaimable":
sReclaimable = true
ret.SReclaimable = t * 1024 ret.SReclaimable = t * 1024
case "PageTables": case "PageTables":
ret.PageTables = t * 1024 ret.PageTables = t * 1024
@ -103,8 +123,13 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
ret.Cached += ret.SReclaimable ret.Cached += ret.SReclaimable
if !memavail { if !memavail {
ret.Available = ret.Free + ret.Buffers + ret.Cached if activeFile && inactiveFile && sReclaimable {
ret.Available = calcuateAvailVmem(ret, retEx)
} else {
ret.Available = ret.Cached + ret.Free
}
} }
ret.Used = ret.Total - ret.Free - ret.Buffers - ret.Cached ret.Used = ret.Total - ret.Free - ret.Buffers - ret.Cached
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0 ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
@ -152,7 +177,69 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
continue continue
} }
ret.Sout = value * 4 * 1024 ret.Sout = value * 4 * 1024
case "pgpgin":
value, err := strconv.ParseUint(fields[1], 10, 64)
if err != nil {
continue
}
ret.PgIn = value * 4 * 1024
case "pgpgout":
value, err := strconv.ParseUint(fields[1], 10, 64)
if err != nil {
continue
}
ret.PgOut = value * 4 * 1024
case "pgfault":
value, err := strconv.ParseUint(fields[1], 10, 64)
if err != nil {
continue
}
ret.PgFault = value * 4 * 1024
} }
} }
return ret, nil return ret, nil
} }
// calcuateAvailVmem is a fallback under kernel 3.14 where /proc/meminfo does not provide
// "MemAvailable:" column. It reimplements an algorithm from the link below
// https://github.com/giampaolo/psutil/pull/890
func calcuateAvailVmem(ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint64 {
var watermarkLow uint64
fn := common.HostProc("zoneinfo")
lines, err := common.ReadLines(fn)
if err != nil {
return ret.Free + ret.Cached // fallback under kernel 2.6.13
}
pagesize := uint64(os.Getpagesize())
watermarkLow = 0
for _, line := range lines {
fields := strings.Fields(line)
if strings.HasPrefix(fields[0], "low") {
lowValue, err := strconv.ParseUint(fields[1], 10, 64)
if err != nil {
lowValue = 0
}
watermarkLow += lowValue
}
}
watermarkLow *= pagesize
availMemory := ret.Free - watermarkLow
pageCache := retEx.ActiveFile + retEx.InactiveFile
pageCache -= uint64(math.Min(float64(pageCache/2), float64(watermarkLow)))
availMemory += pageCache
availMemory += ret.SReclaimable - uint64(math.Min(float64(ret.SReclaimable/2.0), float64(watermarkLow)))
if availMemory < 0 {
availMemory = 0
}
return availMemory
}

View File

@ -52,7 +52,7 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
} }
func zoneName() (string, error) { func zoneName() (string, error) {
zonename, err := exec.LookPath("/usr/bin/zonename") zonename, err := exec.LookPath("zonename")
if err != nil { if err != nil {
return "", err return "", err
} }
@ -69,7 +69,7 @@ func zoneName() (string, error) {
var globalZoneMemoryCapacityMatch = regexp.MustCompile(`memory size: ([\d]+) Megabytes`) var globalZoneMemoryCapacityMatch = regexp.MustCompile(`memory size: ([\d]+) Megabytes`)
func globalZoneMemoryCapacity() (uint64, error) { func globalZoneMemoryCapacity() (uint64, error) {
prtconf, err := exec.LookPath("/usr/sbin/prtconf") prtconf, err := exec.LookPath("prtconf")
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -96,7 +96,7 @@ func globalZoneMemoryCapacity() (uint64, error) {
var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`) var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
func nonGlobalZoneMemoryCapacity() (uint64, error) { func nonGlobalZoneMemoryCapacity() (uint64, error) {
kstat, err := exec.LookPath("/usr/bin/kstat") kstat, err := exec.LookPath("kstat")
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@ -70,6 +70,96 @@ type FilterStat struct {
ConnTrackMax int64 `json:"conntrackMax"` ConnTrackMax int64 `json:"conntrackMax"`
} }
// ConntrackStat has conntrack summary info
type ConntrackStat struct {
Entries uint32 `json:"entries"` // Number of entries in the conntrack table
Searched uint32 `json:"searched"` // Number of conntrack table lookups performed
Found uint32 `json:"found"` // Number of searched entries which were successful
New uint32 `json:"new"` // Number of entries added which were not expected before
Invalid uint32 `json:"invalid"` // Number of packets seen which can not be tracked
Ignore uint32 `json:"ignore"` // Packets seen which are already connected to an entry
Delete uint32 `json:"delete"` // Number of entries which were removed
DeleteList uint32 `json:"delete_list"` // Number of entries which were put to dying list
Insert uint32 `json:"insert"` // Number of entries inserted into the list
InsertFailed uint32 `json:"insert_failed"` // # insertion attempted but failed (same entry exists)
Drop uint32 `json:"drop"` // Number of packets dropped due to conntrack failure.
EarlyDrop uint32 `json:"early_drop"` // Dropped entries to make room for new ones, if maxsize reached
IcmpError uint32 `json:"icmp_error"` // Subset of invalid. Packets that can't be tracked d/t error
ExpectNew uint32 `json:"expect_new"` // Entries added after an expectation was already present
ExpectCreate uint32 `json:"expect_create"` // Expectations added
ExpectDelete uint32 `json:"expect_delete"` // Expectations deleted
SearchRestart uint32 `json:"search_restart"` // Conntrack table lookups restarted due to hashtable resizes
}
func NewConntrackStat(e uint32, s uint32, f uint32, n uint32, inv uint32, ign uint32, del uint32, dlst uint32, ins uint32, insfail uint32, drop uint32, edrop uint32, ie uint32, en uint32, ec uint32, ed uint32, sr uint32) *ConntrackStat {
return &ConntrackStat{
Entries: e,
Searched: s,
Found: f,
New: n,
Invalid: inv,
Ignore: ign,
Delete: del,
DeleteList: dlst,
Insert: ins,
InsertFailed: insfail,
Drop: drop,
EarlyDrop: edrop,
IcmpError: ie,
ExpectNew: en,
ExpectCreate: ec,
ExpectDelete: ed,
SearchRestart: sr,
}
}
type ConntrackStatList struct {
items []*ConntrackStat
}
func NewConntrackStatList() *ConntrackStatList {
return &ConntrackStatList{
items: []*ConntrackStat{},
}
}
func (l *ConntrackStatList) Append(c *ConntrackStat) {
l.items = append(l.items, c)
}
func (l *ConntrackStatList) Items() []ConntrackStat {
items := make([]ConntrackStat, len(l.items), len(l.items))
for i, el := range l.items {
items[i] = *el
}
return items
}
// Summary returns a single-element list with totals from all list items.
func (l *ConntrackStatList) Summary() []ConntrackStat {
summary := NewConntrackStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
for _, cs := range l.items {
summary.Entries += cs.Entries
summary.Searched += cs.Searched
summary.Found += cs.Found
summary.New += cs.New
summary.Invalid += cs.Invalid
summary.Ignore += cs.Ignore
summary.Delete += cs.Delete
summary.DeleteList += cs.DeleteList
summary.Insert += cs.Insert
summary.InsertFailed += cs.InsertFailed
summary.Drop += cs.Drop
summary.EarlyDrop += cs.EarlyDrop
summary.IcmpError += cs.IcmpError
summary.ExpectNew += cs.ExpectNew
summary.ExpectCreate += cs.ExpectCreate
summary.ExpectDelete += cs.ExpectDelete
summary.SearchRestart += cs.SearchRestart
}
return []ConntrackStat{*summary}
}
var constMap = map[string]int{ var constMap = map[string]int{
"unix": syscall.AF_UNIX, "unix": syscall.AF_UNIX,
"TCP": syscall.SOCK_STREAM, "TCP": syscall.SOCK_STREAM,
@ -108,6 +198,11 @@ func (n InterfaceAddr) String() string {
return string(s) return string(s)
} }
func (n ConntrackStat) String() string {
s, _ := json.Marshal(n)
return string(s)
}
func Interfaces() ([]InterfaceStat, error) { func Interfaces() ([]InterfaceStat, error) {
return InterfacesWithContext(context.Background()) return InterfacesWithContext(context.Background())
} }

View File

@ -6,6 +6,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/shirou/gopsutil/internal/common"
"os/exec" "os/exec"
"regexp" "regexp"
"strconv" "strconv"
@ -42,7 +43,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
base := 1 base := 1
numberColumns := len(columns) numberColumns := len(columns)
// sometimes Address is ommitted // sometimes Address is omitted
if numberColumns < 12 { if numberColumns < 12 {
base = 0 base = 0
} }
@ -174,7 +175,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
retIndex int retIndex int
) )
netstat, err := exec.LookPath("/usr/sbin/netstat") netstat, err := exec.LookPath("netstat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -204,7 +205,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
} }
} else { } else {
// duplicated interface, list all interfaces // duplicated interface, list all interfaces
ifconfig, err := exec.LookPath("/sbin/ifconfig") ifconfig, err := exec.LookPath("ifconfig")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -271,6 +272,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
return nil, errors.New("NetFilterCounters not implemented for darwin") return nil, errors.New("NetFilterCounters not implemented for darwin")
} }
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
return ConntrackStatsWithContext(context.Background(), percpu)
}
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
// NetProtoCounters returns network statistics for the entire system // NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise // If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned. // just the protocols in the list are returned.

View File

@ -24,6 +24,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
return []FilterStat{}, common.ErrNotImplementedError return []FilterStat{}, common.ErrNotImplementedError
} }
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
return ConntrackStatsWithContext(context.Background(), percpu)
}
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
return ProtoCountersWithContext(context.Background(), protocols) return ProtoCountersWithContext(context.Background(), protocols)
} }

View File

@ -17,7 +17,7 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
} }
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
netstat, err := exec.LookPath("/usr/bin/netstat") netstat, err := exec.LookPath("netstat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -45,7 +45,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
continue continue
} }
base := 1 base := 1
// sometimes Address is ommitted // sometimes Address is omitted
if len(values) < 13 { if len(values) < 13 {
base = 0 base = 0
} }
@ -112,6 +112,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
return nil, errors.New("NetFilterCounters not implemented for freebsd") return nil, errors.New("NetFilterCounters not implemented for freebsd")
} }
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
return ConntrackStatsWithContext(context.Background(), percpu)
}
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return nil, errors.New("ConntrackStats not implemented for freebsd")
}
// NetProtoCounters returns network statistics for the entire system // NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise // If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned. // just the protocols in the list are returned.

View File

@ -18,6 +18,26 @@ import (
"github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/internal/common"
) )
const ( // Conntrack Column numbers
CT_ENTRIES = iota
CT_SEARCHED
CT_FOUND
CT_NEW
CT_INVALID
CT_IGNORE
CT_DELETE
CT_DELETE_LIST
CT_INSERT
CT_INSERT_FAILED
CT_DROP
CT_EARLY_DROP
CT_ICMP_ERROR
CT_EXPECT_NEW
CT_EXPECT_CREATE
CT_EXPECT_DELETE
CT_SEARCH_RESTART
)
// NetIOCounters returnes network I/O statistics for every network // NetIOCounters returnes network I/O statistics for every network
// interface installed on the system. If pernic argument is false, // interface installed on the system. If pernic argument is false,
// return only sum of all information (which name is 'all'). If true, // return only sum of all information (which name is 'all'). If true,
@ -232,6 +252,58 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
return stats, nil return stats, nil
} }
// ConntrackStats returns more detailed info about the conntrack table
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
return ConntrackStatsWithContext(context.Background(), percpu)
}
// ConntrackStatsWithContext returns more detailed info about the conntrack table
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return conntrackStatsFromFile(common.HostProc("net/stat/nf_conntrack"), percpu)
}
// conntrackStatsFromFile returns more detailed info about the conntrack table
// from `filename`
// If 'percpu' is false, the result will contain exactly one item with totals/summary
func conntrackStatsFromFile(filename string, percpu bool) ([]ConntrackStat, error) {
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err
}
statlist := NewConntrackStatList()
for _, line := range lines {
fields := strings.Fields(line)
if len(fields) == 17 && fields[0] != "entries" {
statlist.Append(NewConntrackStat(
common.HexToUint32(fields[CT_ENTRIES]),
common.HexToUint32(fields[CT_SEARCHED]),
common.HexToUint32(fields[CT_FOUND]),
common.HexToUint32(fields[CT_NEW]),
common.HexToUint32(fields[CT_INVALID]),
common.HexToUint32(fields[CT_IGNORE]),
common.HexToUint32(fields[CT_DELETE]),
common.HexToUint32(fields[CT_DELETE_LIST]),
common.HexToUint32(fields[CT_INSERT]),
common.HexToUint32(fields[CT_INSERT_FAILED]),
common.HexToUint32(fields[CT_DROP]),
common.HexToUint32(fields[CT_EARLY_DROP]),
common.HexToUint32(fields[CT_ICMP_ERROR]),
common.HexToUint32(fields[CT_EXPECT_NEW]),
common.HexToUint32(fields[CT_EXPECT_CREATE]),
common.HexToUint32(fields[CT_EXPECT_DELETE]),
common.HexToUint32(fields[CT_SEARCH_RESTART]),
))
}
}
if percpu {
return statlist.Items(), nil
}
return statlist.Summary(), nil
}
// http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h // http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
var TCPStatuses = map[string]string{ var TCPStatuses = map[string]string{
"01": "ESTABLISHED", "01": "ESTABLISHED",

View File

@ -41,7 +41,7 @@ func ParseNetstat(output string, mode string,
continue continue
} }
base := 1 base := 1
// sometimes Address is ommitted // sometimes Address is omitted
if len(values) < columns { if len(values) < columns {
base = 0 base = 0
} }
@ -156,6 +156,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
return nil, errors.New("NetFilterCounters not implemented for openbsd") return nil, errors.New("NetFilterCounters not implemented for openbsd")
} }
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
return ConntrackStatsWithContext(context.Background(), percpu)
}
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
// NetProtoCounters returns network statistics for the entire system // NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise // If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned. // just the protocols in the list are returned.

View File

@ -19,6 +19,7 @@ var (
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
procGetExtendedTCPTable = modiphlpapi.NewProc("GetExtendedTcpTable") procGetExtendedTCPTable = modiphlpapi.NewProc("GetExtendedTcpTable")
procGetExtendedUDPTable = modiphlpapi.NewProc("GetExtendedUdpTable") procGetExtendedUDPTable = modiphlpapi.NewProc("GetExtendedUdpTable")
procGetIfEntry2 = modiphlpapi.NewProc("GetIfEntry2")
) )
const ( const (
@ -73,6 +74,65 @@ var netConnectionKindMap = map[string][]netConnectionKindType{
"inet6": {kindTCP6, kindUDP6}, "inet6": {kindTCP6, kindUDP6},
} }
// https://github.com/microsoft/ethr/blob/aecdaf923970e5a9b4c461b4e2e3963d781ad2cc/plt_windows.go#L114-L170
type guid struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
const (
maxStringSize = 256
maxPhysAddressLength = 32
pad0for64_4for32 = 0
)
type mibIfRow2 struct {
InterfaceLuid uint64
InterfaceIndex uint32
InterfaceGuid guid
Alias [maxStringSize + 1]uint16
Description [maxStringSize + 1]uint16
PhysicalAddressLength uint32
PhysicalAddress [maxPhysAddressLength]uint8
PermanentPhysicalAddress [maxPhysAddressLength]uint8
Mtu uint32
Type uint32
TunnelType uint32
MediaType uint32
PhysicalMediumType uint32
AccessType uint32
DirectionType uint32
InterfaceAndOperStatusFlags uint32
OperStatus uint32
AdminStatus uint32
MediaConnectState uint32
NetworkGuid guid
ConnectionType uint32
padding1 [pad0for64_4for32]byte
TransmitLinkSpeed uint64
ReceiveLinkSpeed uint64
InOctets uint64
InUcastPkts uint64
InNUcastPkts uint64
InDiscards uint64
InErrors uint64
InUnknownProtos uint64
InUcastOctets uint64
InMulticastOctets uint64
InBroadcastOctets uint64
OutOctets uint64
OutUcastPkts uint64
OutNUcastPkts uint64
OutDiscards uint64
OutErrors uint64
OutUcastOctets uint64
OutMulticastOctets uint64
OutBroadcastOctets uint64
OutQLen uint64
}
func IOCounters(pernic bool) ([]IOCountersStat, error) { func IOCounters(pernic bool) ([]IOCountersStat, error) {
return IOCountersWithContext(context.Background(), pernic) return IOCountersWithContext(context.Background(), pernic)
} }
@ -82,34 +142,59 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
if err != nil { if err != nil {
return nil, err return nil, err
} }
var ret []IOCountersStat var counters []IOCountersStat
for _, ifi := range ifs { err = procGetIfEntry2.Find()
c := IOCountersStat{ if err == nil { // Vista+, uint64 values (issue#693)
Name: ifi.Name, for _, ifi := range ifs {
c := IOCountersStat{
Name: ifi.Name,
}
row := mibIfRow2{InterfaceIndex: uint32(ifi.Index)}
ret, _, err := procGetIfEntry2.Call(uintptr(unsafe.Pointer(&row)))
if ret != 0 {
return nil, os.NewSyscallError("GetIfEntry2", err)
}
c.BytesSent = uint64(row.OutOctets)
c.BytesRecv = uint64(row.InOctets)
c.PacketsSent = uint64(row.OutUcastPkts)
c.PacketsRecv = uint64(row.InUcastPkts)
c.Errin = uint64(row.InErrors)
c.Errout = uint64(row.OutErrors)
c.Dropin = uint64(row.InDiscards)
c.Dropout = uint64(row.OutDiscards)
counters = append(counters, c)
} }
} else { // WinXP fallback, uint32 values
for _, ifi := range ifs {
c := IOCountersStat{
Name: ifi.Name,
}
row := windows.MibIfRow{Index: uint32(ifi.Index)} row := windows.MibIfRow{Index: uint32(ifi.Index)}
e := windows.GetIfEntry(&row) err = windows.GetIfEntry(&row)
if e != nil { if err != nil {
return nil, os.NewSyscallError("GetIfEntry", e) return nil, os.NewSyscallError("GetIfEntry", err)
}
c.BytesSent = uint64(row.OutOctets)
c.BytesRecv = uint64(row.InOctets)
c.PacketsSent = uint64(row.OutUcastPkts)
c.PacketsRecv = uint64(row.InUcastPkts)
c.Errin = uint64(row.InErrors)
c.Errout = uint64(row.OutErrors)
c.Dropin = uint64(row.InDiscards)
c.Dropout = uint64(row.OutDiscards)
counters = append(counters, c)
} }
c.BytesSent = uint64(row.OutOctets)
c.BytesRecv = uint64(row.InOctets)
c.PacketsSent = uint64(row.OutUcastPkts)
c.PacketsRecv = uint64(row.InUcastPkts)
c.Errin = uint64(row.InErrors)
c.Errout = uint64(row.OutErrors)
c.Dropin = uint64(row.InDiscards)
c.Dropout = uint64(row.OutDiscards)
ret = append(ret, c)
} }
if pernic == false { if !pernic {
return getIOCountersAll(ret) return getIOCountersAll(counters)
} }
return ret, nil return counters, nil
} }
// NetIOCountersByFile is an method which is added just a compatibility for linux. // NetIOCountersByFile is an method which is added just a compatibility for linux.
@ -206,6 +291,15 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
return nil, errors.New("NetFilterCounters not implemented for windows") return nil, errors.New("NetFilterCounters not implemented for windows")
} }
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
return ConntrackStatsWithContext(context.Background(), percpu)
}
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
// NetProtoCounters returns network statistics for the entire system // NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise // If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned. // just the protocols in the list are returned.

View File

@ -43,6 +43,7 @@ type OpenFilesStat struct {
type MemoryInfoStat struct { type MemoryInfoStat struct {
RSS uint64 `json:"rss"` // bytes RSS uint64 `json:"rss"` // bytes
VMS uint64 `json:"vms"` // bytes VMS uint64 `json:"vms"` // bytes
HWM uint64 `json:"hwm"` // bytes
Data uint64 `json:"data"` // bytes Data uint64 `json:"data"` // bytes
Stack uint64 `json:"stack"` // bytes Stack uint64 `json:"stack"` // bytes
Locked uint64 `json:"locked"` // bytes Locked uint64 `json:"locked"` // bytes
@ -76,6 +77,13 @@ type NumCtxSwitchesStat struct {
Involuntary int64 `json:"involuntary"` 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 // Resource limit constants are from /usr/include/x86_64-linux-gnu/bits/resource.h
// from libc6-dev package in Ubuntu 16.10 // from libc6-dev package in Ubuntu 16.10
const ( const (

View File

@ -108,30 +108,21 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
out, err := invoke.CommandWithContext(ctx, lsof_bin, "-p", strconv.Itoa(int(p.Pid)), "-Fpfn")
awk_bin, err := exec.LookPath("awk")
if err != nil { if err != nil {
return "", err return "", fmt.Errorf("bad call to lsof: %s", err)
} }
txtFound := 0
sed_bin, err := exec.LookPath("sed") lines := strings.Split(string(out), "\n")
if err != nil { for i := 1; i < len(lines); i += 2 {
return "", err if lines[i] == "ftxt" {
txtFound++
if txtFound == 2 {
return lines[i-1][1:], nil
}
}
} }
return "", fmt.Errorf("missing txt data returned by lsof")
lsof := exec.CommandContext(ctx, lsof_bin, "-p", strconv.Itoa(int(p.Pid)), "-Fpfn")
awk := exec.CommandContext(ctx, awk_bin, "NR==5{print}")
sed := exec.CommandContext(ctx, sed_bin, "s/n\\//\\//")
output, _, err := common.Pipeline(lsof, awk, sed)
if err != nil {
return "", err
}
ret := strings.TrimSpace(string(output))
return ret, nil
} }
// Cmdline returns the command line arguments of the process as a string with // Cmdline returns the command line arguments of the process as a string with
@ -389,12 +380,32 @@ func convertCPUTimes(s string) (ret float64, err error) {
var _tmp string var _tmp string
if strings.Contains(s, ":") { if strings.Contains(s, ":") {
_t := strings.Split(s, ":") _t := strings.Split(s, ":")
hour, err := strconv.Atoi(_t[0]) switch len(_t) {
if err != nil { case 3:
return ret, err hour, err := strconv.Atoi(_t[0])
if err != nil {
return ret, err
}
t += hour * 60 * 60 * ClockTicks
mins, err := strconv.Atoi(_t[1])
if err != nil {
return ret, err
}
t += mins * 60 * ClockTicks
_tmp = _t[2]
case 2:
mins, err := strconv.Atoi(_t[0])
if err != nil {
return ret, err
}
t += mins * 60 * ClockTicks
_tmp = _t[1]
case 1, 0:
_tmp = s
default:
return ret, fmt.Errorf("wrong cpu time string")
} }
t += hour * 60 * 100
_tmp = _t[1]
} else { } else {
_tmp = s _tmp = s
} }
@ -404,7 +415,7 @@ func convertCPUTimes(s string) (ret float64, err error) {
return ret, err return ret, err
} }
h, err := strconv.Atoi(_t[0]) h, err := strconv.Atoi(_t[0])
t += h * 100 t += h * ClockTicks
h, err = strconv.Atoi(_t[1]) h, err = strconv.Atoi(_t[1])
t += h t += h
return float64(t) / ClockTicks, nil return float64(t) / ClockTicks, nil
@ -481,6 +492,14 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
func (p *Process) PageFaults() (*PageFaultsStat, error) {
return p.PageFaultsWithContext(context.Background())
}
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return p.ChildrenWithContext(context.Background()) return p.ChildrenWithContext(context.Background())
} }
@ -517,6 +536,15 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
return net.ConnectionsPid("all", p.Pid) return net.ConnectionsPid("all", p.Pid)
} }
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
return p.ConnectionsMaxWithContext(context.Background(), max)
}
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
return net.ConnectionsPidMax("all", p.Pid, max)
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return p.NetIOCountersWithContext(context.Background(), pernic) return p.NetIOCountersWithContext(context.Background(), pernic)
} }

View File

@ -233,6 +233,12 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
func (p *Process) PageFaults() (*PageFaultsStat, error) {
return p.PageFaultsWithContext(context.Background())
}
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return p.ChildrenWithContext(context.Background()) return p.ChildrenWithContext(context.Background())
} }
@ -254,6 +260,15 @@ func (p *Process) Connections() ([]net.ConnectionStat, error) {
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) { func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
return []net.ConnectionStat{}, common.ErrNotImplementedError return []net.ConnectionStat{}, common.ErrNotImplementedError
} }
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
return p.ConnectionsMaxWithContext(context.Background(), max)
}
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
return []net.ConnectionStat{}, common.ErrNotImplementedError
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return p.NetIOCountersWithContext(context.Background(), pernic) return p.NetIOCountersWithContext(context.Background(), pernic)
} }

View File

@ -371,6 +371,14 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
func (p *Process) PageFaults() (*PageFaultsStat, error) {
return p.PageFaultsWithContext(context.Background())
}
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return p.ChildrenWithContext(context.Background()) return p.ChildrenWithContext(context.Background())
} }
@ -407,6 +415,15 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
return p.ConnectionsMaxWithContext(context.Background(), max)
}
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
return []net.ConnectionStat{}, common.ErrNotImplementedError
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return p.NetIOCountersWithContext(context.Background(), pernic) return p.NetIOCountersWithContext(context.Background(), pernic)
} }

View File

@ -16,7 +16,6 @@ import (
"strings" "strings"
"github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/net" "github.com/shirou/gopsutil/net"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -70,12 +69,8 @@ func (m MemoryMapsStat) String() string {
// to get more information about the process. An error will be returned // to get more information about the process. An error will be returned
// if the process does not exist. // if the process does not exist.
func NewProcess(pid int32) (*Process, error) { func NewProcess(pid int32) (*Process, error) {
p := &Process{ _, err := os.Stat(common.HostProc(strconv.Itoa(int(pid))))
Pid: int32(pid), return &Process{Pid: pid}, err
}
file, err := os.Open(common.HostProc(strconv.Itoa(int(p.Pid))))
defer file.Close()
return p, err
} }
// Ppid returns Parent Process ID of the process. // Ppid returns Parent Process ID of the process.
@ -84,7 +79,7 @@ func (p *Process) Ppid() (int32, error) {
} }
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) { func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
_, ppid, _, _, _, _, err := p.fillFromStat() _, ppid, _, _, _, _, _, err := p.fillFromStat()
if err != nil { if err != nil {
return -1, err return -1, err
} }
@ -150,7 +145,7 @@ func (p *Process) CreateTime() (int64, error) {
} }
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
_, _, _, createTime, _, _, err := p.fillFromStat() _, _, _, createTime, _, _, _, err := p.fillFromStat()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -186,7 +181,7 @@ func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
// Return value could be one of these. // Return value could be one of these.
// R: Running S: Sleep T: Stop I: Idle // R: Running S: Sleep T: Stop I: Idle
// Z: Zombie W: Wait L: Lock // Z: Zombie W: Wait L: Lock
// The charactor is same within all supported platforms. // The character is same within all supported platforms.
func (p *Process) Status() (string, error) { func (p *Process) Status() (string, error) {
return p.StatusWithContext(context.Background()) return p.StatusWithContext(context.Background())
} }
@ -253,7 +248,7 @@ func (p *Process) Terminal() (string, error) {
} }
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) { func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
t, _, _, _, _, _, err := p.fillFromStat() t, _, _, _, _, _, _, err := p.fillFromStat()
if err != nil { if err != nil {
return "", err return "", err
} }
@ -272,7 +267,7 @@ func (p *Process) Nice() (int32, error) {
} }
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) { func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
_, _, _, _, _, nice, err := p.fillFromStat() _, _, _, _, _, nice, _, err := p.fillFromStat()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -310,7 +305,7 @@ func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) (
return rlimits, err return rlimits, err
} }
_, _, _, _, rtprio, nice, err := p.fillFromStat() _, _, _, _, rtprio, nice, _, err := p.fillFromStat()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -418,7 +413,7 @@ func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesS
} }
for _, tid := range tids { for _, tid := range tids {
_, _, cpuTimes, _, _, _, err := p.fillFromTIDStat(tid) _, _, cpuTimes, _, _, _, _, err := p.fillFromTIDStat(tid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -434,7 +429,7 @@ func (p *Process) Times() (*cpu.TimesStat, error) {
} }
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) { func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
_, _, cpuTimes, _, _, _, err := p.fillFromStat() _, _, cpuTimes, _, _, _, _, err := p.fillFromStat()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -478,6 +473,20 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
return memInfoEx, nil return memInfoEx, nil
} }
// PageFaultsInfo returns the process's page fault counters
func (p *Process) PageFaults() (*PageFaultsStat, error) {
return p.PageFaultsWithContext(context.Background())
}
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
_, _, _, _, _, _, pageFaults, err := p.fillFromStat()
if err != nil {
return nil, err
}
return pageFaults, nil
}
// Children returns a slice of Process of the process. // Children returns a slice of Process of the process.
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return p.ChildrenWithContext(context.Background()) return p.ChildrenWithContext(context.Background())
@ -531,6 +540,15 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
return net.ConnectionsPid("all", p.Pid) return net.ConnectionsPid("all", p.Pid)
} }
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
return p.ConnectionsMaxWithContext(context.Background(), max)
}
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
return net.ConnectionsPidMax("all", p.Pid, max)
}
// NetIOCounters returns NetIOCounters of the process. // NetIOCounters returns NetIOCounters of the process.
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return p.NetIOCountersWithContext(context.Background(), pernic) return p.NetIOCountersWithContext(context.Background(), pernic)
@ -559,6 +577,9 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
pid := p.Pid pid := p.Pid
var ret []MemoryMapsStat var ret []MemoryMapsStat
if grouped {
ret = make([]MemoryMapsStat, 1)
}
smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps") smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps")
contents, err := ioutil.ReadFile(smapsPath) contents, err := ioutil.ReadFile(smapsPath)
if err != nil { if err != nil {
@ -621,7 +642,20 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
if err != nil { if err != nil {
return &ret, err return &ret, err
} }
ret = append(ret, g) if grouped {
ret[0].Size += g.Size
ret[0].Rss += g.Rss
ret[0].Pss += g.Pss
ret[0].SharedClean += g.SharedClean
ret[0].SharedDirty += g.SharedDirty
ret[0].PrivateClean += g.PrivateClean
ret[0].PrivateDirty += g.PrivateDirty
ret[0].Referenced += g.Referenced
ret[0].Anonymous += g.Anonymous
ret[0].Swap += g.Swap
} else {
ret = append(ret, g)
}
} }
// starts new block // starts new block
blocks = make([]string, 16) blocks = make([]string, 16)
@ -1083,6 +1117,13 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
return err return err
} }
p.memInfo.Swap = v * 1024 p.memInfo.Swap = v * 1024
case "VmHWM":
value := strings.Trim(value, " kB") // remove last "kB"
v, err := strconv.ParseUint(value, 10, 64)
if err != nil {
return err
}
p.memInfo.HWM = v * 1024
case "VmData": case "VmData":
value := strings.Trim(value, " kB") // remove last "kB" value := strings.Trim(value, " kB") // remove last "kB"
v, err := strconv.ParseUint(value, 10, 64) v, err := strconv.ParseUint(value, 10, 64)
@ -1140,11 +1181,11 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
return nil return nil
} }
func (p *Process) fillFromTIDStat(tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) { func (p *Process) fillFromTIDStat(tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
return p.fillFromTIDStatWithContext(context.Background(), tid) return p.fillFromTIDStatWithContext(context.Background(), tid)
} }
func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) { func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
pid := p.Pid pid := p.Pid
var statPath string var statPath string
@ -1156,7 +1197,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, err return 0, 0, nil, 0, 0, 0, nil, err
} }
fields := strings.Fields(string(contents)) fields := strings.Fields(string(contents))
@ -1167,21 +1208,21 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
terminal, err := strconv.ParseUint(fields[i+5], 10, 64) terminal, err := strconv.ParseUint(fields[i+5], 10, 64)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, err return 0, 0, nil, 0, 0, 0, nil, err
} }
ppid, err := strconv.ParseInt(fields[i+2], 10, 32) ppid, err := strconv.ParseInt(fields[i+2], 10, 32)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, err return 0, 0, nil, 0, 0, 0, nil, err
} }
utime, err := strconv.ParseFloat(fields[i+12], 64) utime, err := strconv.ParseFloat(fields[i+12], 64)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, err return 0, 0, nil, 0, 0, 0, nil, err
} }
stime, err := strconv.ParseFloat(fields[i+13], 64) stime, err := strconv.ParseFloat(fields[i+13], 64)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, err return 0, 0, nil, 0, 0, 0, nil, err
} }
cpuTimes := &cpu.TimesStat{ cpuTimes := &cpu.TimesStat{
@ -1190,17 +1231,17 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
System: float64(stime / ClockTicks), System: float64(stime / ClockTicks),
} }
bootTime, _ := host.BootTime() bootTime, _ := common.BootTimeWithContext(ctx)
t, err := strconv.ParseUint(fields[i+20], 10, 64) t, err := strconv.ParseUint(fields[i+20], 10, 64)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, err return 0, 0, nil, 0, 0, 0, nil, err
} }
ctime := (t / uint64(ClockTicks)) + uint64(bootTime) ctime := (t / uint64(ClockTicks)) + uint64(bootTime)
createTime := int64(ctime * 1000) createTime := int64(ctime * 1000)
rtpriority, err := strconv.ParseInt(fields[i+16], 10, 32) rtpriority, err := strconv.ParseInt(fields[i+16], 10, 32)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, err return 0, 0, nil, 0, 0, 0, nil, err
} }
if rtpriority < 0 { if rtpriority < 0 {
rtpriority = rtpriority*-1 - 1 rtpriority = rtpriority*-1 - 1
@ -1213,14 +1254,38 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
snice, _ := unix.Getpriority(PrioProcess, int(pid)) snice, _ := unix.Getpriority(PrioProcess, int(pid))
nice := int32(snice) // FIXME: is this true? nice := int32(snice) // FIXME: is this true?
return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, nil minFault, err := strconv.ParseUint(fields[i+8], 10, 64)
if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err
}
cMinFault, err := strconv.ParseUint(fields[i+9], 10, 64)
if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err
}
majFault, err := strconv.ParseUint(fields[i+10], 10, 64)
if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err
}
cMajFault, err := strconv.ParseUint(fields[i+11], 10, 64)
if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err
}
faults := &PageFaultsStat{
MinorFaults: minFault,
MajorFaults: majFault,
ChildMinorFaults: cMinFault,
ChildMajorFaults: cMajFault,
}
return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, faults, nil
} }
func (p *Process) fillFromStat() (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) { func (p *Process) fillFromStat() (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
return p.fillFromStatWithContext(context.Background()) return p.fillFromStatWithContext(context.Background())
} }
func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) { func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
return p.fillFromTIDStat(-1) return p.fillFromTIDStat(-1)
} }

View File

@ -7,6 +7,8 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/binary" "encoding/binary"
"os/exec"
"strconv"
"strings" "strings"
"unsafe" "unsafe"
@ -357,6 +359,14 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
func (p *Process) PageFaults() (*PageFaultsStat, error) {
return p.PageFaultsWithContext(context.Background())
}
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return p.ChildrenWithContext(context.Background()) return p.ChildrenWithContext(context.Background())
} }
@ -393,6 +403,14 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
return p.ConnectionsMaxWithContext(context.Background(), max)
}
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
return []net.ConnectionStat{}, common.ErrNotImplementedError
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return p.NetIOCountersWithContext(context.Background(), pernic) return p.NetIOCountersWithContext(context.Background(), pernic)
} }

View File

@ -25,12 +25,15 @@ const (
) )
var ( var (
modpsapi = windows.NewLazySystemDLL("psapi.dll") modpsapi = windows.NewLazySystemDLL("psapi.dll")
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW")
advapi32 = windows.NewLazySystemDLL("advapi32.dll") advapi32 = windows.NewLazySystemDLL("advapi32.dll")
procLookupPrivilegeValue = advapi32.NewProc("LookupPrivilegeValueW") procLookupPrivilegeValue = advapi32.NewProc("LookupPrivilegeValueW")
procAdjustTokenPrivileges = advapi32.NewProc("AdjustTokenPrivileges") procAdjustTokenPrivileges = advapi32.NewProc("AdjustTokenPrivileges")
procQueryFullProcessImageNameW = common.Modkernel32.NewProc("QueryFullProcessImageNameW")
) )
type SystemProcessInformation struct { type SystemProcessInformation struct {
@ -234,24 +237,31 @@ func (p *Process) Exe() (string, error) {
} }
func (p *Process) ExeWithContext(ctx context.Context) (string, error) { func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
if p.Pid != 0 { // 0 or null is the current process for CreateToolhelp32Snapshot // 0x1000 is PROCESS_QUERY_LIMITED_INFORMATION
snap := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPMODULE|w32.TH32CS_SNAPMODULE32, uint32(p.Pid)) c, err := syscall.OpenProcess(0x1000, false, uint32(p.Pid))
if snap != 0 { // don't report errors here, fallback to WMI instead
defer w32.CloseHandle(snap)
var me32 w32.MODULEENTRY32
me32.Size = uint32(unsafe.Sizeof(me32))
if w32.Module32First(snap, &me32) {
szexepath := windows.UTF16ToString(me32.SzExePath[:])
return szexepath, nil
}
}
}
dst, err := GetWin32ProcWithContext(ctx, p.Pid)
if err != nil { if err != nil {
return "", fmt.Errorf("could not get ExecutablePath: %s", err) return "", err
} }
return *dst[0].ExecutablePath, nil defer syscall.CloseHandle(c)
buf := make([]uint16, syscall.MAX_LONG_PATH)
size := uint32(syscall.MAX_LONG_PATH)
if err := procQueryFullProcessImageNameW.Find(); err == nil { // Vista+
ret, _, err := procQueryFullProcessImageNameW.Call(
uintptr(c),
uintptr(0),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&size)))
if ret == 0 {
return "", err
}
return windows.UTF16ToString(buf[:]), nil
}
// XP fallback
ret, _, err := procGetProcessImageFileNameW.Call(uintptr(c), uintptr(unsafe.Pointer(&buf[0])), uintptr(size))
if ret == 0 {
return "", err
}
return common.ConvertDOSPath(windows.UTF16ToString(buf[:])), nil
} }
func (p *Process) Cmdline() (string, error) { func (p *Process) Cmdline() (string, error) {
@ -530,6 +540,14 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
func (p *Process) PageFaults() (*PageFaultsStat, error) {
return p.PageFaultsWithContext(context.Background())
}
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return p.ChildrenWithContext(context.Background()) return p.ChildrenWithContext(context.Background())
} }
@ -543,24 +561,19 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
defer w32.CloseHandle(snap) defer w32.CloseHandle(snap)
var pe32 w32.PROCESSENTRY32 var pe32 w32.PROCESSENTRY32
pe32.DwSize = uint32(unsafe.Sizeof(pe32)) pe32.DwSize = uint32(unsafe.Sizeof(pe32))
if w32.Process32First(snap, &pe32) == false { if !w32.Process32First(snap, &pe32) {
return out, windows.GetLastError() return out, windows.GetLastError()
} }
for {
if pe32.Th32ParentProcessID == uint32(p.Pid) {
p, err := NewProcess(int32(pe32.Th32ProcessID))
if err == nil {
out = append(out, p)
}
}
for w32.Process32Next(snap, &pe32) {
if pe32.Th32ParentProcessID == uint32(p.Pid) { if pe32.Th32ParentProcessID == uint32(p.Pid) {
p, err := NewProcess(int32(pe32.Th32ProcessID)) p, err := NewProcess(int32(pe32.Th32ProcessID))
if err == nil { if err == nil {
out = append(out, p) out = append(out, p)
} }
} }
if !w32.Process32Next(snap, &pe32) {
break
}
} }
return out, nil return out, nil
} }
@ -581,6 +594,14 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
return nil, common.ErrNotImplementedError return nil, common.ErrNotImplementedError
} }
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
return p.ConnectionsMaxWithContext(context.Background(), max)
}
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
return []net.ConnectionStat{}, common.ErrNotImplementedError
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return p.NetIOCountersWithContext(context.Background(), pernic) return p.NetIOCountersWithContext(context.Background(), pernic)
} }
@ -669,22 +690,19 @@ func getFromSnapProcess(pid int32) (int32, int32, string, error) {
defer w32.CloseHandle(snap) defer w32.CloseHandle(snap)
var pe32 w32.PROCESSENTRY32 var pe32 w32.PROCESSENTRY32
pe32.DwSize = uint32(unsafe.Sizeof(pe32)) pe32.DwSize = uint32(unsafe.Sizeof(pe32))
if w32.Process32First(snap, &pe32) == false { if !w32.Process32First(snap, &pe32) {
return 0, 0, "", windows.GetLastError() return 0, 0, "", windows.GetLastError()
} }
for {
if pe32.Th32ProcessID == uint32(pid) {
szexe := windows.UTF16ToString(pe32.SzExeFile[:])
return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
}
for w32.Process32Next(snap, &pe32) {
if pe32.Th32ProcessID == uint32(pid) { if pe32.Th32ProcessID == uint32(pid) {
szexe := windows.UTF16ToString(pe32.SzExeFile[:]) szexe := windows.UTF16ToString(pe32.SzExeFile[:])
return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
} }
if !w32.Process32Next(snap, &pe32) {
break
}
} }
return 0, 0, "", fmt.Errorf("Couldn't find pid: %d", pid) return 0, 0, "", fmt.Errorf("couldn't find pid: %d", pid)
} }
// Get processes // Get processes

View File

@ -1 +1,3 @@
# gops # gops
Go process tools

5
vendor/github.com/vcaesar/gops/go.mod generated vendored Normal file
View File

@ -0,0 +1,5 @@
module github.com/vcaesar/gops
go 1.12
require github.com/shirou/gopsutil v2.19.6+incompatible

10
vendor/github.com/vcaesar/gops/go.sum generated vendored Normal file
View File

@ -0,0 +1,10 @@
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v2.19.6+incompatible h1:49/Gru26Lne9Cl3IoAVDZVM09hvkSrUodgIIsCVRwbs=
github.com/shirou/gopsutil v2.19.6+incompatible/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@ -4,9 +4,10 @@ go_import_path: github.com/vcaesar/imgo
go: go:
# - 1.8.x # - 1.8.x
- 1.9.x # - 1.9.x
- 1.10.x # - 1.10.x
- 1.11.x - 1.11.x
- 1.12.x
# - tip # - tip
install: install:

View File

@ -12,7 +12,7 @@ environment:
matrix: matrix:
- GOARCH: amd64 - GOARCH: amd64
# - GOARCH: 386 # - GOARCH: 386
GOVERSION: 1.12.4 GOVERSION: 1.12.7
# GOPATH: c:\gopath # GOPATH: c:\gopath
install: install:

54
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s generated vendored Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build riscv64,!gccgo
#include "textflag.h"
//
// System calls for linux/riscv64.
//
// Where available, just jump to package syscall's implementation of
// these functions.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
CALL runtime·entersyscall(SB)
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV $0, A3
MOV $0, A4
MOV $0, A5
MOV $0, A6
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP) // r1
MOV A1, r2+40(FP) // r2
CALL runtime·exitsyscall(SB)
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV ZERO, A3
MOV ZERO, A4
MOV ZERO, A5
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP)
MOV A1, r2+40(FP)
RET

View File

@ -6,12 +6,97 @@
package unix package unix
import "syscall" import "unsafe"
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
if len(b) < int(off+size) {
return 0, false
}
if isBigEndian {
return readIntBE(b[off:], size), true
}
return readIntLE(b[off:], size), true
}
func readIntBE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[1]) | uint64(b[0])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
func readIntLE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
// ParseDirent parses up to max directory entries in buf, // ParseDirent parses up to max directory entries in buf,
// appending the names to names. It returns the number of // appending the names to names. It returns the number of
// bytes consumed from buf, the number of entries added // bytes consumed from buf, the number of entries added
// to names, and the new names slice. // to names, and the new names slice.
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
return syscall.ParseDirent(buf, max, names) origlen := len(buf)
count = 0
for max != 0 && len(buf) > 0 {
reclen, ok := direntReclen(buf)
if !ok || reclen > uint64(len(buf)) {
return origlen, count, names
}
rec := buf[:reclen]
buf = buf[reclen:]
ino, ok := direntIno(rec)
if !ok {
break
}
if ino == 0 { // File absent in directory.
continue
}
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
namlen, ok := direntNamlen(rec)
if !ok || namoff+namlen > uint64(len(rec)) {
break
}
name := rec[namoff : namoff+namlen]
for i, c := range name {
if c == 0 {
name = name[:i]
break
}
}
// Check for useless names before allocating a string.
if string(name) == "." || string(name) == ".." {
continue
}
max--
count++
names = append(names, string(name))
}
return origlen - len(buf), count, names
} }

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// //
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le // +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64
package unix package unix

View File

@ -105,25 +105,25 @@ dragonfly_amd64)
freebsd_386) freebsd_386)
mkerrors="$mkerrors -m32" mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32" mksyscall="go run mksyscall.go -l32"
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
freebsd_amd64) freebsd_amd64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
freebsd_arm) freebsd_arm)
mkerrors="$mkerrors" mkerrors="$mkerrors"
mksyscall="go run mksyscall.go -l32 -arm" mksyscall="go run mksyscall.go -l32 -arm"
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
# Let the type of C char be signed for making the bare syscall # Let the type of C char be signed for making the bare syscall
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
freebsd_arm64) freebsd_arm64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
netbsd_386) netbsd_386)
@ -146,6 +146,12 @@ netbsd_arm)
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
netbsd_arm64)
mkerrors="$mkerrors -m64"
mksyscall="go run mksyscall.go -netbsd"
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;;
openbsd_386) openbsd_386)
mkerrors="$mkerrors -m32" mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32 -openbsd" mksyscall="go run mksyscall.go -l32 -openbsd"

View File

@ -182,6 +182,8 @@ struct ltchars {
#include <sys/signalfd.h> #include <sys/signalfd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <linux/bpf.h>
#include <linux/capability.h>
#include <linux/errqueue.h> #include <linux/errqueue.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_alg.h> #include <linux/if_alg.h>
@ -197,6 +199,7 @@ struct ltchars {
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/keyctl.h> #include <linux/keyctl.h>
#include <linux/loop.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/memfd.h> #include <linux/memfd.h>
#include <linux/module.h> #include <linux/module.h>
@ -433,7 +436,9 @@ ccflags="$@"
$2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^TC[IO](ON|OFF)$/ ||
$2 ~ /^IN_/ || $2 ~ /^IN_/ ||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|MCAST|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
$2 ~ /^TP_STATUS_/ || $2 ~ /^TP_STATUS_/ ||
$2 ~ /^FALLOC_/ || $2 ~ /^FALLOC_/ ||
$2 == "ICMPV6_FILTER" || $2 == "ICMPV6_FILTER" ||
@ -466,7 +471,7 @@ ccflags="$@"
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
$2 ~ /^CLONE_[A-Z_]+/ || $2 ~ /^CLONE_[A-Z_]+/ ||
$2 !~ /^(BPF_TIMEVAL)$/ && $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
$2 ~ /^(BPF|DLT)_/ || $2 ~ /^(BPF|DLT)_/ ||
$2 ~ /^(CLOCK|TIMER)_/ || $2 ~ /^(CLOCK|TIMER)_/ ||
$2 ~ /^CAN_/ || $2 ~ /^CAN_/ ||

View File

@ -42,9 +42,16 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
if goos == "aix" {
// Replace type of Atim, Mtim and Ctim by Timespec in Stat_t
// to avoid having both StTimespec and Timespec.
sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`)
b = sttimespec.ReplaceAll(b, []byte("Timespec"))
}
// Intentionally export __val fields in Fsid and Sigset_t // Intentionally export __val fields in Fsid and Sigset_t
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__val(\s+\S+\s+)}`) valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`)
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$3}")) b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}"))
// Intentionally export __fds_bits field in FdSet // Intentionally export __fds_bits field in FdSet
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`) fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
@ -96,6 +103,15 @@ func main() {
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`) cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement)) b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
// Rename Stat_t time fields
if goos == "freebsd" && goarch == "386" {
// Hide Stat_t.[AMCB]tim_ext fields
renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`)
b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_"))
}
renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`)
b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}"))
// gofmt // gofmt
b, err = format.Source(b) b, err = format.Source(b)
if err != nil { if err != nil {

View File

@ -139,7 +139,7 @@ func main() {
text += format(name, num, proto) text += format(name, num, proto)
} }
case "freebsd": case "freebsd":
if t.Match(`^([0-9]+)\s+\S+\s+(?:NO)?STD\s+({ \S+\s+(\w+).*)$`) { if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) {
num, proto := t.sub[1], t.sub[2] num, proto := t.sub[1], t.sub[2]
name := fmt.Sprintf("SYS_%s", t.sub[3]) name := fmt.Sprintf("SYS_%s", t.sub[3])
text += format(name, num, proto) text += format(name, num, proto)

12
vendor/golang.org/x/sys/unix/readdirent_getdents.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix dragonfly freebsd linux netbsd openbsd
package unix
// ReadDirent reads directory entries from fd and writes them into buf.
func ReadDirent(fd int, buf []byte) (n int, err error) {
return Getdents(fd, buf)
}

View File

@ -0,0 +1,19 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
package unix
import "unsafe"
// ReadDirent reads directory entries from fd and writes them into buf.
func ReadDirent(fd int, buf []byte) (n int, err error) {
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
// 64 bits should be enough. (32 bits isn't even on 386). Since the
// actual system call is getdirentries64, 64 is a good guess.
// TODO(rsc): Can we use a single global basep for all calls?
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
return Getdirentries(fd, buf, base)
}

View File

@ -21,10 +21,10 @@ func cmsgAlignOf(salen int) int {
case "aix": case "aix":
// There is no alignment on AIX. // There is no alignment on AIX.
salign = 1 salign = 1
case "darwin", "dragonfly", "solaris": case "darwin", "dragonfly", "solaris", "illumos":
// NOTE: It seems like 64-bit Darwin, DragonFly BSD and // NOTE: It seems like 64-bit Darwin, DragonFly BSD,
// Solaris kernels still require 32-bit aligned access to // illumos, and Solaris kernels still require 32-bit
// network subsystem. // aligned access to network subsystem.
if SizeofPtr == 8 { if SizeofPtr == 8 {
salign = 4 salign = 4
} }

View File

@ -50,5 +50,4 @@ func BytePtrFromString(s string) (*byte, error) {
} }
// Single-word zero for use when we need a valid pointer to 0 bytes. // Single-word zero for use when we need a valid pointer to 0 bytes.
// See mkunix.pl.
var _zero uintptr var _zero uintptr

View File

@ -280,8 +280,24 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
return -1, ENOSYS return -1, ENOSYS
} }
func direntIno(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
}
func direntReclen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}
func direntNamlen(buf []byte) (uint64, bool) {
reclen, ok := direntReclen(buf)
if !ok {
return 0, false
}
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
}
//sys getdirent(fd int, buf []byte) (n int, err error) //sys getdirent(fd int, buf []byte) (n int, err error)
func ReadDirent(fd int, buf []byte) (n int, err error) { func Getdents(fd int, buf []byte) (n int, err error) {
return getdirent(fd, buf) return getdirent(fd, buf)
} }
@ -454,8 +470,8 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
//sys Dup2(oldfd int, newfd int) (err error) //sys Dup2(oldfd int, newfd int) (err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error) //sys fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = fstatat //sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = fstatat
//sys Fstatfs(fd int, buf *Statfs_t) (err error) //sys Fstatfs(fd int, buf *Statfs_t) (err error)
//sys Ftruncate(fd int, length int64) (err error) //sys Ftruncate(fd int, length int64) (err error)
//sysnb Getegid() (egid int) //sysnb Getegid() (egid int)
@ -464,7 +480,7 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
//sysnb Getuid() (uid int) //sysnb Getuid() (uid int)
//sys Lchown(path string, uid int, gid int) (err error) //sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error) //sys Listen(s int, n int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error) //sys lstat(path string, stat *Stat_t) (err error)
//sys Pause() (err error) //sys Pause() (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64 //sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64
@ -474,7 +490,7 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys Stat(path string, stat *Stat_t) (err error) //sys stat(path string, statptr *Stat_t) (err error)
//sys Statfs(path string, buf *Statfs_t) (err error) //sys Statfs(path string, buf *Statfs_t) (err error)
//sys Truncate(path string, length int64) (err error) //sys Truncate(path string, length int64) (err error)

View File

@ -32,3 +32,19 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
func Fstat(fd int, stat *Stat_t) error {
return fstat(fd, stat)
}
func Fstatat(dirfd int, path string, stat *Stat_t, flags int) error {
return fstatat(dirfd, path, stat, flags)
}
func Lstat(path string, stat *Stat_t) error {
return lstat(path, stat)
}
func Stat(path string, statptr *Stat_t) error {
return stat(path, statptr)
}

View File

@ -32,3 +32,50 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
// In order to only have Timespec structure, type of Stat_t's fields
// Atim, Mtim and Ctim is changed from StTimespec to Timespec during
// ztypes generation.
// On ppc64, Timespec.Nsec is an int64 while StTimespec.Nsec is an
// int32, so the fields' value must be modified.
func fixStatTimFields(stat *Stat_t) {
stat.Atim.Nsec >>= 32
stat.Mtim.Nsec >>= 32
stat.Ctim.Nsec >>= 32
}
func Fstat(fd int, stat *Stat_t) error {
err := fstat(fd, stat)
if err != nil {
return err
}
fixStatTimFields(stat)
return nil
}
func Fstatat(dirfd int, path string, stat *Stat_t, flags int) error {
err := fstatat(dirfd, path, stat, flags)
if err != nil {
return err
}
fixStatTimFields(stat)
return nil
}
func Lstat(path string, stat *Stat_t) error {
err := lstat(path, stat)
if err != nil {
return err
}
fixStatTimFields(stat)
return nil
}
func Stat(path string, statptr *Stat_t) error {
err := stat(path, statptr)
if err != nil {
return err
}
fixStatTimFields(statptr)
return nil
}

View File

@ -63,15 +63,6 @@ func Setgroups(gids []int) (err error) {
return setgroups(len(a), &a[0]) return setgroups(len(a), &a[0])
} }
func ReadDirent(fd int, buf []byte) (n int, err error) {
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
// 64 bits should be enough. (32 bits isn't even on 386). Since the
// actual system call is getdirentries64, 64 is a good guess.
// TODO(rsc): Can we use a single global basep for all calls?
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
return Getdirentries(fd, buf, base)
}
// Wait status is 7 bits at bottom, either 0 (exited), // Wait status is 7 bits at bottom, either 0 (exited),
// 0x7F (stopped), or a signal number that caused an exit. // 0x7F (stopped), or a signal number that caused an exit.
// The 0x80 bit is whether there was a core dump. // The 0x80 bit is whether there was a core dump.
@ -86,6 +77,7 @@ const (
shift = 8 shift = 8
exited = 0 exited = 0
killed = 9
stopped = 0x7F stopped = 0x7F
) )
@ -112,6 +104,8 @@ func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP } func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
func (w WaitStatus) Killed() bool { return w&mask == killed && syscall.Signal(w>>shift) != SIGKILL }
func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP } func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
func (w WaitStatus) StopSignal() syscall.Signal { func (w WaitStatus) StopSignal() syscall.Signal {

Some files were not shown because too many files have changed in this diff Show More