dashboard: CPU, memory, diskIO and traffic on the footer (#15950)
* dashboard: footer, deep state update * dashboard: resolve asset path * dashboard: prevent state update on every reconnection * dashboard: fix linter issue * dashboard, cmd: minor UI fix, include commit hash * dashboard: gitCommit renamed to commit * dashboard: move the geth version to the right, make commit optional * dashboard: memory, traffic and CPU on footer * dashboard: fix merge * dashboard: CPU, diskIO on footer * dashboard: rename variables, use group declaration * dashboard: docs
This commit is contained in:
committed by
Péter Szilágyi
parent
ec96216d16
commit
05ade19302
102
vendor/github.com/elastic/gosigar/CHANGELOG.md
generated
vendored
Normal file
102
vendor/github.com/elastic/gosigar/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Fixed
|
||||
|
||||
### Changed
|
||||
|
||||
### Deprecated
|
||||
|
||||
## [0.8.0]
|
||||
|
||||
### Added
|
||||
- Added partial `getrusage` support for Windows to retrieve system CPU time and user CPU time. #95
|
||||
- Added full `getrusage` support for Unix. #95
|
||||
|
||||
## [0.7.0]
|
||||
|
||||
### Added
|
||||
- Added method stubs for process handling for operating system that are not supported
|
||||
by gosigar. All methods return `ErrNotImplemented` on such systems. #88
|
||||
|
||||
### Fixed
|
||||
- Fix freebsd build by using the common version of Get(pid). #91
|
||||
|
||||
### Changed
|
||||
- Fixed issues in cgroup package by adding missing error checks and closing
|
||||
file handles. #92
|
||||
|
||||
## [0.6.0]
|
||||
|
||||
### Added
|
||||
- Added method stubs to enable compilation for operating systems that are not
|
||||
supported by gosigar. All methods return `ErrNotImplemented` on these unsupported
|
||||
operating systems. #83
|
||||
- FreeBSD returns `ErrNotImplemented` for `ProcTime.Get`. #83
|
||||
|
||||
### Changed
|
||||
- OpenBSD returns `ErrNotImplemented` for `ProcTime.Get` instead of `nil`. #83
|
||||
- Fixed incorrect `Mem.Used` calculation under linux. #82
|
||||
- Fixed `ProcState` on Linux and FreeBSD when process names contain parentheses. #81
|
||||
|
||||
### Removed
|
||||
- Remove NetBSD build from sigar_unix.go as it is not supported by gosigar. #83
|
||||
|
||||
## [0.5.0]
|
||||
|
||||
### Changed
|
||||
- Fixed Trim environment variables when comparing values in the test suite. #79
|
||||
- Make `kern_procargs` more robust under darwin when we cannot retrieve
|
||||
all the information about a process. #78
|
||||
|
||||
## [0.4.0]
|
||||
|
||||
### Changed
|
||||
- Fixed Windows issue that caused a hang during `init()` if WMI wasn't ready. #74
|
||||
|
||||
## [0.3.0]
|
||||
|
||||
### Added
|
||||
- Read `MemAvailable` value for kernel 3.14+ #71
|
||||
|
||||
## [0.2.0]
|
||||
|
||||
### Added
|
||||
- Added `ErrCgroupsMissing` to indicate that /proc/cgroups is missing which is
|
||||
an indicator that cgroups were disabled at compile time. #64
|
||||
|
||||
### Changed
|
||||
- Changed `cgroup.SupportedSubsystems()` to honor the "enabled" column in the
|
||||
/proc/cgroups file. #64
|
||||
|
||||
## [0.1.0]
|
||||
|
||||
### Added
|
||||
- Added `CpuList` implementation for Windows that returns CPU timing information
|
||||
on a per CPU basis. #55
|
||||
- Added `Uptime` implementation for Windows. #55
|
||||
- Added `Swap` implementation for Windows based on page file metrics. #55
|
||||
- Added support to `github.com/gosigar/sys/windows` for querying and enabling
|
||||
privileges in a process token.
|
||||
- Added utility code for interfacing with linux NETLINK_INET_DIAG. #60
|
||||
- Added `ProcEnv` for getting a process's environment variables. #61
|
||||
|
||||
### Changed
|
||||
- Changed several `OpenProcess` calls on Windows to request the lowest possible
|
||||
access privileges. #50
|
||||
- Removed cgo usage from Windows code.
|
||||
- Added OS version checks to `ProcArgs.Get` on Windows because the
|
||||
`Win32_Process` WMI query is not available prior to Windows vista. On XP and
|
||||
Windows 2003, this method returns `ErrNotImplemented`. #55
|
||||
|
||||
### Fixed
|
||||
- Fixed value of `Mem.ActualFree` and `Mem.ActualUsed` on Windows. #49
|
||||
- Fixed `ProcTime.StartTime` on Windows to report value in milliseconds since
|
||||
Unix epoch. #51
|
||||
- Fixed `ProcStatus.PPID` value is wrong on Windows. #55
|
||||
- Fixed `ProcStatus.Username` error on Windows XP #56
|
201
vendor/github.com/elastic/gosigar/LICENSE
generated
vendored
Normal file
201
vendor/github.com/elastic/gosigar/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
9
vendor/github.com/elastic/gosigar/NOTICE
generated
vendored
Normal file
9
vendor/github.com/elastic/gosigar/NOTICE
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
Copyright (c) [2009-2011] VMware, Inc. All Rights Reserved.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
You may not use this product except in compliance with the License.
|
||||
|
||||
This product includes a number of subcomponents with
|
||||
separate copyright notices and license terms. Your use of these
|
||||
subcomponents is subject to the terms and conditions of the
|
||||
subcomponent's license, as noted in the LICENSE file.
|
57
vendor/github.com/elastic/gosigar/README.md
generated
vendored
Normal file
57
vendor/github.com/elastic/gosigar/README.md
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
# Go sigar [](https://travis-ci.org/elastic/gosigar) [](https://ci.appveyor.com/project/elastic-beats/gosigar/branch/master)
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Go sigar is a golang implementation of the
|
||||
[sigar API](https://github.com/hyperic/sigar). The Go version of
|
||||
sigar has a very similar interface, but is being written from scratch
|
||||
in pure go/cgo, rather than cgo bindings for libsigar.
|
||||
|
||||
## Test drive
|
||||
|
||||
$ go get github.com/elastic/gosigar
|
||||
$ cd $GOPATH/src/github.com/elastic/gosigar/examples/ps
|
||||
$ go build
|
||||
$ ./ps
|
||||
|
||||
## Supported platforms
|
||||
|
||||
The features vary by operating system.
|
||||
|
||||
| Feature | Linux | Darwin | Windows | OpenBSD | FreeBSD |
|
||||
|-----------------|:-----:|:------:|:-------:|:-------:|:-------:|
|
||||
| Cpu | X | X | X | X | X |
|
||||
| CpuList | X | X | | X | X |
|
||||
| FDUsage | X | | | | X |
|
||||
| FileSystemList | X | X | X | X | X |
|
||||
| FileSystemUsage | X | X | X | X | X |
|
||||
| LoadAverage | X | X | | X | X |
|
||||
| Mem | X | X | X | X | X |
|
||||
| ProcArgs | X | X | X | | X |
|
||||
| ProcEnv | X | X | | | X |
|
||||
| ProcExe | X | X | | | X |
|
||||
| ProcFDUsage | X | | | | X |
|
||||
| ProcList | X | X | X | | X |
|
||||
| ProcMem | X | X | X | | X |
|
||||
| ProcState | X | X | X | | X |
|
||||
| ProcTime | X | X | X | | X |
|
||||
| Swap | X | X | | X | X |
|
||||
| Uptime | X | X | | X | X |
|
||||
|
||||
## OS Specific Notes
|
||||
|
||||
### FreeBSD
|
||||
|
||||
Mount both `linprocfs` and `procfs` for compatability. Consider adding these
|
||||
mounts to your `/etc/fstab` file so they are mounted automatically at boot.
|
||||
|
||||
```
|
||||
sudo mount -t procfs proc /proc
|
||||
sudo mkdir -p /compat/linux/proc
|
||||
sudo mount -t linprocfs /dev/null /compat/linux/proc
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
25
vendor/github.com/elastic/gosigar/Vagrantfile
generated
vendored
Normal file
25
vendor/github.com/elastic/gosigar/Vagrantfile
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
||||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
config.vm.box = "hashicorp/precise64"
|
||||
config.vm.provision "shell", inline: "mkdir -p /home/vagrant/go"
|
||||
config.vm.synced_folder ".", "/home/vagrant/go/src/github.com/cloudfoundry/gosigar"
|
||||
config.vm.provision "shell", inline: "chown -R vagrant:vagrant /home/vagrant/go"
|
||||
install_go = <<-BASH
|
||||
set -e
|
||||
|
||||
if [ ! -d "/usr/local/go" ]; then
|
||||
cd /tmp && wget https://storage.googleapis.com/golang/go1.3.3.linux-amd64.tar.gz
|
||||
cd /usr/local
|
||||
tar xvzf /tmp/go1.3.3.linux-amd64.tar.gz
|
||||
echo 'export GOPATH=/home/vagrant/go; export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin' >> /home/vagrant/.bashrc
|
||||
fi
|
||||
export GOPATH=/home/vagrant/go
|
||||
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
|
||||
/usr/local/go/bin/go get -u github.com/onsi/ginkgo/ginkgo
|
||||
/usr/local/go/bin/go get -u github.com/onsi/gomega;
|
||||
BASH
|
||||
config.vm.provision "shell", inline: 'apt-get install -y git-core'
|
||||
config.vm.provision "shell", inline: install_go
|
||||
end
|
21
vendor/github.com/elastic/gosigar/codecov.yml
generated
vendored
Normal file
21
vendor/github.com/elastic/gosigar/codecov.yml
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Enable coverage report message for diff on commit
|
||||
coverage:
|
||||
status:
|
||||
project: off
|
||||
patch:
|
||||
default:
|
||||
# basic
|
||||
target: auto
|
||||
threshold: null
|
||||
base: auto
|
||||
# advanced
|
||||
branches: null
|
||||
if_no_uploads: error
|
||||
if_not_found: success
|
||||
if_ci_failed: error
|
||||
only_pulls: false
|
||||
flags: null
|
||||
paths: null
|
||||
|
||||
# Disable comments on Pull Requests
|
||||
comment: false
|
83
vendor/github.com/elastic/gosigar/concrete_sigar.go
generated
vendored
Normal file
83
vendor/github.com/elastic/gosigar/concrete_sigar.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ConcreteSigar struct{}
|
||||
|
||||
func (c *ConcreteSigar) CollectCpuStats(collectionInterval time.Duration) (<-chan Cpu, chan<- struct{}) {
|
||||
// samplesCh is buffered to 1 value to immediately return first CPU sample
|
||||
samplesCh := make(chan Cpu, 1)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
var cpuUsage Cpu
|
||||
|
||||
// Immediately provide non-delta value.
|
||||
// samplesCh is buffered to 1 value, so it will not block.
|
||||
cpuUsage.Get()
|
||||
samplesCh <- cpuUsage
|
||||
|
||||
ticker := time.NewTicker(collectionInterval)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
previousCpuUsage := cpuUsage
|
||||
|
||||
cpuUsage.Get()
|
||||
|
||||
select {
|
||||
case samplesCh <- cpuUsage.Delta(previousCpuUsage):
|
||||
default:
|
||||
// Include default to avoid channel blocking
|
||||
}
|
||||
|
||||
case <-stopCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return samplesCh, stopCh
|
||||
}
|
||||
|
||||
func (c *ConcreteSigar) GetLoadAverage() (LoadAverage, error) {
|
||||
l := LoadAverage{}
|
||||
err := l.Get()
|
||||
return l, err
|
||||
}
|
||||
|
||||
func (c *ConcreteSigar) GetMem() (Mem, error) {
|
||||
m := Mem{}
|
||||
err := m.Get()
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (c *ConcreteSigar) GetSwap() (Swap, error) {
|
||||
s := Swap{}
|
||||
err := s.Get()
|
||||
return s, err
|
||||
}
|
||||
|
||||
func (c *ConcreteSigar) GetFileSystemUsage(path string) (FileSystemUsage, error) {
|
||||
f := FileSystemUsage{}
|
||||
err := f.Get(path)
|
||||
return f, err
|
||||
}
|
||||
|
||||
func (c *ConcreteSigar) GetFDUsage() (FDUsage, error) {
|
||||
fd := FDUsage{}
|
||||
err := fd.Get()
|
||||
return fd, err
|
||||
}
|
||||
|
||||
// GetRusage return the resource usage of the process
|
||||
// Possible params: 0 = RUSAGE_SELF, 1 = RUSAGE_CHILDREN, 2 = RUSAGE_THREAD
|
||||
func (c *ConcreteSigar) GetRusage(who int) (Rusage, error) {
|
||||
r := Rusage{}
|
||||
err := r.Get(who)
|
||||
return r, err
|
||||
}
|
494
vendor/github.com/elastic/gosigar/sigar_darwin.go
generated
vendored
Normal file
494
vendor/github.com/elastic/gosigar/sigar_darwin.go
generated
vendored
Normal file
@ -0,0 +1,494 @@
|
||||
// Copyright (c) 2012 VMware, Inc.
|
||||
|
||||
package gosigar
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/host_info.h>
|
||||
#include <libproc.h>
|
||||
#include <mach/processor_info.h>
|
||||
#include <mach/vm_map.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/user"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (self *LoadAverage) Get() error {
|
||||
avg := []C.double{0, 0, 0}
|
||||
|
||||
C.getloadavg(&avg[0], C.int(len(avg)))
|
||||
|
||||
self.One = float64(avg[0])
|
||||
self.Five = float64(avg[1])
|
||||
self.Fifteen = float64(avg[2])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Uptime) Get() error {
|
||||
tv := syscall.Timeval32{}
|
||||
|
||||
if err := sysctlbyname("kern.boottime", &tv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Mem) Get() error {
|
||||
var vmstat C.vm_statistics_data_t
|
||||
|
||||
if err := sysctlbyname("hw.memsize", &self.Total); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := vm_info(&vmstat); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kern := uint64(vmstat.inactive_count) << 12
|
||||
self.Free = uint64(vmstat.free_count) << 12
|
||||
|
||||
self.Used = self.Total - self.Free
|
||||
self.ActualFree = self.Free + kern
|
||||
self.ActualUsed = self.Used - kern
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type xsw_usage struct {
|
||||
Total, Avail, Used uint64
|
||||
}
|
||||
|
||||
func (self *Swap) Get() error {
|
||||
sw_usage := xsw_usage{}
|
||||
|
||||
if err := sysctlbyname("vm.swapusage", &sw_usage); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Total = sw_usage.Total
|
||||
self.Used = sw_usage.Used
|
||||
self.Free = sw_usage.Avail
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Cpu) Get() error {
|
||||
var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT
|
||||
var cpuload C.host_cpu_load_info_data_t
|
||||
|
||||
status := C.host_statistics(C.host_t(C.mach_host_self()),
|
||||
C.HOST_CPU_LOAD_INFO,
|
||||
C.host_info_t(unsafe.Pointer(&cpuload)),
|
||||
&count)
|
||||
|
||||
if status != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("host_statistics error=%d", status)
|
||||
}
|
||||
|
||||
self.User = uint64(cpuload.cpu_ticks[C.CPU_STATE_USER])
|
||||
self.Sys = uint64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM])
|
||||
self.Idle = uint64(cpuload.cpu_ticks[C.CPU_STATE_IDLE])
|
||||
self.Nice = uint64(cpuload.cpu_ticks[C.CPU_STATE_NICE])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *CpuList) Get() error {
|
||||
var count C.mach_msg_type_number_t
|
||||
var cpuload *C.processor_cpu_load_info_data_t
|
||||
var ncpu C.natural_t
|
||||
|
||||
status := C.host_processor_info(C.host_t(C.mach_host_self()),
|
||||
C.PROCESSOR_CPU_LOAD_INFO,
|
||||
&ncpu,
|
||||
(*C.processor_info_array_t)(unsafe.Pointer(&cpuload)),
|
||||
&count)
|
||||
|
||||
if status != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("host_processor_info error=%d", status)
|
||||
}
|
||||
|
||||
// jump through some cgo casting hoops and ensure we properly free
|
||||
// the memory that cpuload points to
|
||||
target := C.vm_map_t(C.mach_task_self_)
|
||||
address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload)))
|
||||
defer C.vm_deallocate(target, address, C.vm_size_t(ncpu))
|
||||
|
||||
// the body of struct processor_cpu_load_info
|
||||
// aka processor_cpu_load_info_data_t
|
||||
var cpu_ticks [C.CPU_STATE_MAX]uint32
|
||||
|
||||
// copy the cpuload array to a []byte buffer
|
||||
// where we can binary.Read the data
|
||||
size := int(ncpu) * binary.Size(cpu_ticks)
|
||||
buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size))
|
||||
|
||||
bbuf := bytes.NewBuffer(buf)
|
||||
|
||||
self.List = make([]Cpu, 0, ncpu)
|
||||
|
||||
for i := 0; i < int(ncpu); i++ {
|
||||
cpu := Cpu{}
|
||||
|
||||
err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cpu.User = uint64(cpu_ticks[C.CPU_STATE_USER])
|
||||
cpu.Sys = uint64(cpu_ticks[C.CPU_STATE_SYSTEM])
|
||||
cpu.Idle = uint64(cpu_ticks[C.CPU_STATE_IDLE])
|
||||
cpu.Nice = uint64(cpu_ticks[C.CPU_STATE_NICE])
|
||||
|
||||
self.List = append(self.List, cpu)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FDUsage) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *FileSystemList) Get() error {
|
||||
num, err := syscall.Getfsstat(nil, C.MNT_NOWAIT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := make([]syscall.Statfs_t, num)
|
||||
|
||||
_, err = syscall.Getfsstat(buf, C.MNT_NOWAIT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fslist := make([]FileSystem, 0, num)
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
fs := FileSystem{}
|
||||
|
||||
fs.DirName = bytePtrToString(&buf[i].Mntonname[0])
|
||||
fs.DevName = bytePtrToString(&buf[i].Mntfromname[0])
|
||||
fs.SysTypeName = bytePtrToString(&buf[i].Fstypename[0])
|
||||
|
||||
fslist = append(fslist, fs)
|
||||
}
|
||||
|
||||
self.List = fslist
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *ProcList) Get() error {
|
||||
n := C.proc_listpids(C.PROC_ALL_PIDS, 0, nil, 0)
|
||||
if n <= 0 {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
buf := make([]byte, n)
|
||||
n = C.proc_listpids(C.PROC_ALL_PIDS, 0, unsafe.Pointer(&buf[0]), n)
|
||||
if n <= 0 {
|
||||
return syscall.ENOMEM
|
||||
}
|
||||
|
||||
var pid int32
|
||||
num := int(n) / binary.Size(pid)
|
||||
list := make([]int, 0, num)
|
||||
bbuf := bytes.NewBuffer(buf)
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
if err := binary.Read(bbuf, binary.LittleEndian, &pid); err != nil {
|
||||
return err
|
||||
}
|
||||
if pid == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, int(pid))
|
||||
}
|
||||
|
||||
self.List = list
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcState) Get(pid int) error {
|
||||
info := C.struct_proc_taskallinfo{}
|
||||
|
||||
if err := task_info(pid, &info); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Name = C.GoString(&info.pbsd.pbi_comm[0])
|
||||
|
||||
switch info.pbsd.pbi_status {
|
||||
case C.SIDL:
|
||||
self.State = RunStateIdle
|
||||
case C.SRUN:
|
||||
self.State = RunStateRun
|
||||
case C.SSLEEP:
|
||||
self.State = RunStateSleep
|
||||
case C.SSTOP:
|
||||
self.State = RunStateStop
|
||||
case C.SZOMB:
|
||||
self.State = RunStateZombie
|
||||
default:
|
||||
self.State = RunStateUnknown
|
||||
}
|
||||
|
||||
self.Ppid = int(info.pbsd.pbi_ppid)
|
||||
|
||||
self.Pgid = int(info.pbsd.pbi_pgid)
|
||||
|
||||
self.Tty = int(info.pbsd.e_tdev)
|
||||
|
||||
self.Priority = int(info.ptinfo.pti_priority)
|
||||
|
||||
self.Nice = int(info.pbsd.pbi_nice)
|
||||
|
||||
// Get process username. Fallback to UID if username is not available.
|
||||
uid := strconv.Itoa(int(info.pbsd.pbi_uid))
|
||||
user, err := user.LookupId(uid)
|
||||
if err == nil && user.Username != "" {
|
||||
self.Username = user.Username
|
||||
} else {
|
||||
self.Username = uid
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcMem) Get(pid int) error {
|
||||
info := C.struct_proc_taskallinfo{}
|
||||
|
||||
if err := task_info(pid, &info); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Size = uint64(info.ptinfo.pti_virtual_size)
|
||||
self.Resident = uint64(info.ptinfo.pti_resident_size)
|
||||
self.PageFaults = uint64(info.ptinfo.pti_faults)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcTime) Get(pid int) error {
|
||||
info := C.struct_proc_taskallinfo{}
|
||||
|
||||
if err := task_info(pid, &info); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.User =
|
||||
uint64(info.ptinfo.pti_total_user) / uint64(time.Millisecond)
|
||||
|
||||
self.Sys =
|
||||
uint64(info.ptinfo.pti_total_system) / uint64(time.Millisecond)
|
||||
|
||||
self.Total = self.User + self.Sys
|
||||
|
||||
self.StartTime = (uint64(info.pbsd.pbi_start_tvsec) * 1000) +
|
||||
(uint64(info.pbsd.pbi_start_tvusec) / 1000)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcArgs) Get(pid int) error {
|
||||
var args []string
|
||||
|
||||
argv := func(arg string) {
|
||||
args = append(args, arg)
|
||||
}
|
||||
|
||||
err := kern_procargs(pid, nil, argv, nil)
|
||||
|
||||
self.List = args
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *ProcEnv) Get(pid int) error {
|
||||
if self.Vars == nil {
|
||||
self.Vars = map[string]string{}
|
||||
}
|
||||
|
||||
env := func(k, v string) {
|
||||
self.Vars[k] = v
|
||||
}
|
||||
|
||||
return kern_procargs(pid, nil, nil, env)
|
||||
}
|
||||
|
||||
func (self *ProcExe) Get(pid int) error {
|
||||
exe := func(arg string) {
|
||||
self.Name = arg
|
||||
}
|
||||
|
||||
return kern_procargs(pid, exe, nil, nil)
|
||||
}
|
||||
|
||||
func (self *ProcFDUsage) Get(pid int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
// wrapper around sysctl KERN_PROCARGS2
|
||||
// callbacks params are optional,
|
||||
// up to the caller as to which pieces of data they want
|
||||
func kern_procargs(pid int,
|
||||
exe func(string),
|
||||
argv func(string),
|
||||
env func(string, string)) error {
|
||||
|
||||
mib := []C.int{C.CTL_KERN, C.KERN_PROCARGS2, C.int(pid)}
|
||||
argmax := uintptr(C.ARG_MAX)
|
||||
buf := make([]byte, argmax)
|
||||
err := sysctl(mib, &buf[0], &argmax, nil, 0)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
bbuf := bytes.NewBuffer(buf)
|
||||
bbuf.Truncate(int(argmax))
|
||||
|
||||
var argc int32
|
||||
binary.Read(bbuf, binary.LittleEndian, &argc)
|
||||
|
||||
path, err := bbuf.ReadBytes(0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading the argv[0]: %v", err)
|
||||
}
|
||||
if exe != nil {
|
||||
exe(string(chop(path)))
|
||||
}
|
||||
|
||||
// skip trailing \0's
|
||||
for {
|
||||
c, err := bbuf.ReadByte()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error skipping nils: %v", err)
|
||||
}
|
||||
if c != 0 {
|
||||
bbuf.UnreadByte()
|
||||
break // start of argv[0]
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < int(argc); i++ {
|
||||
arg, err := bbuf.ReadBytes(0)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading args: %v", err)
|
||||
}
|
||||
if argv != nil {
|
||||
argv(string(chop(arg)))
|
||||
}
|
||||
}
|
||||
|
||||
if env == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
delim := []byte{61} // "="
|
||||
|
||||
for {
|
||||
line, err := bbuf.ReadBytes(0)
|
||||
if err == io.EOF || line[0] == 0 {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading args: %v", err)
|
||||
}
|
||||
pair := bytes.SplitN(chop(line), delim, 2)
|
||||
|
||||
if len(pair) != 2 {
|
||||
return fmt.Errorf("Error reading process information for PID: %d", pid)
|
||||
}
|
||||
|
||||
env(string(pair[0]), string(pair[1]))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// XXX copied from zsyscall_darwin_amd64.go
|
||||
func sysctl(mib []C.int, old *byte, oldlen *uintptr,
|
||||
new *byte, newlen uintptr) (err error) {
|
||||
var p0 unsafe.Pointer
|
||||
p0 = unsafe.Pointer(&mib[0])
|
||||
_, _, e1 := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(p0),
|
||||
uintptr(len(mib)),
|
||||
uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)),
|
||||
uintptr(unsafe.Pointer(new)), uintptr(newlen))
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func vm_info(vmstat *C.vm_statistics_data_t) error {
|
||||
var count C.mach_msg_type_number_t = C.HOST_VM_INFO_COUNT
|
||||
|
||||
status := C.host_statistics(
|
||||
C.host_t(C.mach_host_self()),
|
||||
C.HOST_VM_INFO,
|
||||
C.host_info_t(unsafe.Pointer(vmstat)),
|
||||
&count)
|
||||
|
||||
if status != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("host_statistics=%d", status)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// generic Sysctl buffer unmarshalling
|
||||
func sysctlbyname(name string, data interface{}) (err error) {
|
||||
val, err := syscall.Sysctl(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := []byte(val)
|
||||
|
||||
switch v := data.(type) {
|
||||
case *uint64:
|
||||
*v = *(*uint64)(unsafe.Pointer(&buf[0]))
|
||||
return
|
||||
}
|
||||
|
||||
bbuf := bytes.NewBuffer([]byte(val))
|
||||
return binary.Read(bbuf, binary.LittleEndian, data)
|
||||
}
|
||||
|
||||
func task_info(pid int, info *C.struct_proc_taskallinfo) error {
|
||||
size := C.int(unsafe.Sizeof(*info))
|
||||
ptr := unsafe.Pointer(info)
|
||||
|
||||
n := C.proc_pidinfo(C.int(pid), C.PROC_PIDTASKALLINFO, 0, ptr, size)
|
||||
if n != size {
|
||||
return fmt.Errorf("Could not read process info for pid %d", pid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
126
vendor/github.com/elastic/gosigar/sigar_format.go
generated
vendored
Normal file
126
vendor/github.com/elastic/gosigar/sigar_format.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2012 VMware, Inc.
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Go version of apr_strfsize
|
||||
func FormatSize(size uint64) string {
|
||||
ord := []string{"K", "M", "G", "T", "P", "E"}
|
||||
o := 0
|
||||
buf := new(bytes.Buffer)
|
||||
w := bufio.NewWriter(buf)
|
||||
|
||||
if size < 973 {
|
||||
fmt.Fprintf(w, "%3d ", size)
|
||||
w.Flush()
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
for {
|
||||
remain := size & 1023
|
||||
size >>= 10
|
||||
|
||||
if size >= 973 {
|
||||
o++
|
||||
continue
|
||||
}
|
||||
|
||||
if size < 9 || (size == 9 && remain < 973) {
|
||||
remain = ((remain * 5) + 256) / 512
|
||||
if remain >= 10 {
|
||||
size++
|
||||
remain = 0
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%d.%d%s", size, remain, ord[o])
|
||||
break
|
||||
}
|
||||
|
||||
if remain >= 512 {
|
||||
size++
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%3d%s", size, ord[o])
|
||||
break
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func FormatPercent(percent float64) string {
|
||||
return strconv.FormatFloat(percent, 'f', -1, 64) + "%"
|
||||
}
|
||||
|
||||
func (self *FileSystemUsage) UsePercent() float64 {
|
||||
b_used := (self.Total - self.Free) / 1024
|
||||
b_avail := self.Avail / 1024
|
||||
utotal := b_used + b_avail
|
||||
used := b_used
|
||||
|
||||
if utotal != 0 {
|
||||
u100 := used * 100
|
||||
pct := u100 / utotal
|
||||
if u100%utotal != 0 {
|
||||
pct += 1
|
||||
}
|
||||
return (float64(pct) / float64(100)) * 100.0
|
||||
}
|
||||
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func (self *Uptime) Format() string {
|
||||
buf := new(bytes.Buffer)
|
||||
w := bufio.NewWriter(buf)
|
||||
uptime := uint64(self.Length)
|
||||
|
||||
days := uptime / (60 * 60 * 24)
|
||||
|
||||
if days != 0 {
|
||||
s := ""
|
||||
if days > 1 {
|
||||
s = "s"
|
||||
}
|
||||
fmt.Fprintf(w, "%d day%s, ", days, s)
|
||||
}
|
||||
|
||||
minutes := uptime / 60
|
||||
hours := minutes / 60
|
||||
hours %= 24
|
||||
minutes %= 60
|
||||
|
||||
fmt.Fprintf(w, "%2d:%02d", hours, minutes)
|
||||
|
||||
w.Flush()
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (self *ProcTime) FormatStartTime() string {
|
||||
if self.StartTime == 0 {
|
||||
return "00:00"
|
||||
}
|
||||
start := time.Unix(int64(self.StartTime)/1000, 0)
|
||||
format := "Jan02"
|
||||
if time.Since(start).Seconds() < (60 * 60 * 24) {
|
||||
format = "15:04"
|
||||
}
|
||||
return start.Format(format)
|
||||
}
|
||||
|
||||
func (self *ProcTime) FormatTotal() string {
|
||||
t := self.Total / 1000
|
||||
ss := t % 60
|
||||
t /= 60
|
||||
mm := t % 60
|
||||
t /= 60
|
||||
hh := t % 24
|
||||
return fmt.Sprintf("%02d:%02d:%02d", hh, mm, ss)
|
||||
}
|
108
vendor/github.com/elastic/gosigar/sigar_freebsd.go
generated
vendored
Normal file
108
vendor/github.com/elastic/gosigar/sigar_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
// Copied and modified from sigar_linux.go.
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func init() {
|
||||
system.ticks = uint64(C.sysconf(C._SC_CLK_TCK))
|
||||
|
||||
Procd = "/compat/linux/proc"
|
||||
|
||||
getLinuxBootTime()
|
||||
}
|
||||
|
||||
func getMountTableFileName() string {
|
||||
return Procd + "/mtab"
|
||||
}
|
||||
|
||||
func (self *Uptime) Get() error {
|
||||
ts := C.struct_timespec{}
|
||||
|
||||
if _, err := C.clock_gettime(C.CLOCK_UPTIME, &ts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Length = float64(ts.tv_sec) + 1e-9*float64(ts.tv_nsec)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FDUsage) Get() error {
|
||||
val := C.uint32_t(0)
|
||||
sc := C.size_t(4)
|
||||
|
||||
name := C.CString("kern.openfiles")
|
||||
_, err := C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0)
|
||||
C.free(unsafe.Pointer(name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.Open = uint64(val)
|
||||
|
||||
name = C.CString("kern.maxfiles")
|
||||
_, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0)
|
||||
C.free(unsafe.Pointer(name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.Max = uint64(val)
|
||||
|
||||
self.Unused = self.Max - self.Open
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcFDUsage) Get(pid int) error {
|
||||
err := readFile("/proc/"+strconv.Itoa(pid)+"/rlimit", func(line string) bool {
|
||||
if strings.HasPrefix(line, "nofile") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 3 {
|
||||
self.SoftLimit, _ = strconv.ParseUint(fields[1], 10, 64)
|
||||
self.HardLimit, _ = strconv.ParseUint(fields[2], 10, 64)
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// linprocfs only provides this information for this process (self).
|
||||
fds, err := ioutil.ReadDir(procFileName(pid, "fd"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.Open = uint64(len(fds))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseCpuStat(self *Cpu, line string) error {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
self.User, _ = strtoull(fields[1])
|
||||
self.Nice, _ = strtoull(fields[2])
|
||||
self.Sys, _ = strtoull(fields[3])
|
||||
self.Idle, _ = strtoull(fields[4])
|
||||
return nil
|
||||
}
|
197
vendor/github.com/elastic/gosigar/sigar_interface.go
generated
vendored
Normal file
197
vendor/github.com/elastic/gosigar/sigar_interface.go
generated
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ErrNotImplemented struct {
|
||||
OS string
|
||||
}
|
||||
|
||||
func (e ErrNotImplemented) Error() string {
|
||||
return "not implemented on " + e.OS
|
||||
}
|
||||
|
||||
func IsNotImplemented(err error) bool {
|
||||
switch err.(type) {
|
||||
case ErrNotImplemented, *ErrNotImplemented:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type Sigar interface {
|
||||
CollectCpuStats(collectionInterval time.Duration) (<-chan Cpu, chan<- struct{})
|
||||
GetLoadAverage() (LoadAverage, error)
|
||||
GetMem() (Mem, error)
|
||||
GetSwap() (Swap, error)
|
||||
GetFileSystemUsage(string) (FileSystemUsage, error)
|
||||
GetFDUsage() (FDUsage, error)
|
||||
GetRusage(who int) (Rusage, error)
|
||||
}
|
||||
|
||||
type Cpu struct {
|
||||
User uint64
|
||||
Nice uint64
|
||||
Sys uint64
|
||||
Idle uint64
|
||||
Wait uint64
|
||||
Irq uint64
|
||||
SoftIrq uint64
|
||||
Stolen uint64
|
||||
}
|
||||
|
||||
func (cpu *Cpu) Total() uint64 {
|
||||
return cpu.User + cpu.Nice + cpu.Sys + cpu.Idle +
|
||||
cpu.Wait + cpu.Irq + cpu.SoftIrq + cpu.Stolen
|
||||
}
|
||||
|
||||
func (cpu Cpu) Delta(other Cpu) Cpu {
|
||||
return Cpu{
|
||||
User: cpu.User - other.User,
|
||||
Nice: cpu.Nice - other.Nice,
|
||||
Sys: cpu.Sys - other.Sys,
|
||||
Idle: cpu.Idle - other.Idle,
|
||||
Wait: cpu.Wait - other.Wait,
|
||||
Irq: cpu.Irq - other.Irq,
|
||||
SoftIrq: cpu.SoftIrq - other.SoftIrq,
|
||||
Stolen: cpu.Stolen - other.Stolen,
|
||||
}
|
||||
}
|
||||
|
||||
type LoadAverage struct {
|
||||
One, Five, Fifteen float64
|
||||
}
|
||||
|
||||
type Uptime struct {
|
||||
Length float64
|
||||
}
|
||||
|
||||
type Mem struct {
|
||||
Total uint64
|
||||
Used uint64
|
||||
Free uint64
|
||||
ActualFree uint64
|
||||
ActualUsed uint64
|
||||
}
|
||||
|
||||
type Swap struct {
|
||||
Total uint64
|
||||
Used uint64
|
||||
Free uint64
|
||||
}
|
||||
|
||||
type CpuList struct {
|
||||
List []Cpu
|
||||
}
|
||||
|
||||
type FDUsage struct {
|
||||
Open uint64
|
||||
Unused uint64
|
||||
Max uint64
|
||||
}
|
||||
|
||||
type FileSystem struct {
|
||||
DirName string
|
||||
DevName string
|
||||
TypeName string
|
||||
SysTypeName string
|
||||
Options string
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type FileSystemList struct {
|
||||
List []FileSystem
|
||||
}
|
||||
|
||||
type FileSystemUsage struct {
|
||||
Total uint64
|
||||
Used uint64
|
||||
Free uint64
|
||||
Avail uint64
|
||||
Files uint64
|
||||
FreeFiles uint64
|
||||
}
|
||||
|
||||
type ProcList struct {
|
||||
List []int
|
||||
}
|
||||
|
||||
type RunState byte
|
||||
|
||||
const (
|
||||
RunStateSleep = 'S'
|
||||
RunStateRun = 'R'
|
||||
RunStateStop = 'T'
|
||||
RunStateZombie = 'Z'
|
||||
RunStateIdle = 'D'
|
||||
RunStateUnknown = '?'
|
||||
)
|
||||
|
||||
type ProcState struct {
|
||||
Name string
|
||||
Username string
|
||||
State RunState
|
||||
Ppid int
|
||||
Pgid int
|
||||
Tty int
|
||||
Priority int
|
||||
Nice int
|
||||
Processor int
|
||||
}
|
||||
|
||||
type ProcMem struct {
|
||||
Size uint64
|
||||
Resident uint64
|
||||
Share uint64
|
||||
MinorFaults uint64
|
||||
MajorFaults uint64
|
||||
PageFaults uint64
|
||||
}
|
||||
|
||||
type ProcTime struct {
|
||||
StartTime uint64
|
||||
User uint64
|
||||
Sys uint64
|
||||
Total uint64
|
||||
}
|
||||
|
||||
type ProcArgs struct {
|
||||
List []string
|
||||
}
|
||||
|
||||
type ProcEnv struct {
|
||||
Vars map[string]string
|
||||
}
|
||||
|
||||
type ProcExe struct {
|
||||
Name string
|
||||
Cwd string
|
||||
Root string
|
||||
}
|
||||
|
||||
type ProcFDUsage struct {
|
||||
Open uint64
|
||||
SoftLimit uint64
|
||||
HardLimit uint64
|
||||
}
|
||||
|
||||
type Rusage struct {
|
||||
Utime time.Duration
|
||||
Stime time.Duration
|
||||
Maxrss int64
|
||||
Ixrss int64
|
||||
Idrss int64
|
||||
Isrss int64
|
||||
Minflt int64
|
||||
Majflt int64
|
||||
Nswap int64
|
||||
Inblock int64
|
||||
Oublock int64
|
||||
Msgsnd int64
|
||||
Msgrcv int64
|
||||
Nsignals int64
|
||||
Nvcsw int64
|
||||
Nivcsw int64
|
||||
}
|
84
vendor/github.com/elastic/gosigar/sigar_linux.go
generated
vendored
Normal file
84
vendor/github.com/elastic/gosigar/sigar_linux.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2012 VMware, Inc.
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
system.ticks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||||
|
||||
Procd = "/proc"
|
||||
|
||||
getLinuxBootTime()
|
||||
}
|
||||
|
||||
func getMountTableFileName() string {
|
||||
return "/etc/mtab"
|
||||
}
|
||||
|
||||
func (self *Uptime) Get() error {
|
||||
sysinfo := syscall.Sysinfo_t{}
|
||||
|
||||
if err := syscall.Sysinfo(&sysinfo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Length = float64(sysinfo.Uptime)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FDUsage) Get() error {
|
||||
return readFile(Procd+"/sys/fs/file-nr", func(line string) bool {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 3 {
|
||||
self.Open, _ = strconv.ParseUint(fields[0], 10, 64)
|
||||
self.Unused, _ = strconv.ParseUint(fields[1], 10, 64)
|
||||
self.Max, _ = strconv.ParseUint(fields[2], 10, 64)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func (self *ProcFDUsage) Get(pid int) error {
|
||||
err := readFile(procFileName(pid, "limits"), func(line string) bool {
|
||||
if strings.HasPrefix(line, "Max open files") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 6 {
|
||||
self.SoftLimit, _ = strconv.ParseUint(fields[3], 10, 64)
|
||||
self.HardLimit, _ = strconv.ParseUint(fields[4], 10, 64)
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fds, err := ioutil.ReadDir(procFileName(pid, "fd"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.Open = uint64(len(fds))
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseCpuStat(self *Cpu, line string) error {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
self.User, _ = strtoull(fields[1])
|
||||
self.Nice, _ = strtoull(fields[2])
|
||||
self.Sys, _ = strtoull(fields[3])
|
||||
self.Idle, _ = strtoull(fields[4])
|
||||
self.Wait, _ = strtoull(fields[5])
|
||||
self.Irq, _ = strtoull(fields[6])
|
||||
self.SoftIrq, _ = strtoull(fields[7])
|
||||
self.Stolen, _ = strtoull(fields[8])
|
||||
|
||||
return nil
|
||||
}
|
468
vendor/github.com/elastic/gosigar/sigar_linux_common.go
generated
vendored
Normal file
468
vendor/github.com/elastic/gosigar/sigar_linux_common.go
generated
vendored
Normal file
@ -0,0 +1,468 @@
|
||||
// Copyright (c) 2012 VMware, Inc.
|
||||
|
||||
// +build freebsd linux
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var system struct {
|
||||
ticks uint64
|
||||
btime uint64
|
||||
}
|
||||
|
||||
var Procd string
|
||||
|
||||
func getLinuxBootTime() {
|
||||
// grab system boot time
|
||||
readFile(Procd+"/stat", func(line string) bool {
|
||||
if strings.HasPrefix(line, "btime") {
|
||||
system.btime, _ = strtoull(line[6:])
|
||||
return false // stop reading
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (self *LoadAverage) Get() error {
|
||||
line, err := ioutil.ReadFile(Procd + "/loadavg")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
fields := strings.Fields(string(line))
|
||||
|
||||
self.One, _ = strconv.ParseFloat(fields[0], 64)
|
||||
self.Five, _ = strconv.ParseFloat(fields[1], 64)
|
||||
self.Fifteen, _ = strconv.ParseFloat(fields[2], 64)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Mem) Get() error {
|
||||
|
||||
table, err := parseMeminfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Total, _ = table["MemTotal"]
|
||||
self.Free, _ = table["MemFree"]
|
||||
buffers, _ := table["Buffers"]
|
||||
cached, _ := table["Cached"]
|
||||
|
||||
if available, ok := table["MemAvailable"]; ok {
|
||||
// MemAvailable is in /proc/meminfo (kernel 3.14+)
|
||||
self.ActualFree = available
|
||||
} else {
|
||||
self.ActualFree = self.Free + buffers + cached
|
||||
}
|
||||
|
||||
self.Used = self.Total - self.Free
|
||||
self.ActualUsed = self.Total - self.ActualFree
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Swap) Get() error {
|
||||
|
||||
table, err := parseMeminfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.Total, _ = table["SwapTotal"]
|
||||
self.Free, _ = table["SwapFree"]
|
||||
|
||||
self.Used = self.Total - self.Free
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Cpu) Get() error {
|
||||
return readFile(Procd+"/stat", func(line string) bool {
|
||||
if len(line) > 4 && line[0:4] == "cpu " {
|
||||
parseCpuStat(self, line)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func (self *CpuList) Get() error {
|
||||
capacity := len(self.List)
|
||||
if capacity == 0 {
|
||||
capacity = 4
|
||||
}
|
||||
list := make([]Cpu, 0, capacity)
|
||||
|
||||
err := readFile(Procd+"/stat", func(line string) bool {
|
||||
if len(line) > 3 && line[0:3] == "cpu" && line[3] != ' ' {
|
||||
cpu := Cpu{}
|
||||
parseCpuStat(&cpu, line)
|
||||
list = append(list, cpu)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
self.List = list
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *FileSystemList) Get() error {
|
||||
capacity := len(self.List)
|
||||
if capacity == 0 {
|
||||
capacity = 10
|
||||
}
|
||||
fslist := make([]FileSystem, 0, capacity)
|
||||
|
||||
err := readFile(getMountTableFileName(), func(line string) bool {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
fs := FileSystem{}
|
||||
fs.DevName = fields[0]
|
||||
fs.DirName = fields[1]
|
||||
fs.SysTypeName = fields[2]
|
||||
fs.Options = fields[3]
|
||||
|
||||
fslist = append(fslist, fs)
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
self.List = fslist
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *ProcList) Get() error {
|
||||
dir, err := os.Open(Procd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
const readAllDirnames = -1 // see os.File.Readdirnames doc
|
||||
|
||||
names, err := dir.Readdirnames(readAllDirnames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
capacity := len(names)
|
||||
list := make([]int, 0, capacity)
|
||||
|
||||
for _, name := range names {
|
||||
if name[0] < '0' || name[0] > '9' {
|
||||
continue
|
||||
}
|
||||
pid, err := strconv.Atoi(name)
|
||||
if err == nil {
|
||||
list = append(list, pid)
|
||||
}
|
||||
}
|
||||
|
||||
self.List = list
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcState) Get(pid int) error {
|
||||
data, err := readProcFile(pid, "stat")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract the comm value with is surrounded by parentheses.
|
||||
lIdx := bytes.Index(data, []byte("("))
|
||||
rIdx := bytes.LastIndex(data, []byte(")"))
|
||||
if lIdx < 0 || rIdx < 0 || lIdx >= rIdx || rIdx+2 >= len(data) {
|
||||
return fmt.Errorf("failed to extract comm for pid %d from '%v'", pid, string(data))
|
||||
}
|
||||
self.Name = string(data[lIdx+1 : rIdx])
|
||||
|
||||
// Extract the rest of the fields that we are interested in.
|
||||
fields := bytes.Fields(data[rIdx+2:])
|
||||
if len(fields) <= 36 {
|
||||
return fmt.Errorf("expected more stat fields for pid %d from '%v'", pid, string(data))
|
||||
}
|
||||
|
||||
interests := bytes.Join([][]byte{
|
||||
fields[0], // state
|
||||
fields[1], // ppid
|
||||
fields[2], // pgrp
|
||||
fields[4], // tty_nr
|
||||
fields[15], // priority
|
||||
fields[16], // nice
|
||||
fields[36], // processor (last processor executed on)
|
||||
}, []byte(" "))
|
||||
|
||||
var state string
|
||||
_, err = fmt.Fscan(bytes.NewBuffer(interests),
|
||||
&state,
|
||||
&self.Ppid,
|
||||
&self.Pgid,
|
||||
&self.Tty,
|
||||
&self.Priority,
|
||||
&self.Nice,
|
||||
&self.Processor,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse stat fields for pid %d from '%v': %v", pid, string(data), err)
|
||||
}
|
||||
self.State = RunState(state[0])
|
||||
|
||||
// Read /proc/[pid]/status to get the uid, then lookup uid to get username.
|
||||
status, err := getProcStatus(pid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read process status for pid %d: %v", pid, err)
|
||||
}
|
||||
uids, err := getUIDs(status)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read process status for pid %d: %v", pid, err)
|
||||
}
|
||||
user, err := user.LookupId(uids[0])
|
||||
if err == nil {
|
||||
self.Username = user.Username
|
||||
} else {
|
||||
self.Username = uids[0]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcMem) Get(pid int) error {
|
||||
contents, err := readProcFile(pid, "statm")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fields := strings.Fields(string(contents))
|
||||
|
||||
size, _ := strtoull(fields[0])
|
||||
self.Size = size << 12
|
||||
|
||||
rss, _ := strtoull(fields[1])
|
||||
self.Resident = rss << 12
|
||||
|
||||
share, _ := strtoull(fields[2])
|
||||
self.Share = share << 12
|
||||
|
||||
contents, err = readProcFile(pid, "stat")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fields = strings.Fields(string(contents))
|
||||
|
||||
self.MinorFaults, _ = strtoull(fields[10])
|
||||
self.MajorFaults, _ = strtoull(fields[12])
|
||||
self.PageFaults = self.MinorFaults + self.MajorFaults
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcTime) Get(pid int) error {
|
||||
contents, err := readProcFile(pid, "stat")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fields := strings.Fields(string(contents))
|
||||
|
||||
user, _ := strtoull(fields[13])
|
||||
sys, _ := strtoull(fields[14])
|
||||
// convert to millis
|
||||
self.User = user * (1000 / system.ticks)
|
||||
self.Sys = sys * (1000 / system.ticks)
|
||||
self.Total = self.User + self.Sys
|
||||
|
||||
// convert to millis
|
||||
self.StartTime, _ = strtoull(fields[21])
|
||||
self.StartTime /= system.ticks
|
||||
self.StartTime += system.btime
|
||||
self.StartTime *= 1000
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcArgs) Get(pid int) error {
|
||||
contents, err := readProcFile(pid, "cmdline")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bbuf := bytes.NewBuffer(contents)
|
||||
|
||||
var args []string
|
||||
|
||||
for {
|
||||
arg, err := bbuf.ReadBytes(0)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
args = append(args, string(chop(arg)))
|
||||
}
|
||||
|
||||
self.List = args
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcEnv) Get(pid int) error {
|
||||
contents, err := readProcFile(pid, "environ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if self.Vars == nil {
|
||||
self.Vars = map[string]string{}
|
||||
}
|
||||
|
||||
pairs := bytes.Split(contents, []byte{0})
|
||||
for _, kv := range pairs {
|
||||
parts := bytes.SplitN(kv, []byte{'='}, 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := string(bytes.TrimSpace(parts[0]))
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
self.Vars[key] = string(bytes.TrimSpace(parts[1]))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcExe) Get(pid int) error {
|
||||
fields := map[string]*string{
|
||||
"exe": &self.Name,
|
||||
"cwd": &self.Cwd,
|
||||
"root": &self.Root,
|
||||
}
|
||||
|
||||
for name, field := range fields {
|
||||
val, err := os.Readlink(procFileName(pid, name))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*field = val
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseMeminfo() (map[string]uint64, error) {
|
||||
table := map[string]uint64{}
|
||||
|
||||
err := readFile(Procd+"/meminfo", func(line string) bool {
|
||||
fields := strings.Split(line, ":")
|
||||
|
||||
if len(fields) != 2 {
|
||||
return true // skip on errors
|
||||
}
|
||||
|
||||
num := strings.TrimLeft(fields[1], " ")
|
||||
val, err := strtoull(strings.Fields(num)[0])
|
||||
if err != nil {
|
||||
return true // skip on errors
|
||||
}
|
||||
table[fields[0]] = val * 1024 //in bytes
|
||||
|
||||
return true
|
||||
})
|
||||
return table, err
|
||||
}
|
||||
|
||||
func readFile(file string, handler func(string) bool) error {
|
||||
contents, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(bytes.NewBuffer(contents))
|
||||
|
||||
for {
|
||||
line, _, err := reader.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if !handler(string(line)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func strtoull(val string) (uint64, error) {
|
||||
return strconv.ParseUint(val, 10, 64)
|
||||
}
|
||||
|
||||
func procFileName(pid int, name string) string {
|
||||
return Procd + "/" + strconv.Itoa(pid) + "/" + name
|
||||
}
|
||||
|
||||
func readProcFile(pid int, name string) ([]byte, error) {
|
||||
path := procFileName(pid, name)
|
||||
contents, err := ioutil.ReadFile(path)
|
||||
|
||||
if err != nil {
|
||||
if perr, ok := err.(*os.PathError); ok {
|
||||
if perr.Err == syscall.ENOENT {
|
||||
return nil, syscall.ESRCH
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contents, err
|
||||
}
|
||||
|
||||
// getProcStatus reads /proc/[pid]/status which contains process status
|
||||
// information in human readable form.
|
||||
func getProcStatus(pid int) (map[string]string, error) {
|
||||
status := make(map[string]string, 42)
|
||||
path := filepath.Join(Procd, strconv.Itoa(pid), "status")
|
||||
err := readFile(path, func(line string) bool {
|
||||
fields := strings.SplitN(line, ":", 2)
|
||||
if len(fields) == 2 {
|
||||
status[fields[0]] = strings.TrimSpace(fields[1])
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
return status, err
|
||||
}
|
||||
|
||||
// getUIDs reads the "Uid" value from status and splits it into four values --
|
||||
// real, effective, saved set, and file system UIDs.
|
||||
func getUIDs(status map[string]string) ([]string, error) {
|
||||
uidLine, ok := status["Uid"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Uid not found in proc status")
|
||||
}
|
||||
|
||||
uidStrs := strings.Fields(uidLine)
|
||||
if len(uidStrs) != 4 {
|
||||
return nil, fmt.Errorf("Uid line ('%s') did not contain four values", uidLine)
|
||||
}
|
||||
|
||||
return uidStrs, nil
|
||||
}
|
418
vendor/github.com/elastic/gosigar/sigar_openbsd.go
generated
vendored
Normal file
418
vendor/github.com/elastic/gosigar/sigar_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,418 @@
|
||||
// Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>.
|
||||
|
||||
// +build openbsd
|
||||
|
||||
package gosigar
|
||||
|
||||
/*
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/sched.h>
|
||||
#include <sys/swap.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
//import "github.com/davecgh/go-spew/spew"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Uvmexp struct {
|
||||
pagesize uint32
|
||||
pagemask uint32
|
||||
pageshift uint32
|
||||
npages uint32
|
||||
free uint32
|
||||
active uint32
|
||||
inactive uint32
|
||||
paging uint32
|
||||
wired uint32
|
||||
zeropages uint32
|
||||
reserve_pagedaemon uint32
|
||||
reserve_kernel uint32
|
||||
anonpages uint32
|
||||
vnodepages uint32
|
||||
vtextpages uint32
|
||||
freemin uint32
|
||||
freetarg uint32
|
||||
inactarg uint32
|
||||
wiredmax uint32
|
||||
anonmin uint32
|
||||
vtextmin uint32
|
||||
vnodemin uint32
|
||||
anonminpct uint32
|
||||
vtextmi uint32
|
||||
npct uint32
|
||||
vnodeminpct uint32
|
||||
nswapdev uint32
|
||||
swpages uint32
|
||||
swpginuse uint32
|
||||
swpgonly uint32
|
||||
nswget uint32
|
||||
nanon uint32
|
||||
nanonneeded uint32
|
||||
nfreeanon uint32
|
||||
faults uint32
|
||||
traps uint32
|
||||
intrs uint32
|
||||
swtch uint32
|
||||
softs uint32
|
||||
syscalls uint32
|
||||
pageins uint32
|
||||
obsolete_swapins uint32
|
||||
obsolete_swapouts uint32
|
||||
pgswapin uint32
|
||||
pgswapout uint32
|
||||
forks uint32
|
||||
forks_ppwait uint32
|
||||
forks_sharevm uint32
|
||||
pga_zerohit uint32
|
||||
pga_zeromiss uint32
|
||||
zeroaborts uint32
|
||||
fltnoram uint32
|
||||
fltnoanon uint32
|
||||
fltpgwait uint32
|
||||
fltpgrele uint32
|
||||
fltrelck uint32
|
||||
fltrelckok uint32
|
||||
fltanget uint32
|
||||
fltanretry uint32
|
||||
fltamcopy uint32
|
||||
fltnamap uint32
|
||||
fltnomap uint32
|
||||
fltlget uint32
|
||||
fltget uint32
|
||||
flt_anon uint32
|
||||
flt_acow uint32
|
||||
flt_obj uint32
|
||||
flt_prcopy uint32
|
||||
flt_przero uint32
|
||||
pdwoke uint32
|
||||
pdrevs uint32
|
||||
pdswout uint32
|
||||
pdfreed uint32
|
||||
pdscans uint32
|
||||
pdanscan uint32
|
||||
pdobscan uint32
|
||||
pdreact uint32
|
||||
pdbusy uint32
|
||||
pdpageouts uint32
|
||||
pdpending uint32
|
||||
pddeact uint32
|
||||
pdreanon uint32
|
||||
pdrevnode uint32
|
||||
pdrevtext uint32
|
||||
fpswtch uint32
|
||||
kmapent uint32
|
||||
}
|
||||
|
||||
type Bcachestats struct {
|
||||
numbufs uint64
|
||||
numbufpages uint64
|
||||
numdirtypages uint64
|
||||
numcleanpages uint64
|
||||
pendingwrites uint64
|
||||
pendingreads uint64
|
||||
numwrites uint64
|
||||
numreads uint64
|
||||
cachehits uint64
|
||||
busymapped uint64
|
||||
dmapages uint64
|
||||
highpages uint64
|
||||
delwribufs uint64
|
||||
kvaslots uint64
|
||||
kvaslots_avail uint64
|
||||
}
|
||||
|
||||
type Swapent struct {
|
||||
se_dev C.dev_t
|
||||
se_flags int32
|
||||
se_nblks int32
|
||||
se_inuse int32
|
||||
se_priority int32
|
||||
sw_path []byte
|
||||
}
|
||||
|
||||
func (self *FileSystemList) Get() error {
|
||||
num, err := syscall.Getfsstat(nil, C.MNT_NOWAIT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := make([]syscall.Statfs_t, num)
|
||||
|
||||
_, err = syscall.Getfsstat(buf, C.MNT_NOWAIT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fslist := make([]FileSystem, 0, num)
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
fs := FileSystem{}
|
||||
|
||||
fs.DirName = bytePtrToString(&buf[i].F_mntonname[0])
|
||||
fs.DevName = bytePtrToString(&buf[i].F_mntfromname[0])
|
||||
fs.SysTypeName = bytePtrToString(&buf[i].F_fstypename[0])
|
||||
|
||||
fslist = append(fslist, fs)
|
||||
}
|
||||
|
||||
self.List = fslist
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *FileSystemUsage) Get(path string) error {
|
||||
stat := syscall.Statfs_t{}
|
||||
err := syscall.Statfs(path, &stat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Total = uint64(stat.F_blocks) * uint64(stat.F_bsize)
|
||||
self.Free = uint64(stat.F_bfree) * uint64(stat.F_bsize)
|
||||
self.Avail = uint64(stat.F_bavail) * uint64(stat.F_bsize)
|
||||
self.Used = self.Total - self.Free
|
||||
self.Files = stat.F_files
|
||||
self.FreeFiles = stat.F_ffree
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FDUsage) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *LoadAverage) Get() error {
|
||||
avg := []C.double{0, 0, 0}
|
||||
|
||||
C.getloadavg(&avg[0], C.int(len(avg)))
|
||||
|
||||
self.One = float64(avg[0])
|
||||
self.Five = float64(avg[1])
|
||||
self.Fifteen = float64(avg[2])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Uptime) Get() error {
|
||||
tv := syscall.Timeval{}
|
||||
mib := [2]int32{C.CTL_KERN, C.KERN_BOOTTIME}
|
||||
|
||||
n := uintptr(0)
|
||||
// First we determine how much memory we'll need to pass later on (via `n`)
|
||||
_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Now perform the actual sysctl(3) call, storing the result in tv
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&tv)), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Mem) Get() error {
|
||||
n := uintptr(0)
|
||||
|
||||
var uvmexp Uvmexp
|
||||
mib := [2]int32{C.CTL_VM, C.VM_UVMEXP}
|
||||
n = uintptr(0)
|
||||
// First we determine how much memory we'll need to pass later on (via `n`)
|
||||
_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&uvmexp)), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var bcachestats Bcachestats
|
||||
mib3 := [3]int32{C.CTL_VFS, C.VFS_GENERIC, C.VFS_BCACHESTAT}
|
||||
n = uintptr(0)
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, uintptr(unsafe.Pointer(&bcachestats)), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.Total = uint64(uvmexp.npages) << uvmexp.pageshift
|
||||
self.Used = uint64(uvmexp.npages-uvmexp.free) << uvmexp.pageshift
|
||||
self.Free = uint64(uvmexp.free) << uvmexp.pageshift
|
||||
|
||||
self.ActualFree = self.Free + (uint64(bcachestats.numbufpages) << uvmexp.pageshift)
|
||||
self.ActualUsed = self.Used - (uint64(bcachestats.numbufpages) << uvmexp.pageshift)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Swap) Get() error {
|
||||
nswap := C.swapctl(C.SWAP_NSWAP, unsafe.Pointer(uintptr(0)), 0)
|
||||
|
||||
// If there are no swap devices, nothing to do here.
|
||||
if nswap == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
swdev := make([]Swapent, nswap)
|
||||
|
||||
rnswap := C.swapctl(C.SWAP_STATS, unsafe.Pointer(&swdev[0]), nswap)
|
||||
if rnswap == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < int(nswap); i++ {
|
||||
if swdev[i].se_flags&C.SWF_ENABLE == 2 {
|
||||
self.Used = self.Used + uint64(swdev[i].se_inuse/(1024/C.DEV_BSIZE))
|
||||
self.Total = self.Total + uint64(swdev[i].se_nblks/(1024/C.DEV_BSIZE))
|
||||
}
|
||||
}
|
||||
|
||||
self.Free = self.Total - self.Used
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Cpu) Get() error {
|
||||
load := [C.CPUSTATES]C.long{C.CP_USER, C.CP_NICE, C.CP_SYS, C.CP_INTR, C.CP_IDLE}
|
||||
|
||||
mib := [2]int32{C.CTL_KERN, C.KERN_CPTIME}
|
||||
n := uintptr(0)
|
||||
// First we determine how much memory we'll need to pass later on (via `n`)
|
||||
_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&load)), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.User = uint64(load[0])
|
||||
self.Nice = uint64(load[1])
|
||||
self.Sys = uint64(load[2])
|
||||
self.Irq = uint64(load[3])
|
||||
self.Idle = uint64(load[4])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *CpuList) Get() error {
|
||||
mib := [2]int32{C.CTL_HW, C.HW_NCPU}
|
||||
var ncpu int
|
||||
|
||||
n := uintptr(0)
|
||||
// First we determine how much memory we'll need to pass later on (via `n`)
|
||||
_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Now perform the actual sysctl(3) call, storing the result in ncpu
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&ncpu)), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
load := [C.CPUSTATES]C.long{C.CP_USER, C.CP_NICE, C.CP_SYS, C.CP_INTR, C.CP_IDLE}
|
||||
|
||||
self.List = make([]Cpu, ncpu)
|
||||
for curcpu := range self.List {
|
||||
sysctlCptime(ncpu, curcpu, &load)
|
||||
fillCpu(&self.List[curcpu], load)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcList) Get() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcArgs) Get(pid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcEnv) Get(pid int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *ProcState) Get(pid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcMem) Get(pid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcTime) Get(pid int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *ProcExe) Get(pid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcFDUsage) Get(pid int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func fillCpu(cpu *Cpu, load [C.CPUSTATES]C.long) {
|
||||
cpu.User = uint64(load[0])
|
||||
cpu.Nice = uint64(load[1])
|
||||
cpu.Sys = uint64(load[2])
|
||||
cpu.Irq = uint64(load[3])
|
||||
cpu.Idle = uint64(load[4])
|
||||
}
|
||||
|
||||
func sysctlCptime(ncpu int, curcpu int, load *[C.CPUSTATES]C.long) error {
|
||||
var mib []int32
|
||||
|
||||
// Use the correct mib based on the number of CPUs and fill out the
|
||||
// current CPU number in case of SMP. (0 indexed cf. self.List)
|
||||
if ncpu == 0 {
|
||||
mib = []int32{C.CTL_KERN, C.KERN_CPTIME}
|
||||
} else {
|
||||
mib = []int32{C.CTL_KERN, C.KERN_CPTIME2, int32(curcpu)}
|
||||
}
|
||||
|
||||
len := len(mib)
|
||||
|
||||
n := uintptr(0)
|
||||
// First we determine how much memory we'll need to pass later on (via `n`)
|
||||
_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), uintptr(unsafe.Pointer(load)), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errno != 0 || n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
71
vendor/github.com/elastic/gosigar/sigar_stub.go
generated
vendored
Normal file
71
vendor/github.com/elastic/gosigar/sigar_stub.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
// +build !darwin,!freebsd,!linux,!openbsd,!windows
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func (c *Cpu) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (l *LoadAverage) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (m *Mem) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (s *Swap) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (f *FDUsage) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcTime) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *FileSystemUsage) Get(path string) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *CpuList) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcState) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcExe) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcMem) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcFDUsage) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcEnv) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcList) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (p *ProcArgs) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *Rusage) Get(int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
69
vendor/github.com/elastic/gosigar/sigar_unix.go
generated
vendored
Normal file
69
vendor/github.com/elastic/gosigar/sigar_unix.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2012 VMware, Inc.
|
||||
|
||||
// +build darwin freebsd linux
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (self *FileSystemUsage) Get(path string) error {
|
||||
stat := syscall.Statfs_t{}
|
||||
err := syscall.Statfs(path, &stat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Total = uint64(stat.Blocks) * uint64(stat.Bsize)
|
||||
self.Free = uint64(stat.Bfree) * uint64(stat.Bsize)
|
||||
self.Avail = uint64(stat.Bavail) * uint64(stat.Bsize)
|
||||
self.Used = self.Total - self.Free
|
||||
self.Files = stat.Files
|
||||
self.FreeFiles = uint64(stat.Ffree)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Rusage) Get(who int) error {
|
||||
ru, err := getResourceUsage(who)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uTime := convertRtimeToDur(ru.Utime)
|
||||
sTime := convertRtimeToDur(ru.Stime)
|
||||
|
||||
r.Utime = uTime
|
||||
r.Stime = sTime
|
||||
r.Maxrss = int64(ru.Maxrss)
|
||||
r.Ixrss = int64(ru.Ixrss)
|
||||
r.Idrss = int64(ru.Idrss)
|
||||
r.Isrss = int64(ru.Isrss)
|
||||
r.Minflt = int64(ru.Minflt)
|
||||
r.Majflt = int64(ru.Majflt)
|
||||
r.Nswap = int64(ru.Nswap)
|
||||
r.Inblock = int64(ru.Inblock)
|
||||
r.Oublock = int64(ru.Oublock)
|
||||
r.Msgsnd = int64(ru.Msgsnd)
|
||||
r.Msgrcv = int64(ru.Msgrcv)
|
||||
r.Nsignals = int64(ru.Nsignals)
|
||||
r.Nvcsw = int64(ru.Nvcsw)
|
||||
r.Nivcsw = int64(ru.Nivcsw)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getResourceUsage(who int) (unix.Rusage, error) {
|
||||
r := unix.Rusage{}
|
||||
err := unix.Getrusage(who, &r)
|
||||
|
||||
return r, err
|
||||
}
|
||||
|
||||
func convertRtimeToDur(t unix.Timeval) time.Duration {
|
||||
return time.Duration(t.Nano())
|
||||
}
|
22
vendor/github.com/elastic/gosigar/sigar_util.go
generated
vendored
Normal file
22
vendor/github.com/elastic/gosigar/sigar_util.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2012 VMware, Inc.
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func bytePtrToString(ptr *int8) string {
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(ptr))
|
||||
|
||||
n := 0
|
||||
for bytes[n] != 0 {
|
||||
n++
|
||||
}
|
||||
|
||||
return string(bytes[0:n])
|
||||
}
|
||||
|
||||
func chop(buf []byte) []byte {
|
||||
return buf[0 : len(buf)-1]
|
||||
}
|
437
vendor/github.com/elastic/gosigar/sigar_windows.go
generated
vendored
Normal file
437
vendor/github.com/elastic/gosigar/sigar_windows.go
generated
vendored
Normal file
@ -0,0 +1,437 @@
|
||||
// Copyright (c) 2012 VMware, Inc.
|
||||
|
||||
package gosigar
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/elastic/gosigar/sys/windows"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Win32_Process represents a process on the Windows operating system. If
|
||||
// additional fields are added here (that match the Windows struct) they will
|
||||
// automatically be populated when calling getWin32Process.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa394372(v=vs.85).aspx
|
||||
type Win32_Process struct {
|
||||
CommandLine string
|
||||
}
|
||||
|
||||
// Win32_OperatingSystem WMI class represents a Windows-based operating system
|
||||
// installed on a computer.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa394239(v=vs.85).aspx
|
||||
type Win32_OperatingSystem struct {
|
||||
LastBootUpTime time.Time
|
||||
}
|
||||
|
||||
var (
|
||||
// version is Windows version of the host OS.
|
||||
version = windows.GetWindowsVersion()
|
||||
|
||||
// processQueryLimitedInfoAccess is set to PROCESS_QUERY_INFORMATION for Windows
|
||||
// 2003 and XP where PROCESS_QUERY_LIMITED_INFORMATION is unknown. For all newer
|
||||
// OS versions it is set to PROCESS_QUERY_LIMITED_INFORMATION.
|
||||
processQueryLimitedInfoAccess = windows.PROCESS_QUERY_LIMITED_INFORMATION
|
||||
|
||||
// bootTime is the time when the OS was last booted. This value may be nil
|
||||
// on operating systems that do not support the WMI query used to obtain it.
|
||||
bootTime *time.Time
|
||||
bootTimeLock sync.Mutex
|
||||
)
|
||||
|
||||
func init() {
|
||||
if !version.IsWindowsVistaOrGreater() {
|
||||
// PROCESS_QUERY_LIMITED_INFORMATION cannot be used on 2003 or XP.
|
||||
processQueryLimitedInfoAccess = syscall.PROCESS_QUERY_INFORMATION
|
||||
}
|
||||
}
|
||||
|
||||
func (self *LoadAverage) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *FDUsage) Get() error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *ProcEnv) Get(pid int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *ProcExe) Get(pid int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *ProcFDUsage) Get(pid int) error {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
func (self *Uptime) Get() error {
|
||||
// Minimum supported OS is Windows Vista.
|
||||
if !version.IsWindowsVistaOrGreater() {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
bootTimeLock.Lock()
|
||||
defer bootTimeLock.Unlock()
|
||||
if bootTime == nil {
|
||||
os, err := getWin32OperatingSystem()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get boot time using WMI")
|
||||
}
|
||||
bootTime = &os.LastBootUpTime
|
||||
}
|
||||
|
||||
self.Length = time.Since(*bootTime).Seconds()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Mem) Get() error {
|
||||
memoryStatusEx, err := windows.GlobalMemoryStatusEx()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GlobalMemoryStatusEx failed")
|
||||
}
|
||||
|
||||
self.Total = memoryStatusEx.TotalPhys
|
||||
self.Free = memoryStatusEx.AvailPhys
|
||||
self.Used = self.Total - self.Free
|
||||
self.ActualFree = self.Free
|
||||
self.ActualUsed = self.Used
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Swap) Get() error {
|
||||
memoryStatusEx, err := windows.GlobalMemoryStatusEx()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GlobalMemoryStatusEx failed")
|
||||
}
|
||||
|
||||
self.Total = memoryStatusEx.TotalPageFile
|
||||
self.Free = memoryStatusEx.AvailPageFile
|
||||
self.Used = self.Total - self.Free
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Cpu) Get() error {
|
||||
idle, kernel, user, err := windows.GetSystemTimes()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetSystemTimes failed")
|
||||
}
|
||||
|
||||
// CPU times are reported in milliseconds by gosigar.
|
||||
self.Idle = uint64(idle / time.Millisecond)
|
||||
self.Sys = uint64(kernel / time.Millisecond)
|
||||
self.User = uint64(user / time.Millisecond)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *CpuList) Get() error {
|
||||
cpus, err := windows.NtQuerySystemProcessorPerformanceInformation()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NtQuerySystemProcessorPerformanceInformation failed")
|
||||
}
|
||||
|
||||
self.List = make([]Cpu, 0, len(cpus))
|
||||
for _, cpu := range cpus {
|
||||
self.List = append(self.List, Cpu{
|
||||
Idle: uint64(cpu.IdleTime / time.Millisecond),
|
||||
Sys: uint64(cpu.KernelTime / time.Millisecond),
|
||||
User: uint64(cpu.UserTime / time.Millisecond),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FileSystemList) Get() error {
|
||||
drives, err := windows.GetLogicalDriveStrings()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetLogicalDriveStrings failed")
|
||||
}
|
||||
|
||||
for _, drive := range drives {
|
||||
dt, err := windows.GetDriveType(drive)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetDriveType failed")
|
||||
}
|
||||
|
||||
self.List = append(self.List, FileSystem{
|
||||
DirName: drive,
|
||||
DevName: drive,
|
||||
TypeName: dt.String(),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves a list of all process identifiers (PIDs) in the system.
|
||||
func (self *ProcList) Get() error {
|
||||
pids, err := windows.EnumProcesses()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "EnumProcesses failed")
|
||||
}
|
||||
|
||||
// Convert uint32 PIDs to int.
|
||||
self.List = make([]int, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
self.List = append(self.List, int(pid))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcState) Get(pid int) error {
|
||||
var errs []error
|
||||
|
||||
var err error
|
||||
self.Name, err = getProcName(pid)
|
||||
if err != nil {
|
||||
errs = append(errs, errors.Wrap(err, "getProcName failed"))
|
||||
}
|
||||
|
||||
self.State, err = getProcStatus(pid)
|
||||
if err != nil {
|
||||
errs = append(errs, errors.Wrap(err, "getProcStatus failed"))
|
||||
}
|
||||
|
||||
self.Ppid, err = getParentPid(pid)
|
||||
if err != nil {
|
||||
errs = append(errs, errors.Wrap(err, "getParentPid failed"))
|
||||
}
|
||||
|
||||
self.Username, err = getProcCredName(pid)
|
||||
if err != nil {
|
||||
errs = append(errs, errors.Wrap(err, "getProcCredName failed"))
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
errStrs := make([]string, 0, len(errs))
|
||||
for _, e := range errs {
|
||||
errStrs = append(errStrs, e.Error())
|
||||
}
|
||||
return errors.New(strings.Join(errStrs, "; "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getProcName returns the process name associated with the PID.
|
||||
func getProcName(pid int) (string, error) {
|
||||
handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
|
||||
}
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
filename, err := windows.GetProcessImageFileName(handle)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "GetProcessImageFileName failed for pid=%v", pid)
|
||||
}
|
||||
|
||||
return filepath.Base(filename), nil
|
||||
}
|
||||
|
||||
// getProcStatus returns the status of a process.
|
||||
func getProcStatus(pid int) (RunState, error) {
|
||||
handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
|
||||
if err != nil {
|
||||
return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
|
||||
}
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
var exitCode uint32
|
||||
err = syscall.GetExitCodeProcess(handle, &exitCode)
|
||||
if err != nil {
|
||||
return RunStateUnknown, errors.Wrapf(err, "GetExitCodeProcess failed for pid=%v")
|
||||
}
|
||||
|
||||
if exitCode == 259 { //still active
|
||||
return RunStateRun, nil
|
||||
}
|
||||
return RunStateSleep, nil
|
||||
}
|
||||
|
||||
// getParentPid returns the parent process ID of a process.
|
||||
func getParentPid(pid int) (int, error) {
|
||||
handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
|
||||
if err != nil {
|
||||
return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
|
||||
}
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
procInfo, err := windows.NtQueryProcessBasicInformation(handle)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid)
|
||||
}
|
||||
|
||||
return int(procInfo.InheritedFromUniqueProcessID), nil
|
||||
}
|
||||
|
||||
func getProcCredName(pid int) (string, error) {
|
||||
handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
|
||||
}
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
// Find process token via win32.
|
||||
var token syscall.Token
|
||||
err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "OpenProcessToken failed for pid=%v", pid)
|
||||
}
|
||||
|
||||
// Find the token user.
|
||||
tokenUser, err := token.GetTokenUser()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "GetTokenInformation failed for pid=%v", pid)
|
||||
}
|
||||
|
||||
// Close token to prevent handle leaks.
|
||||
err = token.Close()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed while closing process token handle for pid=%v", pid)
|
||||
}
|
||||
|
||||
// Look up domain account by SID.
|
||||
account, domain, _, err := tokenUser.User.Sid.LookupAccount("")
|
||||
if err != nil {
|
||||
sid, sidErr := tokenUser.User.Sid.String()
|
||||
if sidErr != nil {
|
||||
return "", errors.Wrapf(err, "failed while looking up account name for pid=%v", pid)
|
||||
}
|
||||
return "", errors.Wrapf(err, "failed while looking up account name for SID=%v of pid=%v", sid, pid)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`%s\%s`, domain, account), nil
|
||||
}
|
||||
|
||||
func (self *ProcMem) Get(pid int) error {
|
||||
handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
|
||||
}
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
counters, err := windows.GetProcessMemoryInfo(handle)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetProcessMemoryInfo failed for pid=%v", pid)
|
||||
}
|
||||
|
||||
self.Resident = uint64(counters.WorkingSetSize)
|
||||
self.Size = uint64(counters.PrivateUsage)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ProcTime) Get(pid int) error {
|
||||
cpu, err := getProcTimes(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Windows epoch times are expressed as time elapsed since midnight on
|
||||
// January 1, 1601 at Greenwich, England. This converts the Filetime to
|
||||
// unix epoch in milliseconds.
|
||||
self.StartTime = uint64(cpu.CreationTime.Nanoseconds() / 1e6)
|
||||
|
||||
// Convert to millis.
|
||||
self.User = uint64(windows.FiletimeToDuration(&cpu.UserTime).Nanoseconds() / 1e6)
|
||||
self.Sys = uint64(windows.FiletimeToDuration(&cpu.KernelTime).Nanoseconds() / 1e6)
|
||||
self.Total = self.User + self.Sys
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getProcTimes(pid int) (*syscall.Rusage, error) {
|
||||
handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
|
||||
}
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
var cpu syscall.Rusage
|
||||
if err := syscall.GetProcessTimes(handle, &cpu.CreationTime, &cpu.ExitTime, &cpu.KernelTime, &cpu.UserTime); err != nil {
|
||||
return nil, errors.Wrapf(err, "GetProcessTimes failed for pid=%v", pid)
|
||||
}
|
||||
|
||||
return &cpu, nil
|
||||
}
|
||||
|
||||
func (self *ProcArgs) Get(pid int) error {
|
||||
// The minimum supported client for Win32_Process is Windows Vista.
|
||||
if !version.IsWindowsVistaOrGreater() {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
process, err := getWin32Process(int32(pid))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ProcArgs failed for pid=%v", pid)
|
||||
}
|
||||
|
||||
self.List = []string{process.CommandLine}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FileSystemUsage) Get(path string) error {
|
||||
freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, err := windows.GetDiskFreeSpaceEx(path)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetDiskFreeSpaceEx failed")
|
||||
}
|
||||
|
||||
self.Total = totalNumberOfBytes
|
||||
self.Free = totalNumberOfFreeBytes
|
||||
self.Used = self.Total - self.Free
|
||||
self.Avail = freeBytesAvailable
|
||||
return nil
|
||||
}
|
||||
|
||||
// getWin32Process gets information about the process with the given process ID.
|
||||
// It uses a WMI query to get the information from the local system.
|
||||
func getWin32Process(pid int32) (Win32_Process, error) {
|
||||
var dst []Win32_Process
|
||||
query := fmt.Sprintf("WHERE ProcessId = %d", pid)
|
||||
q := wmi.CreateQuery(&dst, query)
|
||||
err := wmi.Query(q, &dst)
|
||||
if err != nil {
|
||||
return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: %v", query, err)
|
||||
}
|
||||
if len(dst) < 1 {
|
||||
return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: Process not found", query)
|
||||
}
|
||||
return dst[0], nil
|
||||
}
|
||||
|
||||
func getWin32OperatingSystem() (Win32_OperatingSystem, error) {
|
||||
var dst []Win32_OperatingSystem
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
err := wmi.Query(q, &dst)
|
||||
if err != nil {
|
||||
return Win32_OperatingSystem{}, errors.Wrap(err, "wmi query for Win32_OperatingSystem failed")
|
||||
}
|
||||
if len(dst) != 1 {
|
||||
return Win32_OperatingSystem{}, errors.New("wmi query for Win32_OperatingSystem failed")
|
||||
}
|
||||
return dst[0], nil
|
||||
}
|
||||
|
||||
func (self *Rusage) Get(who int) error {
|
||||
if who != 0 {
|
||||
return ErrNotImplemented{runtime.GOOS}
|
||||
}
|
||||
|
||||
pid := os.Getpid()
|
||||
cpu, err := getProcTimes(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.Utime = windows.FiletimeToDuration(&cpu.UserTime)
|
||||
self.Stime = windows.FiletimeToDuration(&cpu.KernelTime)
|
||||
|
||||
return nil
|
||||
}
|
2
vendor/github.com/elastic/gosigar/sys/windows/doc.go
generated
vendored
Normal file
2
vendor/github.com/elastic/gosigar/sys/windows/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
// Package windows contains various Windows system call.
|
||||
package windows
|
132
vendor/github.com/elastic/gosigar/sys/windows/ntquery.go
generated
vendored
Normal file
132
vendor/github.com/elastic/gosigar/sys/windows/ntquery.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// On both 32-bit and 64-bit systems NtQuerySystemInformation expects the
|
||||
// size of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION to be 48.
|
||||
const sizeofSystemProcessorPerformanceInformation = 48
|
||||
|
||||
// ProcessBasicInformation is an equivalent representation of
|
||||
// PROCESS_BASIC_INFORMATION in the Windows API.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx
|
||||
type ProcessBasicInformation struct {
|
||||
ExitStatus uint
|
||||
PebBaseAddress uintptr
|
||||
AffinityMask uint
|
||||
BasePriority uint
|
||||
UniqueProcessID uint
|
||||
InheritedFromUniqueProcessID uint
|
||||
}
|
||||
|
||||
// NtQueryProcessBasicInformation queries basic information about the process
|
||||
// associated with the given handle (provided by OpenProcess). It uses the
|
||||
// NtQueryInformationProcess function to collect the data.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx
|
||||
func NtQueryProcessBasicInformation(handle syscall.Handle) (ProcessBasicInformation, error) {
|
||||
var processBasicInfo ProcessBasicInformation
|
||||
processBasicInfoPtr := (*byte)(unsafe.Pointer(&processBasicInfo))
|
||||
size := uint32(unsafe.Sizeof(processBasicInfo))
|
||||
ntStatus, _ := _NtQueryInformationProcess(handle, 0, processBasicInfoPtr, size, nil)
|
||||
if ntStatus != 0 {
|
||||
return ProcessBasicInformation{}, errors.Errorf("NtQueryInformationProcess failed, NTSTATUS=0x%X", ntStatus)
|
||||
}
|
||||
|
||||
return processBasicInfo, nil
|
||||
}
|
||||
|
||||
// SystemProcessorPerformanceInformation contains CPU performance information
|
||||
// for a single CPU.
|
||||
type SystemProcessorPerformanceInformation struct {
|
||||
IdleTime time.Duration // Amount of time spent idle.
|
||||
KernelTime time.Duration // Kernel time does NOT include time spent in idle.
|
||||
UserTime time.Duration // Amount of time spent executing in user mode.
|
||||
}
|
||||
|
||||
// _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION is an equivalent representation of
|
||||
// SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION in the Windows API. This struct is
|
||||
// used internally with NtQuerySystemInformation call and is not exported. The
|
||||
// exported equivalent is SystemProcessorPerformanceInformation.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
|
||||
type _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION struct {
|
||||
IdleTime int64
|
||||
KernelTime int64
|
||||
UserTime int64
|
||||
Reserved1 [2]int64
|
||||
Reserved2 uint32
|
||||
}
|
||||
|
||||
// NtQuerySystemProcessorPerformanceInformation queries CPU performance
|
||||
// information for each CPU. It uses the NtQuerySystemInformation function to
|
||||
// collect the SystemProcessorPerformanceInformation.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
|
||||
func NtQuerySystemProcessorPerformanceInformation() ([]SystemProcessorPerformanceInformation, error) {
|
||||
// NTSTATUS code for success.
|
||||
// https://msdn.microsoft.com/en-us/library/cc704588.aspx
|
||||
const STATUS_SUCCESS = 0
|
||||
|
||||
// From the _SYSTEM_INFORMATION_CLASS enum.
|
||||
// http://processhacker.sourceforge.net/doc/ntexapi_8h.html#ad5d815b48e8f4da1ef2eb7a2f18a54e0
|
||||
const systemProcessorPerformanceInformation = 8
|
||||
|
||||
// Create a buffer large enough to hold an entry for each processor.
|
||||
b := make([]byte, runtime.NumCPU()*sizeofSystemProcessorPerformanceInformation)
|
||||
|
||||
// Query the performance information. Note that this function uses 0 to
|
||||
// indicate success. Most other Windows functions use non-zero for success.
|
||||
var returnLength uint32
|
||||
ntStatus, _ := _NtQuerySystemInformation(systemProcessorPerformanceInformation, &b[0], uint32(len(b)), &returnLength)
|
||||
if ntStatus != STATUS_SUCCESS {
|
||||
return nil, errors.Errorf("NtQuerySystemInformation failed, NTSTATUS=0x%X, bufLength=%v, returnLength=%v", ntStatus, len(b), returnLength)
|
||||
}
|
||||
|
||||
return readSystemProcessorPerformanceInformationBuffer(b)
|
||||
}
|
||||
|
||||
// readSystemProcessorPerformanceInformationBuffer reads from a buffer
|
||||
// containing SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION data. The buffer should
|
||||
// contain one entry for each CPU.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
|
||||
func readSystemProcessorPerformanceInformationBuffer(b []byte) ([]SystemProcessorPerformanceInformation, error) {
|
||||
n := len(b) / sizeofSystemProcessorPerformanceInformation
|
||||
r := bytes.NewReader(b)
|
||||
|
||||
rtn := make([]SystemProcessorPerformanceInformation, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
_, err := r.Seek(int64(i*sizeofSystemProcessorPerformanceInformation), io.SeekStart)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to seek to cpuN=%v in buffer", i)
|
||||
}
|
||||
|
||||
times := make([]uint64, 3)
|
||||
for j := range times {
|
||||
err := binary.Read(r, binary.LittleEndian, ×[j])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed reading cpu times for cpuN=%v", i)
|
||||
}
|
||||
}
|
||||
|
||||
idleTime := time.Duration(times[0] * 100)
|
||||
kernelTime := time.Duration(times[1] * 100)
|
||||
userTime := time.Duration(times[2] * 100)
|
||||
|
||||
rtn = append(rtn, SystemProcessorPerformanceInformation{
|
||||
IdleTime: idleTime,
|
||||
KernelTime: kernelTime - idleTime, // Subtract out idle time from kernel time.
|
||||
UserTime: userTime,
|
||||
})
|
||||
}
|
||||
|
||||
return rtn, nil
|
||||
}
|
272
vendor/github.com/elastic/gosigar/sys/windows/privileges.go
generated
vendored
Normal file
272
vendor/github.com/elastic/gosigar/sys/windows/privileges.go
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Cache of privilege names to LUIDs.
|
||||
var (
|
||||
privNames = make(map[string]int64)
|
||||
privNameMutex sync.Mutex
|
||||
)
|
||||
|
||||
const (
|
||||
// SeDebugPrivilege is the name of the privilege used to debug programs.
|
||||
SeDebugPrivilege = "SeDebugPrivilege"
|
||||
)
|
||||
|
||||
// Errors returned by AdjustTokenPrivileges.
|
||||
const (
|
||||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
|
||||
)
|
||||
|
||||
// Attribute bits for privileges.
|
||||
const (
|
||||
_SE_PRIVILEGE_ENABLED_BY_DEFAULT uint32 = 0x00000001
|
||||
_SE_PRIVILEGE_ENABLED uint32 = 0x00000002
|
||||
_SE_PRIVILEGE_REMOVED uint32 = 0x00000004
|
||||
_SE_PRIVILEGE_USED_FOR_ACCESS uint32 = 0x80000000
|
||||
)
|
||||
|
||||
// Privilege contains information about a single privilege associated with a
|
||||
// Token.
|
||||
type Privilege struct {
|
||||
LUID int64 `json:"-"` // Locally unique identifier (guaranteed only until the system is restarted).
|
||||
Name string `json:"-"`
|
||||
EnabledByDefault bool `json:"enabled_by_default,omitempty"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Removed bool `json:"removed,omitempty"`
|
||||
Used bool `json:"used,omitempty"`
|
||||
}
|
||||
|
||||
func (p Privilege) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(p.Name)
|
||||
buf.WriteString("=(")
|
||||
|
||||
opts := make([]string, 0, 4)
|
||||
if p.EnabledByDefault {
|
||||
opts = append(opts, "Default")
|
||||
}
|
||||
if p.Enabled {
|
||||
opts = append(opts, "Enabled")
|
||||
}
|
||||
if !p.EnabledByDefault && !p.Enabled {
|
||||
opts = append(opts, "Disabled")
|
||||
}
|
||||
if p.Removed {
|
||||
opts = append(opts, "Removed")
|
||||
}
|
||||
if p.Used {
|
||||
opts = append(opts, "Used")
|
||||
}
|
||||
|
||||
buf.WriteString(strings.Join(opts, ", "))
|
||||
buf.WriteString(")")
|
||||
|
||||
// Example: SeDebugPrivilege=(Default, Enabled)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// User represent the information about a Windows account.
|
||||
type User struct {
|
||||
SID string
|
||||
Account string
|
||||
Domain string
|
||||
Type uint32
|
||||
}
|
||||
|
||||
func (u User) String() string {
|
||||
return fmt.Sprintf(`User:%v\%v, SID:%v, Type:%v`, u.Domain, u.Account, u.SID, u.Type)
|
||||
}
|
||||
|
||||
// DebugInfo contains general debug info about the current process.
|
||||
type DebugInfo struct {
|
||||
OSVersion Version // OS version info.
|
||||
Arch string // Architecture of the machine.
|
||||
NumCPU int // Number of CPUs.
|
||||
User User // User that this process is running as.
|
||||
ProcessPrivs map[string]Privilege // Privileges held by the process.
|
||||
}
|
||||
|
||||
func (d DebugInfo) String() string {
|
||||
bytes, _ := json.Marshal(d)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
// LookupPrivilegeName looks up a privilege name given a LUID value.
|
||||
func LookupPrivilegeName(systemName string, luid int64) (string, error) {
|
||||
buf := make([]uint16, 256)
|
||||
bufSize := uint32(len(buf))
|
||||
err := _LookupPrivilegeName(systemName, &luid, &buf[0], &bufSize)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "LookupPrivilegeName failed for luid=%v", luid)
|
||||
}
|
||||
|
||||
return syscall.UTF16ToString(buf), nil
|
||||
}
|
||||
|
||||
// mapPrivileges maps privilege names to LUID values.
|
||||
func mapPrivileges(names []string) ([]int64, error) {
|
||||
var privileges []int64
|
||||
privNameMutex.Lock()
|
||||
defer privNameMutex.Unlock()
|
||||
for _, name := range names {
|
||||
p, ok := privNames[name]
|
||||
if !ok {
|
||||
err := _LookupPrivilegeValue("", name, &p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "LookupPrivilegeValue failed on '%v'", name)
|
||||
}
|
||||
privNames[name] = p
|
||||
}
|
||||
privileges = append(privileges, p)
|
||||
}
|
||||
return privileges, nil
|
||||
}
|
||||
|
||||
// EnableTokenPrivileges enables the specified privileges in the given
|
||||
// Token. The token must have TOKEN_ADJUST_PRIVILEGES access. If the token
|
||||
// does not already contain the privilege it cannot be enabled.
|
||||
func EnableTokenPrivileges(token syscall.Token, privileges ...string) error {
|
||||
privValues, err := mapPrivileges(privileges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
binary.Write(&b, binary.LittleEndian, uint32(len(privValues)))
|
||||
for _, p := range privValues {
|
||||
binary.Write(&b, binary.LittleEndian, p)
|
||||
binary.Write(&b, binary.LittleEndian, uint32(_SE_PRIVILEGE_ENABLED))
|
||||
}
|
||||
|
||||
success, err := _AdjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(b.Len()), nil, nil)
|
||||
if !success {
|
||||
return err
|
||||
}
|
||||
if err == ERROR_NOT_ALL_ASSIGNED {
|
||||
return errors.Wrap(err, "error not all privileges were assigned")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTokenPrivileges returns a list of privileges associated with a token.
|
||||
// The provided token must have at a minimum TOKEN_QUERY access. This is a
|
||||
// wrapper around the GetTokenInformation function.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa446671(v=vs.85).aspx
|
||||
func GetTokenPrivileges(token syscall.Token) (map[string]Privilege, error) {
|
||||
// Determine the required buffer size.
|
||||
var size uint32
|
||||
syscall.GetTokenInformation(token, syscall.TokenPrivileges, nil, 0, &size)
|
||||
|
||||
// This buffer will receive a TOKEN_PRIVILEGE structure.
|
||||
b := bytes.NewBuffer(make([]byte, size))
|
||||
err := syscall.GetTokenInformation(token, syscall.TokenPrivileges, &b.Bytes()[0], uint32(b.Len()), &size)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetTokenInformation failed")
|
||||
}
|
||||
|
||||
var privilegeCount uint32
|
||||
err = binary.Read(b, binary.LittleEndian, &privilegeCount)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read PrivilegeCount")
|
||||
}
|
||||
|
||||
rtn := make(map[string]Privilege, privilegeCount)
|
||||
for i := 0; i < int(privilegeCount); i++ {
|
||||
var luid int64
|
||||
err = binary.Read(b, binary.LittleEndian, &luid)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read LUID value")
|
||||
}
|
||||
|
||||
var attributes uint32
|
||||
err = binary.Read(b, binary.LittleEndian, &attributes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read attributes")
|
||||
}
|
||||
|
||||
name, err := LookupPrivilegeName("", luid)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "LookupPrivilegeName failed for LUID=%v", luid)
|
||||
}
|
||||
|
||||
rtn[name] = Privilege{
|
||||
LUID: luid,
|
||||
Name: name,
|
||||
EnabledByDefault: (attributes & _SE_PRIVILEGE_ENABLED_BY_DEFAULT) > 0,
|
||||
Enabled: (attributes & _SE_PRIVILEGE_ENABLED) > 0,
|
||||
Removed: (attributes & _SE_PRIVILEGE_REMOVED) > 0,
|
||||
Used: (attributes & _SE_PRIVILEGE_USED_FOR_ACCESS) > 0,
|
||||
}
|
||||
}
|
||||
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
// GetTokenUser returns the User associated with the given Token.
|
||||
func GetTokenUser(token syscall.Token) (User, error) {
|
||||
tokenUser, err := token.GetTokenUser()
|
||||
if err != nil {
|
||||
return User{}, errors.Wrap(err, "GetTokenUser failed")
|
||||
}
|
||||
|
||||
var user User
|
||||
user.SID, err = tokenUser.User.Sid.String()
|
||||
if err != nil {
|
||||
return user, errors.Wrap(err, "ConvertSidToStringSid failed")
|
||||
}
|
||||
|
||||
user.Account, user.Domain, user.Type, err = tokenUser.User.Sid.LookupAccount("")
|
||||
if err != nil {
|
||||
return user, errors.Wrap(err, "LookupAccountSid failed")
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// GetDebugInfo returns general debug info about the current process.
|
||||
func GetDebugInfo() (*DebugInfo, error) {
|
||||
h, err := windows.GetCurrentProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var token syscall.Token
|
||||
err = syscall.OpenProcessToken(syscall.Handle(h), syscall.TOKEN_QUERY, &token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privs, err := GetTokenPrivileges(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user, err := GetTokenUser(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DebugInfo{
|
||||
User: user,
|
||||
ProcessPrivs: privs,
|
||||
OSVersion: GetWindowsVersion(),
|
||||
Arch: runtime.GOARCH,
|
||||
NumCPU: runtime.NumCPU(),
|
||||
}, nil
|
||||
}
|
385
vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go
generated
vendored
Normal file
385
vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,385 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
sizeofUint32 = 4
|
||||
sizeofProcessEntry32 = uint32(unsafe.Sizeof(ProcessEntry32{}))
|
||||
sizeofProcessMemoryCountersEx = uint32(unsafe.Sizeof(ProcessMemoryCountersEx{}))
|
||||
sizeofMemoryStatusEx = uint32(unsafe.Sizeof(MemoryStatusEx{}))
|
||||
)
|
||||
|
||||
// Process-specific access rights. Others are declared in the syscall package.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx
|
||||
const (
|
||||
PROCESS_QUERY_LIMITED_INFORMATION uint32 = 0x1000
|
||||
PROCESS_VM_READ uint32 = 0x0010
|
||||
)
|
||||
|
||||
// MAX_PATH is the maximum length for a path in Windows.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
|
||||
const MAX_PATH = 260
|
||||
|
||||
// DriveType represents a type of drive (removable, fixed, CD-ROM, RAM disk, or
|
||||
// network drive).
|
||||
type DriveType uint32
|
||||
|
||||
// Drive types as returned by GetDriveType.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364939(v=vs.85).aspx
|
||||
const (
|
||||
DRIVE_UNKNOWN DriveType = iota
|
||||
DRIVE_NO_ROOT_DIR
|
||||
DRIVE_REMOVABLE
|
||||
DRIVE_FIXED
|
||||
DRIVE_REMOTE
|
||||
DRIVE_CDROM
|
||||
DRIVE_RAMDISK
|
||||
)
|
||||
|
||||
func (dt DriveType) String() string {
|
||||
names := map[DriveType]string{
|
||||
DRIVE_UNKNOWN: "unknown",
|
||||
DRIVE_NO_ROOT_DIR: "invalid",
|
||||
DRIVE_REMOVABLE: "removable",
|
||||
DRIVE_FIXED: "fixed",
|
||||
DRIVE_REMOTE: "remote",
|
||||
DRIVE_CDROM: "cdrom",
|
||||
DRIVE_RAMDISK: "ramdisk",
|
||||
}
|
||||
|
||||
name, found := names[dt]
|
||||
if !found {
|
||||
return "unknown DriveType value"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// Flags that can be used with CreateToolhelp32Snapshot.
|
||||
const (
|
||||
TH32CS_INHERIT uint32 = 0x80000000 // Indicates that the snapshot handle is to be inheritable.
|
||||
TH32CS_SNAPHEAPLIST uint32 = 0x00000001 // Includes all heaps of the process specified in th32ProcessID in the snapshot.
|
||||
TH32CS_SNAPMODULE uint32 = 0x00000008 // Includes all modules of the process specified in th32ProcessID in the snapshot.
|
||||
TH32CS_SNAPMODULE32 uint32 = 0x00000010 // Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit process.
|
||||
TH32CS_SNAPPROCESS uint32 = 0x00000002 // Includes all processes in the system in the snapshot.
|
||||
TH32CS_SNAPTHREAD uint32 = 0x00000004 // Includes all threads in the system in the snapshot.
|
||||
)
|
||||
|
||||
// ProcessEntry32 is an equivalent representation of PROCESSENTRY32 in the
|
||||
// Windows API. It contains a process's information. Do not modify or reorder.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx
|
||||
type ProcessEntry32 struct {
|
||||
size uint32
|
||||
CntUsage uint32
|
||||
ProcessID uint32
|
||||
DefaultHeapID uintptr
|
||||
ModuleID uint32
|
||||
CntThreads uint32
|
||||
ParentProcessID uint32
|
||||
PriorityClassBase int32
|
||||
Flags uint32
|
||||
exeFile [MAX_PATH]uint16
|
||||
}
|
||||
|
||||
// ExeFile returns the name of the executable file for the process. It does
|
||||
// not contain the full path.
|
||||
func (p ProcessEntry32) ExeFile() string {
|
||||
return syscall.UTF16ToString(p.exeFile[:])
|
||||
}
|
||||
|
||||
func (p ProcessEntry32) String() string {
|
||||
return fmt.Sprintf("{CntUsage:%v ProcessID:%v DefaultHeapID:%v ModuleID:%v "+
|
||||
"CntThreads:%v ParentProcessID:%v PriorityClassBase:%v Flags:%v ExeFile:%v",
|
||||
p.CntUsage, p.ProcessID, p.DefaultHeapID, p.ModuleID, p.CntThreads,
|
||||
p.ParentProcessID, p.PriorityClassBase, p.Flags, p.ExeFile())
|
||||
}
|
||||
|
||||
// MemoryStatusEx is an equivalent representation of MEMORYSTATUSEX in the
|
||||
// Windows API. It contains information about the current state of both physical
|
||||
// and virtual memory, including extended memory.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770
|
||||
type MemoryStatusEx struct {
|
||||
length uint32
|
||||
MemoryLoad uint32
|
||||
TotalPhys uint64
|
||||
AvailPhys uint64
|
||||
TotalPageFile uint64
|
||||
AvailPageFile uint64
|
||||
TotalVirtual uint64
|
||||
AvailVirtual uint64
|
||||
AvailExtendedVirtual uint64
|
||||
}
|
||||
|
||||
// ProcessMemoryCountersEx is an equivalent representation of
|
||||
// PROCESS_MEMORY_COUNTERS_EX in the Windows API.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx
|
||||
type ProcessMemoryCountersEx struct {
|
||||
cb uint32
|
||||
PageFaultCount uint32
|
||||
PeakWorkingSetSize uintptr
|
||||
WorkingSetSize uintptr
|
||||
QuotaPeakPagedPoolUsage uintptr
|
||||
QuotaPagedPoolUsage uintptr
|
||||
QuotaPeakNonPagedPoolUsage uintptr
|
||||
QuotaNonPagedPoolUsage uintptr
|
||||
PagefileUsage uintptr
|
||||
PeakPagefileUsage uintptr
|
||||
PrivateUsage uintptr
|
||||
}
|
||||
|
||||
// GetLogicalDriveStrings returns a list of drives in the system.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364975(v=vs.85).aspx
|
||||
func GetLogicalDriveStrings() ([]string, error) {
|
||||
// Determine the size of the buffer required to receive all drives.
|
||||
bufferLength, err := _GetLogicalDriveStringsW(0, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetLogicalDriveStringsW failed to get buffer length")
|
||||
}
|
||||
if bufferLength < 0 {
|
||||
return nil, errors.New("GetLogicalDriveStringsW returned an invalid buffer length")
|
||||
}
|
||||
|
||||
buffer := make([]uint16, bufferLength)
|
||||
_, err = _GetLogicalDriveStringsW(uint32(len(buffer)), &buffer[0])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetLogicalDriveStringsW failed")
|
||||
}
|
||||
|
||||
// Split the uint16 slice at null-terminators.
|
||||
var startIdx int
|
||||
var drivesUTF16 [][]uint16
|
||||
for i, value := range buffer {
|
||||
if value == 0 {
|
||||
drivesUTF16 = append(drivesUTF16, buffer[startIdx:i])
|
||||
startIdx = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the utf16 slices to strings.
|
||||
drives := make([]string, 0, len(drivesUTF16))
|
||||
for _, driveUTF16 := range drivesUTF16 {
|
||||
if len(driveUTF16) > 0 {
|
||||
drives = append(drives, syscall.UTF16ToString(driveUTF16))
|
||||
}
|
||||
}
|
||||
|
||||
return drives, nil
|
||||
}
|
||||
|
||||
// GlobalMemoryStatusEx retrieves information about the system's current usage
|
||||
// of both physical and virtual memory.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx
|
||||
func GlobalMemoryStatusEx() (MemoryStatusEx, error) {
|
||||
memoryStatusEx := MemoryStatusEx{length: sizeofMemoryStatusEx}
|
||||
err := _GlobalMemoryStatusEx(&memoryStatusEx)
|
||||
if err != nil {
|
||||
return MemoryStatusEx{}, errors.Wrap(err, "GlobalMemoryStatusEx failed")
|
||||
}
|
||||
|
||||
return memoryStatusEx, nil
|
||||
}
|
||||
|
||||
// GetProcessMemoryInfo retrieves information about the memory usage of the
|
||||
// specified process.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683219(v=vs.85).aspx
|
||||
func GetProcessMemoryInfo(handle syscall.Handle) (ProcessMemoryCountersEx, error) {
|
||||
processMemoryCountersEx := ProcessMemoryCountersEx{cb: sizeofProcessMemoryCountersEx}
|
||||
err := _GetProcessMemoryInfo(handle, &processMemoryCountersEx, processMemoryCountersEx.cb)
|
||||
if err != nil {
|
||||
return ProcessMemoryCountersEx{}, errors.Wrap(err, "GetProcessMemoryInfo failed")
|
||||
}
|
||||
|
||||
return processMemoryCountersEx, nil
|
||||
}
|
||||
|
||||
// GetProcessImageFileName Retrieves the name of the executable file for the
|
||||
// specified process.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx
|
||||
func GetProcessImageFileName(handle syscall.Handle) (string, error) {
|
||||
buffer := make([]uint16, MAX_PATH)
|
||||
_, err := _GetProcessImageFileName(handle, &buffer[0], uint32(len(buffer)))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "GetProcessImageFileName failed")
|
||||
}
|
||||
|
||||
return syscall.UTF16ToString(buffer), nil
|
||||
}
|
||||
|
||||
// GetSystemTimes retrieves system timing information. On a multiprocessor
|
||||
// system, the values returned are the sum of the designated times across all
|
||||
// processors. The returned kernel time does not include the system idle time.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724400(v=vs.85).aspx
|
||||
func GetSystemTimes() (idle, kernel, user time.Duration, err error) {
|
||||
var idleTime, kernelTime, userTime syscall.Filetime
|
||||
err = _GetSystemTimes(&idleTime, &kernelTime, &userTime)
|
||||
if err != nil {
|
||||
return 0, 0, 0, errors.Wrap(err, "GetSystemTimes failed")
|
||||
}
|
||||
|
||||
idle = FiletimeToDuration(&idleTime)
|
||||
kernel = FiletimeToDuration(&kernelTime) // Kernel time includes idle time so we subtract it out.
|
||||
user = FiletimeToDuration(&userTime)
|
||||
|
||||
return idle, kernel - idle, user, nil
|
||||
}
|
||||
|
||||
// FiletimeToDuration converts a Filetime to a time.Duration. Do not use this
|
||||
// method to convert a Filetime to an actual clock time, for that use
|
||||
// Filetime.Nanosecond().
|
||||
func FiletimeToDuration(ft *syscall.Filetime) time.Duration {
|
||||
n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals
|
||||
return time.Duration(n * 100)
|
||||
}
|
||||
|
||||
// GetDriveType Determines whether a disk drive is a removable, fixed, CD-ROM,
|
||||
// RAM disk, or network drive. A trailing backslash is required on the
|
||||
// rootPathName.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364939
|
||||
func GetDriveType(rootPathName string) (DriveType, error) {
|
||||
rootPathNamePtr, err := syscall.UTF16PtrFromString(rootPathName)
|
||||
if err != nil {
|
||||
return DRIVE_UNKNOWN, errors.Wrapf(err, "UTF16PtrFromString failed for rootPathName=%v", rootPathName)
|
||||
}
|
||||
|
||||
dt, err := _GetDriveType(rootPathNamePtr)
|
||||
if err != nil {
|
||||
return DRIVE_UNKNOWN, errors.Wrapf(err, "GetDriveType failed for rootPathName=%v", rootPathName)
|
||||
}
|
||||
|
||||
return dt, nil
|
||||
}
|
||||
|
||||
// EnumProcesses retrieves the process identifier for each process object in the
|
||||
// system. This function can return a max of 65536 PIDs. If there are more
|
||||
// processes than that then this will not return them all.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682629(v=vs.85).aspx
|
||||
func EnumProcesses() ([]uint32, error) {
|
||||
enumProcesses := func(size int) ([]uint32, error) {
|
||||
var (
|
||||
pids = make([]uint32, size)
|
||||
sizeBytes = len(pids) * sizeofUint32
|
||||
bytesWritten uint32
|
||||
)
|
||||
|
||||
err := _EnumProcesses(&pids[0], uint32(sizeBytes), &bytesWritten)
|
||||
|
||||
pidsWritten := int(bytesWritten) / sizeofUint32
|
||||
if int(bytesWritten)%sizeofUint32 != 0 || pidsWritten > len(pids) {
|
||||
return nil, errors.Errorf("EnumProcesses returned an invalid bytesWritten value of %v", bytesWritten)
|
||||
}
|
||||
pids = pids[:pidsWritten]
|
||||
|
||||
return pids, err
|
||||
}
|
||||
|
||||
// Retry the EnumProcesses call with larger arrays if needed.
|
||||
size := 2048
|
||||
var pids []uint32
|
||||
for tries := 0; tries < 5; tries++ {
|
||||
var err error
|
||||
pids, err = enumProcesses(size)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "EnumProcesses failed")
|
||||
}
|
||||
|
||||
if len(pids) < size {
|
||||
break
|
||||
}
|
||||
|
||||
// Increase the size the pids array and retry the enumProcesses call
|
||||
// because the array wasn't large enough to hold all of the processes.
|
||||
size *= 2
|
||||
}
|
||||
|
||||
return pids, nil
|
||||
}
|
||||
|
||||
// GetDiskFreeSpaceEx retrieves information about the amount of space that is
|
||||
// available on a disk volume, which is the total amount of space, the total
|
||||
// amount of free space, and the total amount of free space available to the
|
||||
// user that is associated with the calling thread.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx
|
||||
func GetDiskFreeSpaceEx(directoryName string) (freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes uint64, err error) {
|
||||
directoryNamePtr, err := syscall.UTF16PtrFromString(directoryName)
|
||||
if err != nil {
|
||||
return 0, 0, 0, errors.Wrapf(err, "UTF16PtrFromString failed for directoryName=%v", directoryName)
|
||||
}
|
||||
|
||||
err = _GetDiskFreeSpaceEx(directoryNamePtr, &freeBytesAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
return freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, nil
|
||||
}
|
||||
|
||||
// CreateToolhelp32Snapshot takes a snapshot of the specified processes, as well
|
||||
// as the heaps, modules, and threads used by these processes.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682489(v=vs.85).aspx
|
||||
func CreateToolhelp32Snapshot(flags, pid uint32) (syscall.Handle, error) {
|
||||
h, err := _CreateToolhelp32Snapshot(flags, pid)
|
||||
if err != nil {
|
||||
return syscall.InvalidHandle, err
|
||||
}
|
||||
if h == syscall.InvalidHandle {
|
||||
return syscall.InvalidHandle, syscall.GetLastError()
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// Process32First retrieves information about the first process encountered in a
|
||||
// system snapshot.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834
|
||||
func Process32First(handle syscall.Handle) (ProcessEntry32, error) {
|
||||
processEntry32 := ProcessEntry32{size: sizeofProcessEntry32}
|
||||
err := _Process32First(handle, &processEntry32)
|
||||
if err != nil {
|
||||
return ProcessEntry32{}, errors.Wrap(err, "Process32First failed")
|
||||
}
|
||||
|
||||
return processEntry32, nil
|
||||
}
|
||||
|
||||
// Process32Next retrieves information about the next process recorded in a
|
||||
// system snapshot. When there are no more processes to iterate then
|
||||
// syscall.ERROR_NO_MORE_FILES is returned (use errors.Cause() to unwrap).
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684836
|
||||
func Process32Next(handle syscall.Handle) (ProcessEntry32, error) {
|
||||
processEntry32 := ProcessEntry32{size: sizeofProcessEntry32}
|
||||
err := _Process32Next(handle, &processEntry32)
|
||||
if err != nil {
|
||||
return ProcessEntry32{}, errors.Wrap(err, "Process32Next failed")
|
||||
}
|
||||
|
||||
return processEntry32, nil
|
||||
}
|
||||
|
||||
// Use "GOOS=windows go generate -v -x ." to generate the source.
|
||||
|
||||
// Add -trace to enable debug prints around syscalls.
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
|
||||
|
||||
// Windows API calls
|
||||
//sys _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) = kernel32.GlobalMemoryStatusEx
|
||||
//sys _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint32, err error) = kernel32.GetLogicalDriveStringsW
|
||||
//sys _GetProcessMemoryInfo(handle syscall.Handle, psmemCounters *ProcessMemoryCountersEx, cb uint32) (err error) = psapi.GetProcessMemoryInfo
|
||||
//sys _GetProcessImageFileName(handle syscall.Handle, outImageFileName *uint16, size uint32) (length uint32, err error) = psapi.GetProcessImageFileNameW
|
||||
//sys _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, userTime *syscall.Filetime) (err error) = kernel32.GetSystemTimes
|
||||
//sys _GetDriveType(rootPathName *uint16) (dt DriveType, err error) = kernel32.GetDriveTypeW
|
||||
//sys _EnumProcesses(processIds *uint32, sizeBytes uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
|
||||
//sys _GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailable *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = kernel32.GetDiskFreeSpaceExW
|
||||
//sys _Process32First(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) = kernel32.Process32FirstW
|
||||
//sys _Process32Next(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) = kernel32.Process32NextW
|
||||
//sys _CreateToolhelp32Snapshot(flags uint32, processID uint32) (handle syscall.Handle, err error) = kernel32.CreateToolhelp32Snapshot
|
||||
//sys _NtQuerySystemInformation(systemInformationClass uint32, systemInformation *byte, systemInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) = ntdll.NtQuerySystemInformation
|
||||
//sys _NtQueryInformationProcess(processHandle syscall.Handle, processInformationClass uint32, processInformation *byte, processInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) = ntdll.NtQueryInformationProcess
|
||||
//sys _LookupPrivilegeName(systemName string, luid *int64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
|
||||
//sys _LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) = advapi32.LookupPrivilegeValueW
|
||||
//sys _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
|
43
vendor/github.com/elastic/gosigar/sys/windows/version.go
generated
vendored
Normal file
43
vendor/github.com/elastic/gosigar/sys/windows/version.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Version identifies a Windows version by major, minor, and build number.
|
||||
type Version struct {
|
||||
Major int
|
||||
Minor int
|
||||
Build int
|
||||
}
|
||||
|
||||
// GetWindowsVersion returns the Windows version information. Applications not
|
||||
// manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version
|
||||
// value (6.2).
|
||||
//
|
||||
// For a table of version numbers see:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
|
||||
func GetWindowsVersion() Version {
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
|
||||
ver, err := syscall.GetVersion()
|
||||
if err != nil {
|
||||
// GetVersion should never return an error.
|
||||
panic(fmt.Errorf("GetVersion failed: %v", err))
|
||||
}
|
||||
|
||||
return Version{
|
||||
Major: int(ver & 0xFF),
|
||||
Minor: int(ver >> 8 & 0xFF),
|
||||
Build: int(ver >> 16),
|
||||
}
|
||||
}
|
||||
|
||||
// IsWindowsVistaOrGreater returns true if the Windows version is Vista or
|
||||
// greater.
|
||||
func (v Version) IsWindowsVistaOrGreater() bool {
|
||||
// Vista is 6.0.
|
||||
return v.Major >= 6 && v.Minor >= 0
|
||||
}
|
260
vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go
generated
vendored
Normal file
260
vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,260 @@
|
||||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
||||
|
||||
package windows
|
||||
|
||||
import "unsafe"
|
||||
import "syscall"
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
var (
|
||||
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
modpsapi = syscall.NewLazyDLL("psapi.dll")
|
||||
modntdll = syscall.NewLazyDLL("ntdll.dll")
|
||||
modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
|
||||
|
||||
procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx")
|
||||
procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW")
|
||||
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||||
procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW")
|
||||
procGetSystemTimes = modkernel32.NewProc("GetSystemTimes")
|
||||
procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW")
|
||||
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
|
||||
procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW")
|
||||
procProcess32FirstW = modkernel32.NewProc("Process32FirstW")
|
||||
procProcess32NextW = modkernel32.NewProc("Process32NextW")
|
||||
procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
|
||||
procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation")
|
||||
procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess")
|
||||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
|
||||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
|
||||
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
|
||||
)
|
||||
|
||||
func _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGlobalMemoryStatusEx.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint32, err error) {
|
||||
r0, _, e1 := syscall.Syscall(procGetLogicalDriveStringsW.Addr(), 2, uintptr(bufferLength), uintptr(unsafe.Pointer(buffer)), 0)
|
||||
length = uint32(r0)
|
||||
if length == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _GetProcessMemoryInfo(handle syscall.Handle, psmemCounters *ProcessMemoryCountersEx, cb uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(psmemCounters)), uintptr(cb))
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _GetProcessImageFileName(handle syscall.Handle, outImageFileName *uint16, size uint32) (length uint32, err error) {
|
||||
r0, _, e1 := syscall.Syscall(procGetProcessImageFileNameW.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(outImageFileName)), uintptr(size))
|
||||
length = uint32(r0)
|
||||
if length == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, userTime *syscall.Filetime) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGetSystemTimes.Addr(), 3, uintptr(unsafe.Pointer(idleTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)))
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _GetDriveType(rootPathName *uint16) (dt DriveType, err error) {
|
||||
r0, _, e1 := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0)
|
||||
dt = DriveType(r0)
|
||||
if dt == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _EnumProcesses(processIds *uint32, sizeBytes uint32, bytesReturned *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(processIds)), uintptr(sizeBytes), uintptr(unsafe.Pointer(bytesReturned)))
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailable *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailable)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _Process32First(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _Process32Next(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _CreateToolhelp32Snapshot(flags uint32, processID uint32) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processID), 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _NtQuerySystemInformation(systemInformationClass uint32, systemInformation *byte, systemInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(systemInformationClass), uintptr(unsafe.Pointer(systemInformation)), uintptr(systemInformationLength), uintptr(unsafe.Pointer(returnLength)), 0, 0)
|
||||
ntstatus = uint32(r0)
|
||||
if ntstatus == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _NtQueryInformationProcess(processHandle syscall.Handle, processInformationClass uint32, processInformation *byte, processInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(processHandle), uintptr(processInformationClass), uintptr(unsafe.Pointer(processInformation)), uintptr(processInformationLength), uintptr(unsafe.Pointer(returnLength)), 0)
|
||||
ntstatus = uint32(r0)
|
||||
if ntstatus == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _LookupPrivilegeName(systemName string, luid *int64, buffer *uint16, size *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return __LookupPrivilegeName(_p0, luid, buffer, size)
|
||||
}
|
||||
|
||||
func __LookupPrivilegeName(systemName *uint16, luid *int64, buffer *uint16, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var _p1 *uint16
|
||||
_p1, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return __LookupPrivilegeValue(_p0, _p1, luid)
|
||||
}
|
||||
|
||||
func __LookupPrivilegeValue(systemName *uint16, name *uint16, luid *int64) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
|
||||
var _p0 uint32
|
||||
if releaseAll {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
|
||||
success = r0 != 0
|
||||
if true {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user