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:
Kurkó Mihály
2018-01-23 22:51:04 +02:00
committed by Péter Szilágyi
parent ec96216d16
commit 05ade19302
111 changed files with 13162 additions and 3158 deletions

102
vendor/github.com/elastic/gosigar/CHANGELOG.md generated vendored Normal file
View 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
View 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
View 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
View File

@ -0,0 +1,57 @@
# Go sigar [![Build Status](https://travis-ci.org/elastic/gosigar.svg?branch=master)](https://travis-ci.org/elastic/gosigar) [![Build status](https://ci.appveyor.com/api/projects/status/4yh6sa7u97ek5uib/branch/master?svg=true)](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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,2 @@
// Package windows contains various Windows system call.
package windows

View 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, &times[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
}

View 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
}

View 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

View 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
}

View 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
}