mirror of
https://github.com/kemko/nomad.git
synced 2026-01-08 11:25:41 +03:00
Merge branch 'master' into f-plan-endpoint
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -53,3 +53,4 @@ TODO.md
|
||||
|
||||
.terraform
|
||||
*.tfstate*
|
||||
rkt-*
|
||||
|
||||
@@ -7,7 +7,7 @@ services:
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
- 1.6.2
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
BUG FIXES:
|
||||
* core: Updated User, Meta or Resources in a task cause create/destroy updates
|
||||
[GH-1128]
|
||||
[GH-1128, GH-1153]
|
||||
* dicovery: Ensure service and check names are unique [GH-1143, GH-1144]
|
||||
|
||||
## 0.3.2 (April 22, 2016)
|
||||
|
||||
@@ -89,8 +89,7 @@ func (d *AllocDir) UnmountAll() error {
|
||||
if err := d.unmountSharedDir(taskAlloc); err != nil {
|
||||
mErr.Errors = append(mErr.Errors,
|
||||
fmt.Errorf("failed to unmount shared alloc dir %q: %v", taskAlloc, err))
|
||||
}
|
||||
if err := os.RemoveAll(taskAlloc); err != nil {
|
||||
} else if err := os.RemoveAll(taskAlloc); err != nil {
|
||||
mErr.Errors = append(mErr.Errors,
|
||||
fmt.Errorf("failed to delete shared alloc dir %q: %v", taskAlloc, err))
|
||||
}
|
||||
|
||||
26
client/allocdir/alloc_dir_freebsd.go
Normal file
26
client/allocdir/alloc_dir_freebsd.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package allocdir
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Hardlinks the shared directory. As a side-effect the shared directory and
|
||||
// task directory must be on the same filesystem.
|
||||
func (d *AllocDir) mountSharedDir(dir string) error {
|
||||
return syscall.Link(d.SharedDir, dir)
|
||||
}
|
||||
|
||||
func (d *AllocDir) unmountSharedDir(dir string) error {
|
||||
return syscall.Unlink(dir)
|
||||
}
|
||||
|
||||
// MountSpecialDirs mounts the dev and proc file system on the chroot of the
|
||||
// task. It's a no-op on FreeBSD right now.
|
||||
func (d *AllocDir) MountSpecialDirs(taskDir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// unmountSpecialDirs unmounts the dev and proc file system from the chroot
|
||||
func (d *AllocDir) unmountSpecialDirs(taskDir string) error {
|
||||
return nil
|
||||
}
|
||||
@@ -60,9 +60,7 @@ func (d *AllocDir) unmountSpecialDirs(taskDir string) error {
|
||||
if d.pathExists(dev) {
|
||||
if err := syscall.Unmount(dev, 0); err != nil {
|
||||
errs = multierror.Append(errs, fmt.Errorf("Failed to unmount dev (%v): %v", dev, err))
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(dev); err != nil {
|
||||
} else if err := os.RemoveAll(dev); err != nil {
|
||||
errs = multierror.Append(errs, fmt.Errorf("Failed to delete dev directory (%v): %v", dev, err))
|
||||
}
|
||||
}
|
||||
@@ -72,9 +70,7 @@ func (d *AllocDir) unmountSpecialDirs(taskDir string) error {
|
||||
if d.pathExists(proc) {
|
||||
if err := syscall.Unmount(proc, 0); err != nil {
|
||||
errs = multierror.Append(errs, fmt.Errorf("Failed to unmount proc (%v): %v", proc, err))
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(proc); err != nil {
|
||||
} else if err := os.RemoveAll(proc); err != nil {
|
||||
errs = multierror.Append(errs, fmt.Errorf("Failed to delete proc directory (%v): %v", dev, err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build !windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
// Functions shared between linux/darwin.
|
||||
package allocdir
|
||||
@@ -8,7 +8,8 @@ import (
|
||||
"os"
|
||||
"os/user"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (d *AllocDir) linkOrCopy(src, dst string, perm os.FileMode) error {
|
||||
@@ -22,7 +23,7 @@ func (d *AllocDir) linkOrCopy(src, dst string, perm os.FileMode) error {
|
||||
|
||||
func (d *AllocDir) dropDirPermissions(path string) error {
|
||||
// Can't do anything if not root.
|
||||
if syscall.Geteuid() != 0 {
|
||||
if unix.Geteuid() != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -582,6 +582,7 @@ func (c *Client) reservePorts() {
|
||||
func (c *Client) fingerprint() error {
|
||||
whitelist := c.config.ReadStringListToMap("fingerprint.whitelist")
|
||||
whitelistEnabled := len(whitelist) > 0
|
||||
c.logger.Printf("[DEBUG] client: built-in fingerprints: %v", fingerprint.BuiltinFingerprints)
|
||||
|
||||
var applied []string
|
||||
var skipped []string
|
||||
|
||||
@@ -752,9 +752,20 @@ func TestDockerUser(t *testing.T) {
|
||||
handle.Kill()
|
||||
t.Fatalf("Should've failed")
|
||||
}
|
||||
msg := "System error: Unable to find user alice"
|
||||
if !strings.Contains(err.Error(), msg) {
|
||||
t.Fatalf("Expecting '%v' in '%v'", msg, err)
|
||||
|
||||
msgs := []string{
|
||||
"System error: Unable to find user alice",
|
||||
"linux spec user: Unable to find user alice",
|
||||
}
|
||||
var found bool
|
||||
for _, msg := range msgs {
|
||||
if strings.Contains(err.Error(), msg) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("Expected failure string not found, found %q instead", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
@@ -81,33 +80,6 @@ func (d *ExecDriver) Validate(config map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[execDriverAttr]
|
||||
|
||||
// Only enable if cgroups are available and we are root
|
||||
if _, ok := node.Attributes["unique.cgroup.mountpoint"]; !ok {
|
||||
if currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.exec: cgroups unavailable, disabling")
|
||||
}
|
||||
delete(node.Attributes, execDriverAttr)
|
||||
return false, nil
|
||||
} else if syscall.Geteuid() != 0 {
|
||||
if currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.exec: must run as root user, disabling")
|
||||
}
|
||||
delete(node.Attributes, execDriverAttr)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if !currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.exec: exec driver is enabled")
|
||||
}
|
||||
node.Attributes[execDriverAttr] = "1"
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (d *ExecDriver) Periodic() (bool, time.Duration) {
|
||||
return true, 15 * time.Second
|
||||
}
|
||||
|
||||
12
client/driver/exec_default.go
Normal file
12
client/driver/exec_default.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
36
client/driver/exec_unix.go
Normal file
36
client/driver/exec_unix.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[execDriverAttr]
|
||||
|
||||
// Only enable if cgroups are available and we are root
|
||||
if _, ok := node.Attributes["unique.cgroup.mountpoint"]; !ok {
|
||||
if currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.exec: cgroups unavailable, disabling")
|
||||
}
|
||||
delete(node.Attributes, execDriverAttr)
|
||||
return false, nil
|
||||
} else if unix.Geteuid() != 0 {
|
||||
if currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.exec: must run as root user, disabling")
|
||||
}
|
||||
delete(node.Attributes, execDriverAttr)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if !currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.exec: exec driver is enabled")
|
||||
}
|
||||
node.Attributes[execDriverAttr] = "1"
|
||||
return true, nil
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/armon/circbuf"
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
|
||||
cstructs "github.com/hashicorp/nomad/client/driver/structs"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package executor
|
||||
|
||||
import (
|
||||
@@ -1,10 +1,8 @@
|
||||
// +build !linux
|
||||
// +build windows
|
||||
|
||||
package executor
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
)
|
||||
import "os/exec"
|
||||
|
||||
func (e *ExecScriptCheck) setChroot(cmd *exec.Cmd) {
|
||||
}
|
||||
@@ -338,8 +338,16 @@ func (e *UniversalExecutor) wait() {
|
||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||
exitCode = status.ExitStatus()
|
||||
if status.Signaled() {
|
||||
// bash(1) uses the lower 7 bits of a uint8
|
||||
// to indicate normal program failure (see
|
||||
// <sysexits.h>). If a process terminates due
|
||||
// to a signal, encode the signal number to
|
||||
// indicate which signal caused the process
|
||||
// to terminate. Mirror this exit code
|
||||
// encoding scheme.
|
||||
const exitSignalBase = 128
|
||||
signal = int(status.Signal())
|
||||
exitCode = 128 + signal
|
||||
exitCode = exitSignalBase + signal
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -574,7 +582,8 @@ func (e *UniversalExecutor) createCheck(check *structs.ServiceCheck, checkID str
|
||||
}, nil
|
||||
}
|
||||
|
||||
if check.Type == structs.ServiceCheckScript && e.ctx.Driver == "exec" {
|
||||
if check.Type == structs.ServiceCheckScript && (e.ctx.Driver == "exec" ||
|
||||
e.ctx.Driver == "raw_exec" || e.ctx.Driver == "java") {
|
||||
return &ExecScriptCheck{
|
||||
id: checkID,
|
||||
interval: check.Interval,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build !windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package executor
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build !windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package logging
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build !windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package logging
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build !windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package logging
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package driver
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// isolateCommand sets the setsid flag in exec.Cmd to true so that the process
|
||||
// becomes the process leader in a new session and doesn't receive signals that
|
||||
// are sent to the parent process.
|
||||
func isolateCommand(cmd *exec.Cmd) {
|
||||
if cmd.SysProcAttr == nil {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
}
|
||||
cmd.SysProcAttr.Setsid = true
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build !linux,!windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package driver
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package fingerprint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
client "github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
@@ -47,35 +45,6 @@ func NewCGroupFingerprint(logger *log.Logger) Fingerprint {
|
||||
return f
|
||||
}
|
||||
|
||||
// Fingerprint tries to find a valid cgroup moint point
|
||||
func (f *CGroupFingerprint) Fingerprint(cfg *client.Config, node *structs.Node) (bool, error) {
|
||||
mount, err := f.mountPointDetector.MountPoint()
|
||||
if err != nil {
|
||||
f.clearCGroupAttributes(node)
|
||||
return false, fmt.Errorf("Failed to discover cgroup mount point: %s", err)
|
||||
}
|
||||
|
||||
// Check if a cgroup mount point was found
|
||||
if mount == "" {
|
||||
// Clear any attributes from the previous fingerprint.
|
||||
f.clearCGroupAttributes(node)
|
||||
|
||||
if f.lastState == cgroupAvailable {
|
||||
f.logger.Printf("[INFO] fingerprint.cgroups: cgroups are unavailable")
|
||||
}
|
||||
f.lastState = cgroupUnavailable
|
||||
return true, nil
|
||||
}
|
||||
|
||||
node.Attributes["unique.cgroup.mountpoint"] = mount
|
||||
|
||||
if f.lastState == cgroupUnavailable {
|
||||
f.logger.Printf("[INFO] fingerprint.cgroups: cgroups are available")
|
||||
}
|
||||
f.lastState = cgroupAvailable
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// clearCGroupAttributes clears any node attributes related to cgroups that might
|
||||
// have been set in a previous fingerprint run.
|
||||
func (f *CGroupFingerprint) clearCGroupAttributes(n *structs.Node) {
|
||||
|
||||
18
client/fingerprint/cgroup_default.go
Normal file
18
client/fingerprint/cgroup_default.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// +build !linux
|
||||
|
||||
package fingerprint
|
||||
|
||||
import (
|
||||
client "github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
// FindCgroupMountpointDir returns an empty path on non-Linux systems
|
||||
func FindCgroupMountpointDir() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Fingerprint tries to find a valid cgroup moint point
|
||||
func (f *CGroupFingerprint) Fingerprint(cfg *client.Config, node *structs.Node) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
package fingerprint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
client "github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
)
|
||||
|
||||
@@ -22,3 +26,32 @@ func FindCgroupMountpointDir() (string, error) {
|
||||
}
|
||||
return mount, nil
|
||||
}
|
||||
|
||||
// Fingerprint tries to find a valid cgroup moint point
|
||||
func (f *CGroupFingerprint) Fingerprint(cfg *client.Config, node *structs.Node) (bool, error) {
|
||||
mount, err := f.mountPointDetector.MountPoint()
|
||||
if err != nil {
|
||||
f.clearCGroupAttributes(node)
|
||||
return false, fmt.Errorf("Failed to discover cgroup mount point: %s", err)
|
||||
}
|
||||
|
||||
// Check if a cgroup mount point was found
|
||||
if mount == "" {
|
||||
// Clear any attributes from the previous fingerprint.
|
||||
f.clearCGroupAttributes(node)
|
||||
|
||||
if f.lastState == cgroupAvailable {
|
||||
f.logger.Printf("[INFO] fingerprint.cgroups: cgroups are unavailable")
|
||||
}
|
||||
f.lastState = cgroupUnavailable
|
||||
return true, nil
|
||||
}
|
||||
|
||||
node.Attributes["unique.cgroup.mountpoint"] = mount
|
||||
|
||||
if f.lastState == cgroupUnavailable {
|
||||
f.logger.Printf("[INFO] fingerprint.cgroups: cgroups are available")
|
||||
}
|
||||
f.lastState = cgroupAvailable
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// +build !linux
|
||||
|
||||
package fingerprint
|
||||
|
||||
// FindCgroupMountpointDir returns an empty path on non-Linux systems
|
||||
func FindCgroupMountpointDir() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
@@ -48,10 +48,18 @@ func (f *CPUFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bo
|
||||
|
||||
if mhz > 0 {
|
||||
node.Attributes["cpu.frequency"] = fmt.Sprintf("%.6f", mhz)
|
||||
f.logger.Printf("[DEBUG] fingerprint.cpu: frequency: %02.1fMHz", mhz)
|
||||
}
|
||||
|
||||
if numCores <= 0 {
|
||||
const defaultCPUCoreCount = 1
|
||||
f.logger.Printf("[DEBUG] fingerprint.cpu: unable to find core count, defaulting to %d", defaultCPUCoreCount)
|
||||
numCores = defaultCPUCoreCount
|
||||
}
|
||||
|
||||
if numCores > 0 {
|
||||
node.Attributes["cpu.numcores"] = fmt.Sprintf("%d", numCores)
|
||||
f.logger.Printf("[DEBUG] fingerprint.cpu: core count: %d", numCores)
|
||||
}
|
||||
|
||||
if mhz > 0 && numCores > 0 {
|
||||
|
||||
@@ -96,7 +96,7 @@ func (f *EnvGCEFingerprint) Get(attribute string, recursive bool) (string, error
|
||||
|
||||
res, err := f.client.Do(req)
|
||||
if err != nil || res.StatusCode != http.StatusOK {
|
||||
f.logger.Printf("[WARN] fingerprint.env_gce: Could not read value for attribute %q", attribute)
|
||||
f.logger.Printf("[DEBUG] fingerprint.env_gce: Could not read value for attribute %q", attribute)
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,8 @@ package fingerprint
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
@@ -78,10 +73,11 @@ func (f *NetworkFingerprint) Fingerprint(cfg *config.Config, node *structs.Node)
|
||||
newNetwork.IP = ip
|
||||
newNetwork.CIDR = newNetwork.IP + "/32"
|
||||
|
||||
f.logger.Printf("[DEBUG] fingerprint.network: Detected interface %v with IP %v during fingerprinting", intf.Name, ip)
|
||||
f.logger.Printf("[DEBUG] fingerprint.network: Detected interface %v with IP %v during fingerprinting", intf.Name, ip)
|
||||
|
||||
if throughput := f.linkSpeed(intf.Name); throughput > 0 {
|
||||
newNetwork.MBits = throughput
|
||||
f.logger.Printf("[DEBUG] fingerprint.network: link speed for %v set to %v", intf.Name, newNetwork.MBits)
|
||||
} else {
|
||||
f.logger.Printf("[DEBUG] fingerprint.network: Unable to read link speed; setting to default %v", cfg.NetworkSpeed)
|
||||
newNetwork.MBits = cfg.NetworkSpeed
|
||||
@@ -97,74 +93,6 @@ func (f *NetworkFingerprint) Fingerprint(cfg *config.Config, node *structs.Node)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// linkSpeed returns link speed in Mb/s, or 0 when unable to determine it.
|
||||
func (f *NetworkFingerprint) linkSpeed(device string) int {
|
||||
// Use LookPath to find the ethtool in the systems $PATH
|
||||
// If it's not found or otherwise errors, LookPath returns and empty string
|
||||
// and an error we can ignore for our purposes
|
||||
ethtoolPath, _ := exec.LookPath("ethtool")
|
||||
if ethtoolPath != "" {
|
||||
if speed := f.linkSpeedEthtool(ethtoolPath, device); speed > 0 {
|
||||
return speed
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back on checking a system file for link speed.
|
||||
return f.linkSpeedSys(device)
|
||||
}
|
||||
|
||||
// linkSpeedSys parses link speed in Mb/s from /sys.
|
||||
func (f *NetworkFingerprint) linkSpeedSys(device string) int {
|
||||
path := fmt.Sprintf("/sys/class/net/%s/speed", device)
|
||||
|
||||
// Read contents of the device/speed file
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
f.logger.Printf("[WARN] fingerprint.network: Unable to read link speed from %s", path)
|
||||
return 0
|
||||
}
|
||||
|
||||
lines := strings.Split(string(content), "\n")
|
||||
mbs, err := strconv.Atoi(lines[0])
|
||||
if err != nil || mbs <= 0 {
|
||||
f.logger.Printf("[WARN] fingerprint.network: Unable to parse link speed from %s", path)
|
||||
return 0
|
||||
}
|
||||
|
||||
return mbs
|
||||
}
|
||||
|
||||
// linkSpeedEthtool determines link speed in Mb/s with 'ethtool'.
|
||||
func (f *NetworkFingerprint) linkSpeedEthtool(path, device string) int {
|
||||
outBytes, err := exec.Command(path, device).Output()
|
||||
if err != nil {
|
||||
f.logger.Printf("[WARN] fingerprint.network: Error calling ethtool (%s %s): %v", path, device, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
output := strings.TrimSpace(string(outBytes))
|
||||
re := regexp.MustCompile("Speed: [0-9]+[a-zA-Z]+/s")
|
||||
m := re.FindString(output)
|
||||
if m == "" {
|
||||
// no matches found, output may be in a different format
|
||||
f.logger.Printf("[WARN] fingerprint.network: Unable to parse Speed in output of '%s %s'", path, device)
|
||||
return 0
|
||||
}
|
||||
|
||||
// Split and trim the Mb/s unit from the string output
|
||||
args := strings.Split(m, ": ")
|
||||
raw := strings.TrimSuffix(args[1], "Mb/s")
|
||||
|
||||
// convert to Mb/s
|
||||
mbs, err := strconv.Atoi(raw)
|
||||
if err != nil || mbs <= 0 {
|
||||
f.logger.Printf("[WARN] fingerprint.network: Unable to parse Mb/s in output of '%s %s'", path, device)
|
||||
return 0
|
||||
}
|
||||
|
||||
return mbs
|
||||
}
|
||||
|
||||
// Gets the ipv4 addr for a network interface
|
||||
func (f *NetworkFingerprint) ipAddress(intf *net.Interface) (string, error) {
|
||||
var addrs []net.Addr
|
||||
|
||||
8
client/fingerprint/network_default.go
Normal file
8
client/fingerprint/network_default.go
Normal file
@@ -0,0 +1,8 @@
|
||||
// +build !linux
|
||||
|
||||
package fingerprint
|
||||
|
||||
// linkSpeed returns the default link speed
|
||||
func (f *NetworkFingerprint) linkSpeed(device string) int {
|
||||
return 0
|
||||
}
|
||||
78
client/fingerprint/network_linux.go
Normal file
78
client/fingerprint/network_linux.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package fingerprint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// linkSpeedSys parses link speed in Mb/s from /sys.
|
||||
func (f *NetworkFingerprint) linkSpeedSys(device string) int {
|
||||
path := fmt.Sprintf("/sys/class/net/%s/speed", device)
|
||||
|
||||
// Read contents of the device/speed file
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
f.logger.Printf("[DEBUG] fingerprint.network: Unable to read link speed from %s", path)
|
||||
return 0
|
||||
}
|
||||
|
||||
lines := strings.Split(string(content), "\n")
|
||||
mbs, err := strconv.Atoi(lines[0])
|
||||
if err != nil || mbs <= 0 {
|
||||
f.logger.Printf("[DEBUG] fingerprint.network: Unable to parse link speed from %s", path)
|
||||
return 0
|
||||
}
|
||||
|
||||
return mbs
|
||||
}
|
||||
|
||||
// linkSpeed returns link speed in Mb/s, or 0 when unable to determine it.
|
||||
func (f *NetworkFingerprint) linkSpeed(device string) int {
|
||||
// Use LookPath to find the ethtool in the systems $PATH
|
||||
// If it's not found or otherwise errors, LookPath returns and empty string
|
||||
// and an error we can ignore for our purposes
|
||||
ethtoolPath, _ := exec.LookPath("ethtool")
|
||||
if ethtoolPath != "" {
|
||||
if speed := f.linkSpeedEthtool(ethtoolPath, device); speed > 0 {
|
||||
return speed
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back on checking a system file for link speed.
|
||||
return f.linkSpeedSys(device)
|
||||
}
|
||||
|
||||
// linkSpeedEthtool determines link speed in Mb/s with 'ethtool'.
|
||||
func (f *NetworkFingerprint) linkSpeedEthtool(path, device string) int {
|
||||
outBytes, err := exec.Command(path, device).Output()
|
||||
if err != nil {
|
||||
f.logger.Printf("[WARN] fingerprint.network: Error calling ethtool (%s %s): %v", path, device, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
output := strings.TrimSpace(string(outBytes))
|
||||
re := regexp.MustCompile("Speed: [0-9]+[a-zA-Z]+/s")
|
||||
m := re.FindString(output)
|
||||
if m == "" {
|
||||
// no matches found, output may be in a different format
|
||||
f.logger.Printf("[WARN] fingerprint.network: Unable to parse Speed in output of '%s %s'", path, device)
|
||||
return 0
|
||||
}
|
||||
|
||||
// Split and trim the Mb/s unit from the string output
|
||||
args := strings.Split(m, ": ")
|
||||
raw := strings.TrimSuffix(args[1], "Mb/s")
|
||||
|
||||
// convert to Mb/s
|
||||
mbs, err := strconv.Atoi(raw)
|
||||
if err != nil || mbs <= 0 {
|
||||
f.logger.Printf("[WARN] fingerprint.network: Unable to parse Mb/s in output of '%s %s'", path, device)
|
||||
return 0
|
||||
}
|
||||
|
||||
return mbs
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package fingerprint
|
||||
|
||||
|
||||
@@ -184,6 +184,9 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque
|
||||
var buf []byte
|
||||
if prettyPrint {
|
||||
buf, err = json.MarshalIndent(obj, "", " ")
|
||||
if err == nil {
|
||||
buf = append(buf, "\n"...)
|
||||
}
|
||||
} else {
|
||||
buf, err = json.Marshal(obj)
|
||||
}
|
||||
|
||||
@@ -145,14 +145,18 @@ func TestContentTypeIsJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPrettyPrint(t *testing.T) {
|
||||
testPrettyPrint("pretty=1", t)
|
||||
testPrettyPrint("pretty=1", true, t)
|
||||
}
|
||||
|
||||
func TestPrettyPrintOff(t *testing.T) {
|
||||
testPrettyPrint("pretty=0", false, t)
|
||||
}
|
||||
|
||||
func TestPrettyPrintBare(t *testing.T) {
|
||||
testPrettyPrint("pretty", t)
|
||||
testPrettyPrint("pretty", true, t)
|
||||
}
|
||||
|
||||
func testPrettyPrint(pretty string, t *testing.T) {
|
||||
func testPrettyPrint(pretty string, prettyFmt bool, t *testing.T) {
|
||||
s := makeHTTPServer(t, nil)
|
||||
defer s.Cleanup()
|
||||
|
||||
@@ -168,6 +172,9 @@ func testPrettyPrint(pretty string, t *testing.T) {
|
||||
s.Server.wrap(handler)(resp, req)
|
||||
|
||||
expected, _ := json.MarshalIndent(r, "", " ")
|
||||
if prettyFmt {
|
||||
expected = append(expected, "\n"...)
|
||||
}
|
||||
actual, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
||||
@@ -203,6 +203,7 @@ func (idx *NetworkIndex) AssignNetwork(ask *NetworkResource) (out *NetworkResour
|
||||
offer := &NetworkResource{
|
||||
Device: n.Device,
|
||||
IP: ipStr,
|
||||
MBits: ask.MBits,
|
||||
ReservedPorts: ask.ReservedPorts,
|
||||
DynamicPorts: ask.DynamicPorts,
|
||||
}
|
||||
|
||||
@@ -302,19 +302,59 @@ func tasksUpdated(a, b *structs.TaskGroup) bool {
|
||||
if !reflect.DeepEqual(at.Env, bt.Env) {
|
||||
return true
|
||||
}
|
||||
if !reflect.DeepEqual(at.Resources, bt.Resources) {
|
||||
return true
|
||||
}
|
||||
if !reflect.DeepEqual(at.Meta, bt.Meta) {
|
||||
return true
|
||||
}
|
||||
if !reflect.DeepEqual(at.Artifacts, bt.Artifacts) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Inspect the network to see if the dynamic ports are different
|
||||
if len(at.Resources.Networks) != len(bt.Resources.Networks) {
|
||||
return true
|
||||
}
|
||||
for idx := range at.Resources.Networks {
|
||||
an := at.Resources.Networks[idx]
|
||||
bn := bt.Resources.Networks[idx]
|
||||
|
||||
if an.MBits != bn.MBits {
|
||||
return true
|
||||
}
|
||||
|
||||
aPorts, bPorts := networkPortMap(an), networkPortMap(bn)
|
||||
if !reflect.DeepEqual(aPorts, bPorts) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Inspect the non-network resources
|
||||
if ar, br := at.Resources, bt.Resources; ar.CPU != br.CPU {
|
||||
return true
|
||||
} else if ar.MemoryMB != br.MemoryMB {
|
||||
return true
|
||||
} else if ar.DiskMB != br.DiskMB {
|
||||
return true
|
||||
} else if ar.IOPS != br.IOPS {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// networkPortMap takes a network resource and returns a map of port labels to
|
||||
// values. The value for dynamic ports is disregarded even if it is set. This
|
||||
// makes this function suitable for comparing two network resources for changes.
|
||||
func networkPortMap(n *structs.NetworkResource) map[string]int {
|
||||
m := make(map[string]int, len(n.DynamicPorts)+len(n.ReservedPorts))
|
||||
for _, p := range n.ReservedPorts {
|
||||
m[p.Label] = p.Value
|
||||
}
|
||||
for _, p := range n.DynamicPorts {
|
||||
m[p.Label] = -1
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// setStatus is used to update the status of the evaluation
|
||||
func setStatus(logger *log.Logger, planner Planner, eval, nextEval *structs.Evaluation, status, desc string) error {
|
||||
logger.Printf("[DEBUG] sched: %#v: setting status to %s", eval, status)
|
||||
|
||||
@@ -404,6 +404,24 @@ func TestTasksUpdated(t *testing.T) {
|
||||
if !tasksUpdated(j1.TaskGroups[0], j11.TaskGroups[0]) {
|
||||
t.Fatalf("bad")
|
||||
}
|
||||
|
||||
j12 := mock.Job()
|
||||
j12.TaskGroups[0].Tasks[0].Resources.Networks[0].MBits = 100
|
||||
if !tasksUpdated(j1.TaskGroups[0], j12.TaskGroups[0]) {
|
||||
t.Fatalf("bad")
|
||||
}
|
||||
|
||||
j13 := mock.Job()
|
||||
j13.TaskGroups[0].Tasks[0].Resources.Networks[0].DynamicPorts[0].Label = "foobar"
|
||||
if !tasksUpdated(j1.TaskGroups[0], j13.TaskGroups[0]) {
|
||||
t.Fatalf("bad")
|
||||
}
|
||||
|
||||
j14 := mock.Job()
|
||||
j14.TaskGroups[0].Tasks[0].Resources.Networks[0].ReservedPorts = []structs.Port{{Label: "foo", Value: 1312}}
|
||||
if !tasksUpdated(j1.TaskGroups[0], j14.TaskGroups[0]) {
|
||||
t.Fatalf("bad")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvictAndPlace_LimitLessThanAllocs(t *testing.T) {
|
||||
|
||||
@@ -17,7 +17,7 @@ GIT_DIRTY="$(test -n "`git status --porcelain`" && echo "+CHANGES" || true)"
|
||||
|
||||
# Determine the arch/os combos we're building for
|
||||
XC_ARCH=${XC_ARCH:-"386 amd64 arm"}
|
||||
XC_OS=${XC_OS:-linux darwin windows freebsd openbsd}
|
||||
XC_OS=${XC_OS:-darwin dragonfly freebsd linux netbsd openbsd solaris windows}
|
||||
|
||||
# Delete the old dir
|
||||
echo "==> Removing old directory..."
|
||||
@@ -35,8 +35,11 @@ fi
|
||||
echo "==> Building..."
|
||||
gox \
|
||||
-os="${XC_OS}" \
|
||||
-os="!dragonfly" \
|
||||
-os="!freebsd" \
|
||||
-os="!netbsd" \
|
||||
-os="!openbsd" \
|
||||
-os="!solaris" \
|
||||
-arch="${XC_ARCH}" \
|
||||
-osarch="!linux/arm !darwin/386" \
|
||||
-ldflags "-X main.GitCommit='${GIT_COMMIT}${GIT_DIRTY}'" \
|
||||
|
||||
@@ -2,14 +2,28 @@
|
||||
|
||||
set -ex
|
||||
|
||||
RKT_VERSION="v1.2.0"
|
||||
RKT_VERSION="v1.5.1"
|
||||
RKT_SHA512="8163ca59fc8c44c9c2997431d16274d81d2e82ff2956c860607f4c111de744b78cdce716f8afbacf7173e0cdce25deac73ec95a30a8849bbf58d35faeb84e398"
|
||||
DEST_DIR="/usr/local/bin"
|
||||
|
||||
sudo mkdir -p /etc/rkt/net.d
|
||||
echo '{"name": "default", "type": "ptp", "ipMasq": false, "ipam": { "type": "host-local", "subnet": "172.16.28.0/24", "routes": [ { "dst": "0.0.0.0/0" } ] } }' | sudo tee -a /etc/rkt/net.d/99-network.conf
|
||||
|
||||
wget https://github.com/coreos/rkt/releases/download/$RKT_VERSION/rkt-$RKT_VERSION.tar.gz
|
||||
tar xzvf rkt-$RKT_VERSION.tar.gz
|
||||
if [ ! -d "rkt-${RKT_VERSION}" ]; then
|
||||
printf "rkt-%s/ doesn't exist\n" "${RKT_VERSION}"
|
||||
if [ ! -f "rkt-${RKT_VERSION}.tar.gz" ]; then
|
||||
printf "Fetching rkt-%s.tar.gz\n" "${RKT_VERSION}"
|
||||
wget https://github.com/coreos/rkt/releases/download/$RKT_VERSION/rkt-$RKT_VERSION.tar.gz
|
||||
expected_version=$(printf 'SHA512(rkt-%s.tar.gz)= %s' "${RKT_VERSION}" "${RKT_SHA512}")
|
||||
actual_version=$(openssl sha512 rkt-${RKT_VERSION}.tar.gz)
|
||||
if [ "${expected_version}" != "${actual_version}" ]; then
|
||||
printf "SHA512 of rkt-%s failed\n" "${RKT_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
tar xzvf rkt-$RKT_VERSION.tar.gz
|
||||
fi
|
||||
fi
|
||||
|
||||
sudo cp rkt-$RKT_VERSION/rkt $DEST_DIR
|
||||
sudo cp rkt-$RKT_VERSION/*.aci $DEST_DIR
|
||||
|
||||
|
||||
13
vendor/golang.org/x/sys/windows/asm_windows_386.s
generated
vendored
Normal file
13
vendor/golang.org/x/sys/windows/asm_windows_386.s
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//
|
||||
// System calls for 386, Windows are implemented in runtime/syscall_windows.goc
|
||||
//
|
||||
|
||||
TEXT ·getprocaddress(SB), 7, $0-8
|
||||
JMP syscall·getprocaddress(SB)
|
||||
|
||||
TEXT ·loadlibrary(SB), 7, $0-4
|
||||
JMP syscall·loadlibrary(SB)
|
||||
13
vendor/golang.org/x/sys/windows/asm_windows_amd64.s
generated
vendored
Normal file
13
vendor/golang.org/x/sys/windows/asm_windows_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//
|
||||
// System calls for amd64, Windows are implemented in runtime/syscall_windows.goc
|
||||
//
|
||||
|
||||
TEXT ·getprocaddress(SB), 7, $0-32
|
||||
JMP syscall·getprocaddress(SB)
|
||||
|
||||
TEXT ·loadlibrary(SB), 7, $0-8
|
||||
JMP syscall·loadlibrary(SB)
|
||||
374
vendor/golang.org/x/sys/windows/dll_windows.go
generated
vendored
Normal file
374
vendor/golang.org/x/sys/windows/dll_windows.go
generated
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// DLLError describes reasons for DLL load failures.
|
||||
type DLLError struct {
|
||||
Err error
|
||||
ObjName string
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e *DLLError) Error() string { return e.Msg }
|
||||
|
||||
// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file.
|
||||
func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno)
|
||||
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno)
|
||||
|
||||
// A DLL implements access to a single DLL.
|
||||
type DLL struct {
|
||||
Name string
|
||||
Handle Handle
|
||||
}
|
||||
|
||||
// LoadDLL loads DLL file into memory.
|
||||
//
|
||||
// Warning: using LoadDLL without an absolute path name is subject to
|
||||
// DLL preloading attacks. To safely load a system DLL, use LazyDLL
|
||||
// with System set to true, or use LoadLibraryEx directly.
|
||||
func LoadDLL(name string) (dll *DLL, err error) {
|
||||
namep, err := UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, e := loadlibrary(namep)
|
||||
if e != 0 {
|
||||
return nil, &DLLError{
|
||||
Err: e,
|
||||
ObjName: name,
|
||||
Msg: "Failed to load " + name + ": " + e.Error(),
|
||||
}
|
||||
}
|
||||
d := &DLL{
|
||||
Name: name,
|
||||
Handle: Handle(h),
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// MustLoadDLL is like LoadDLL but panics if load operation failes.
|
||||
func MustLoadDLL(name string) *DLL {
|
||||
d, e := LoadDLL(name)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// FindProc searches DLL d for procedure named name and returns *Proc
|
||||
// if found. It returns an error if search fails.
|
||||
func (d *DLL) FindProc(name string) (proc *Proc, err error) {
|
||||
namep, err := BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a, e := getprocaddress(uintptr(d.Handle), namep)
|
||||
if e != 0 {
|
||||
return nil, &DLLError{
|
||||
Err: e,
|
||||
ObjName: name,
|
||||
Msg: "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(),
|
||||
}
|
||||
}
|
||||
p := &Proc{
|
||||
Dll: d,
|
||||
Name: name,
|
||||
addr: a,
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// MustFindProc is like FindProc but panics if search fails.
|
||||
func (d *DLL) MustFindProc(name string) *Proc {
|
||||
p, e := d.FindProc(name)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Release unloads DLL d from memory.
|
||||
func (d *DLL) Release() (err error) {
|
||||
return FreeLibrary(d.Handle)
|
||||
}
|
||||
|
||||
// A Proc implements access to a procedure inside a DLL.
|
||||
type Proc struct {
|
||||
Dll *DLL
|
||||
Name string
|
||||
addr uintptr
|
||||
}
|
||||
|
||||
// Addr returns the address of the procedure represented by p.
|
||||
// The return value can be passed to Syscall to run the procedure.
|
||||
func (p *Proc) Addr() uintptr {
|
||||
return p.addr
|
||||
}
|
||||
|
||||
// Call executes procedure p with arguments a. It will panic, if more then 15 arguments
|
||||
// are supplied.
|
||||
//
|
||||
// The returned error is always non-nil, constructed from the result of GetLastError.
|
||||
// Callers must inspect the primary return value to decide whether an error occurred
|
||||
// (according to the semantics of the specific function being called) before consulting
|
||||
// the error. The error will be guaranteed to contain windows.Errno.
|
||||
func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
switch len(a) {
|
||||
case 0:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0)
|
||||
case 1:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0)
|
||||
case 2:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0)
|
||||
case 3:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2])
|
||||
case 4:
|
||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
|
||||
case 5:
|
||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
|
||||
case 6:
|
||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
|
||||
case 7:
|
||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
|
||||
case 8:
|
||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
|
||||
case 9:
|
||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
|
||||
case 10:
|
||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
|
||||
case 11:
|
||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
|
||||
case 12:
|
||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
|
||||
case 13:
|
||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
|
||||
case 14:
|
||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
|
||||
case 15:
|
||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
|
||||
default:
|
||||
panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// A LazyDLL implements access to a single DLL.
|
||||
// It will delay the load of the DLL until the first
|
||||
// call to its Handle method or to one of its
|
||||
// LazyProc's Addr method.
|
||||
type LazyDLL struct {
|
||||
Name string
|
||||
|
||||
// System determines whether the DLL must be loaded from the
|
||||
// Windows System directory, bypassing the normal DLL search
|
||||
// path.
|
||||
System bool
|
||||
|
||||
mu sync.Mutex
|
||||
dll *DLL // non nil once DLL is loaded
|
||||
}
|
||||
|
||||
// Load loads DLL file d.Name into memory. It returns an error if fails.
|
||||
// Load will not try to load DLL, if it is already loaded into memory.
|
||||
func (d *LazyDLL) Load() error {
|
||||
// Non-racy version of:
|
||||
// if d.dll != nil {
|
||||
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) != nil {
|
||||
return nil
|
||||
}
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
if d.dll != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// kernel32.dll is special, since it's where LoadLibraryEx comes from.
|
||||
// The kernel already special-cases its name, so it's always
|
||||
// loaded from system32.
|
||||
var dll *DLL
|
||||
var err error
|
||||
if d.Name == "kernel32.dll" {
|
||||
dll, err = LoadDLL(d.Name)
|
||||
} else {
|
||||
dll, err = loadLibraryEx(d.Name, d.System)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Non-racy version of:
|
||||
// d.dll = dll
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
|
||||
return nil
|
||||
}
|
||||
|
||||
// mustLoad is like Load but panics if search fails.
|
||||
func (d *LazyDLL) mustLoad() {
|
||||
e := d.Load()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle returns d's module handle.
|
||||
func (d *LazyDLL) Handle() uintptr {
|
||||
d.mustLoad()
|
||||
return uintptr(d.dll.Handle)
|
||||
}
|
||||
|
||||
// NewProc returns a LazyProc for accessing the named procedure in the DLL d.
|
||||
func (d *LazyDLL) NewProc(name string) *LazyProc {
|
||||
return &LazyProc{l: d, Name: name}
|
||||
}
|
||||
|
||||
// NewLazyDLL creates new LazyDLL associated with DLL file.
|
||||
func NewLazyDLL(name string) *LazyDLL {
|
||||
return &LazyDLL{Name: name}
|
||||
}
|
||||
|
||||
// NewLazySystemDLL is like NewLazyDLL, but will only
|
||||
// search Windows System directory for the DLL if name is
|
||||
// a base name (like "advapi32.dll").
|
||||
func NewLazySystemDLL(name string) *LazyDLL {
|
||||
return &LazyDLL{Name: name, System: true}
|
||||
}
|
||||
|
||||
// A LazyProc implements access to a procedure inside a LazyDLL.
|
||||
// It delays the lookup until the Addr method is called.
|
||||
type LazyProc struct {
|
||||
Name string
|
||||
|
||||
mu sync.Mutex
|
||||
l *LazyDLL
|
||||
proc *Proc
|
||||
}
|
||||
|
||||
// Find searches DLL for procedure named p.Name. It returns
|
||||
// an error if search fails. Find will not search procedure,
|
||||
// if it is already found and loaded into memory.
|
||||
func (p *LazyProc) Find() error {
|
||||
// Non-racy version of:
|
||||
// if p.proc == nil {
|
||||
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
if p.proc == nil {
|
||||
e := p.l.Load()
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
proc, e := p.l.dll.FindProc(p.Name)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
// Non-racy version of:
|
||||
// p.proc = proc
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mustFind is like Find but panics if search fails.
|
||||
func (p *LazyProc) mustFind() {
|
||||
e := p.Find()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Addr returns the address of the procedure represented by p.
|
||||
// The return value can be passed to Syscall to run the procedure.
|
||||
func (p *LazyProc) Addr() uintptr {
|
||||
p.mustFind()
|
||||
return p.proc.Addr()
|
||||
}
|
||||
|
||||
// Call executes procedure p with arguments a. It will panic, if more then 15 arguments
|
||||
// are supplied.
|
||||
//
|
||||
// The returned error is always non-nil, constructed from the result of GetLastError.
|
||||
// Callers must inspect the primary return value to decide whether an error occurred
|
||||
// (according to the semantics of the specific function being called) before consulting
|
||||
// the error. The error will be guaranteed to contain windows.Errno.
|
||||
func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
p.mustFind()
|
||||
return p.proc.Call(a...)
|
||||
}
|
||||
|
||||
var canDoSearchSystem32Once struct {
|
||||
sync.Once
|
||||
v bool
|
||||
}
|
||||
|
||||
func initCanDoSearchSystem32() {
|
||||
// https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says:
|
||||
// "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows
|
||||
// Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on
|
||||
// systems that have KB2533623 installed. To determine whether the
|
||||
// flags are available, use GetProcAddress to get the address of the
|
||||
// AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories
|
||||
// function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_*
|
||||
// flags can be used with LoadLibraryEx."
|
||||
canDoSearchSystem32Once.v = (modkernel32.NewProc("AddDllDirectory").Find() == nil)
|
||||
}
|
||||
|
||||
func canDoSearchSystem32() bool {
|
||||
canDoSearchSystem32Once.Do(initCanDoSearchSystem32)
|
||||
return canDoSearchSystem32Once.v
|
||||
}
|
||||
|
||||
func isBaseName(name string) bool {
|
||||
for _, c := range name {
|
||||
if c == ':' || c == '/' || c == '\\' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// loadLibraryEx wraps the Windows LoadLibraryEx function.
|
||||
//
|
||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx
|
||||
//
|
||||
// If name is not an absolute path, LoadLibraryEx searches for the DLL
|
||||
// in a variety of automatic locations unless constrained by flags.
|
||||
// See: https://msdn.microsoft.com/en-us/library/ff919712%28VS.85%29.aspx
|
||||
func loadLibraryEx(name string, system bool) (*DLL, error) {
|
||||
loadDLL := name
|
||||
var flags uintptr
|
||||
if system {
|
||||
if canDoSearchSystem32() {
|
||||
const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
|
||||
flags = LOAD_LIBRARY_SEARCH_SYSTEM32
|
||||
} else if isBaseName(name) {
|
||||
// WindowsXP or unpatched Windows machine
|
||||
// trying to load "foo.dll" out of the system
|
||||
// folder, but LoadLibraryEx doesn't support
|
||||
// that yet on their system, so emulate it.
|
||||
windir, _ := Getenv("WINDIR") // old var; apparently works on XP
|
||||
if windir == "" {
|
||||
return nil, errString("%WINDIR% not defined")
|
||||
}
|
||||
loadDLL = windir + "\\System32\\" + name
|
||||
}
|
||||
}
|
||||
h, err := LoadLibraryEx(loadDLL, 0, flags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &DLL{Name: name, Handle: h}, nil
|
||||
}
|
||||
|
||||
type errString string
|
||||
|
||||
func (s errString) Error() string { return string(s) }
|
||||
15
vendor/golang.org/x/sys/windows/env_unset.go
generated
vendored
Normal file
15
vendor/golang.org/x/sys/windows/env_unset.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
// +build go1.4
|
||||
|
||||
package windows
|
||||
|
||||
import "syscall"
|
||||
|
||||
func Unsetenv(key string) error {
|
||||
// This was added in Go 1.4.
|
||||
return syscall.Unsetenv(key)
|
||||
}
|
||||
25
vendor/golang.org/x/sys/windows/env_windows.go
generated
vendored
Normal file
25
vendor/golang.org/x/sys/windows/env_windows.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Windows environment variables.
|
||||
|
||||
package windows
|
||||
|
||||
import "syscall"
|
||||
|
||||
func Getenv(key string) (value string, found bool) {
|
||||
return syscall.Getenv(key)
|
||||
}
|
||||
|
||||
func Setenv(key, value string) error {
|
||||
return syscall.Setenv(key, value)
|
||||
}
|
||||
|
||||
func Clearenv() {
|
||||
syscall.Clearenv()
|
||||
}
|
||||
|
||||
func Environ() []string {
|
||||
return syscall.Environ()
|
||||
}
|
||||
20
vendor/golang.org/x/sys/windows/eventlog.go
generated
vendored
Normal file
20
vendor/golang.org/x/sys/windows/eventlog.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
const (
|
||||
EVENTLOG_SUCCESS = 0
|
||||
EVENTLOG_ERROR_TYPE = 1
|
||||
EVENTLOG_WARNING_TYPE = 2
|
||||
EVENTLOG_INFORMATION_TYPE = 4
|
||||
EVENTLOG_AUDIT_SUCCESS = 8
|
||||
EVENTLOG_AUDIT_FAILURE = 16
|
||||
)
|
||||
|
||||
//sys RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) [failretval==0] = advapi32.RegisterEventSourceW
|
||||
//sys DeregisterEventSource(handle Handle) (err error) = advapi32.DeregisterEventSource
|
||||
//sys ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) = advapi32.ReportEventW
|
||||
97
vendor/golang.org/x/sys/windows/exec_windows.go
generated
vendored
Normal file
97
vendor/golang.org/x/sys/windows/exec_windows.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Fork, exec, wait, etc.
|
||||
|
||||
package windows
|
||||
|
||||
// EscapeArg rewrites command line argument s as prescribed
|
||||
// in http://msdn.microsoft.com/en-us/library/ms880421.
|
||||
// This function returns "" (2 double quotes) if s is empty.
|
||||
// Alternatively, these transformations are done:
|
||||
// - every back slash (\) is doubled, but only if immediately
|
||||
// followed by double quote (");
|
||||
// - every double quote (") is escaped by back slash (\);
|
||||
// - finally, s is wrapped with double quotes (arg -> "arg"),
|
||||
// but only if there is space or tab inside s.
|
||||
func EscapeArg(s string) string {
|
||||
if len(s) == 0 {
|
||||
return "\"\""
|
||||
}
|
||||
n := len(s)
|
||||
hasSpace := false
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '"', '\\':
|
||||
n++
|
||||
case ' ', '\t':
|
||||
hasSpace = true
|
||||
}
|
||||
}
|
||||
if hasSpace {
|
||||
n += 2
|
||||
}
|
||||
if n == len(s) {
|
||||
return s
|
||||
}
|
||||
|
||||
qs := make([]byte, n)
|
||||
j := 0
|
||||
if hasSpace {
|
||||
qs[j] = '"'
|
||||
j++
|
||||
}
|
||||
slashes := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
default:
|
||||
slashes = 0
|
||||
qs[j] = s[i]
|
||||
case '\\':
|
||||
slashes++
|
||||
qs[j] = s[i]
|
||||
case '"':
|
||||
for ; slashes > 0; slashes-- {
|
||||
qs[j] = '\\'
|
||||
j++
|
||||
}
|
||||
qs[j] = '\\'
|
||||
j++
|
||||
qs[j] = s[i]
|
||||
}
|
||||
j++
|
||||
}
|
||||
if hasSpace {
|
||||
for ; slashes > 0; slashes-- {
|
||||
qs[j] = '\\'
|
||||
j++
|
||||
}
|
||||
qs[j] = '"'
|
||||
j++
|
||||
}
|
||||
return string(qs[:j])
|
||||
}
|
||||
|
||||
func CloseOnExec(fd Handle) {
|
||||
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
|
||||
}
|
||||
|
||||
// FullPath retrieves the full path of the specified file.
|
||||
func FullPath(name string) (path string, err error) {
|
||||
p, err := UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
n := uint32(100)
|
||||
for {
|
||||
buf := make([]uint16, n)
|
||||
n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if n <= uint32(len(buf)) {
|
||||
return UTF16ToString(buf[:n]), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
30
vendor/golang.org/x/sys/windows/race.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/windows/race.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows,race
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const raceenabled = true
|
||||
|
||||
func raceAcquire(addr unsafe.Pointer) {
|
||||
runtime.RaceAcquire(addr)
|
||||
}
|
||||
|
||||
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||
runtime.RaceReleaseMerge(addr)
|
||||
}
|
||||
|
||||
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||
runtime.RaceReadRange(addr, len)
|
||||
}
|
||||
|
||||
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||
runtime.RaceWriteRange(addr, len)
|
||||
}
|
||||
25
vendor/golang.org/x/sys/windows/race0.go
generated
vendored
Normal file
25
vendor/golang.org/x/sys/windows/race0.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows,!race
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const raceenabled = false
|
||||
|
||||
func raceAcquire(addr unsafe.Pointer) {
|
||||
}
|
||||
|
||||
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||
}
|
||||
|
||||
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||
}
|
||||
|
||||
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||
}
|
||||
435
vendor/golang.org/x/sys/windows/security_windows.go
generated
vendored
Normal file
435
vendor/golang.org/x/sys/windows/security_windows.go
generated
vendored
Normal file
@@ -0,0 +1,435 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
STANDARD_RIGHTS_REQUIRED = 0xf0000
|
||||
STANDARD_RIGHTS_READ = 0x20000
|
||||
STANDARD_RIGHTS_WRITE = 0x20000
|
||||
STANDARD_RIGHTS_EXECUTE = 0x20000
|
||||
STANDARD_RIGHTS_ALL = 0x1F0000
|
||||
)
|
||||
|
||||
const (
|
||||
NameUnknown = 0
|
||||
NameFullyQualifiedDN = 1
|
||||
NameSamCompatible = 2
|
||||
NameDisplay = 3
|
||||
NameUniqueId = 6
|
||||
NameCanonical = 7
|
||||
NameUserPrincipal = 8
|
||||
NameCanonicalEx = 9
|
||||
NameServicePrincipal = 10
|
||||
NameDnsDomain = 12
|
||||
)
|
||||
|
||||
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
|
||||
// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
|
||||
//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
|
||||
//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
|
||||
|
||||
// TranslateAccountName converts a directory service
|
||||
// object name from one format to another.
|
||||
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
|
||||
u, e := UTF16PtrFromString(username)
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
n := uint32(50)
|
||||
for {
|
||||
b := make([]uint16, n)
|
||||
e = TranslateName(u, from, to, &b[0], &n)
|
||||
if e == nil {
|
||||
return UTF16ToString(b[:n]), nil
|
||||
}
|
||||
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||
return "", e
|
||||
}
|
||||
if n <= uint32(len(b)) {
|
||||
return "", e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// do not reorder
|
||||
NetSetupUnknownStatus = iota
|
||||
NetSetupUnjoined
|
||||
NetSetupWorkgroupName
|
||||
NetSetupDomainName
|
||||
)
|
||||
|
||||
type UserInfo10 struct {
|
||||
Name *uint16
|
||||
Comment *uint16
|
||||
UsrComment *uint16
|
||||
FullName *uint16
|
||||
}
|
||||
|
||||
//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
|
||||
//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
|
||||
//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
|
||||
|
||||
const (
|
||||
// do not reorder
|
||||
SidTypeUser = 1 + iota
|
||||
SidTypeGroup
|
||||
SidTypeDomain
|
||||
SidTypeAlias
|
||||
SidTypeWellKnownGroup
|
||||
SidTypeDeletedAccount
|
||||
SidTypeInvalid
|
||||
SidTypeUnknown
|
||||
SidTypeComputer
|
||||
SidTypeLabel
|
||||
)
|
||||
|
||||
type SidIdentifierAuthority struct {
|
||||
Value [6]byte
|
||||
}
|
||||
|
||||
var (
|
||||
SECURITY_NULL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
|
||||
SECURITY_WORLD_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
|
||||
SECURITY_LOCAL_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
|
||||
SECURITY_CREATOR_SID_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
|
||||
SECURITY_NON_UNIQUE_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
|
||||
SECURITY_NT_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
|
||||
SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
|
||||
)
|
||||
|
||||
const (
|
||||
SECURITY_NULL_RID = 0
|
||||
SECURITY_WORLD_RID = 0
|
||||
SECURITY_LOCAL_RID = 0
|
||||
SECURITY_CREATOR_OWNER_RID = 0
|
||||
SECURITY_CREATOR_GROUP_RID = 1
|
||||
SECURITY_DIALUP_RID = 1
|
||||
SECURITY_NETWORK_RID = 2
|
||||
SECURITY_BATCH_RID = 3
|
||||
SECURITY_INTERACTIVE_RID = 4
|
||||
SECURITY_LOGON_IDS_RID = 5
|
||||
SECURITY_SERVICE_RID = 6
|
||||
SECURITY_LOCAL_SYSTEM_RID = 18
|
||||
SECURITY_BUILTIN_DOMAIN_RID = 32
|
||||
SECURITY_PRINCIPAL_SELF_RID = 10
|
||||
SECURITY_CREATOR_OWNER_SERVER_RID = 0x2
|
||||
SECURITY_CREATOR_GROUP_SERVER_RID = 0x3
|
||||
SECURITY_LOGON_IDS_RID_COUNT = 0x3
|
||||
SECURITY_ANONYMOUS_LOGON_RID = 0x7
|
||||
SECURITY_PROXY_RID = 0x8
|
||||
SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
|
||||
SECURITY_SERVER_LOGON_RID = SECURITY_ENTERPRISE_CONTROLLERS_RID
|
||||
SECURITY_AUTHENTICATED_USER_RID = 0xb
|
||||
SECURITY_RESTRICTED_CODE_RID = 0xc
|
||||
SECURITY_NT_NON_UNIQUE_RID = 0x15
|
||||
)
|
||||
|
||||
//sys LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
|
||||
//sys LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
|
||||
//sys ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
||||
//sys ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
|
||||
//sys GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
|
||||
//sys CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
|
||||
//sys AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
|
||||
//sys FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
|
||||
//sys EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
|
||||
|
||||
// The security identifier (SID) structure is a variable-length
|
||||
// structure used to uniquely identify users or groups.
|
||||
type SID struct{}
|
||||
|
||||
// StringToSid converts a string-format security identifier
|
||||
// sid into a valid, functional sid.
|
||||
func StringToSid(s string) (*SID, error) {
|
||||
var sid *SID
|
||||
p, e := UTF16PtrFromString(s)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
e = ConvertStringSidToSid(p, &sid)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
defer LocalFree((Handle)(unsafe.Pointer(sid)))
|
||||
return sid.Copy()
|
||||
}
|
||||
|
||||
// LookupSID retrieves a security identifier sid for the account
|
||||
// and the name of the domain on which the account was found.
|
||||
// System specify target computer to search.
|
||||
func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
|
||||
if len(account) == 0 {
|
||||
return nil, "", 0, syscall.EINVAL
|
||||
}
|
||||
acc, e := UTF16PtrFromString(account)
|
||||
if e != nil {
|
||||
return nil, "", 0, e
|
||||
}
|
||||
var sys *uint16
|
||||
if len(system) > 0 {
|
||||
sys, e = UTF16PtrFromString(system)
|
||||
if e != nil {
|
||||
return nil, "", 0, e
|
||||
}
|
||||
}
|
||||
n := uint32(50)
|
||||
dn := uint32(50)
|
||||
for {
|
||||
b := make([]byte, n)
|
||||
db := make([]uint16, dn)
|
||||
sid = (*SID)(unsafe.Pointer(&b[0]))
|
||||
e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
|
||||
if e == nil {
|
||||
return sid, UTF16ToString(db), accType, nil
|
||||
}
|
||||
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||
return nil, "", 0, e
|
||||
}
|
||||
if n <= uint32(len(b)) {
|
||||
return nil, "", 0, e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// String converts sid to a string format
|
||||
// suitable for display, storage, or transmission.
|
||||
func (sid *SID) String() (string, error) {
|
||||
var s *uint16
|
||||
e := ConvertSidToStringSid(sid, &s)
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
defer LocalFree((Handle)(unsafe.Pointer(s)))
|
||||
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
|
||||
}
|
||||
|
||||
// Len returns the length, in bytes, of a valid security identifier sid.
|
||||
func (sid *SID) Len() int {
|
||||
return int(GetLengthSid(sid))
|
||||
}
|
||||
|
||||
// Copy creates a duplicate of security identifier sid.
|
||||
func (sid *SID) Copy() (*SID, error) {
|
||||
b := make([]byte, sid.Len())
|
||||
sid2 := (*SID)(unsafe.Pointer(&b[0]))
|
||||
e := CopySid(uint32(len(b)), sid2, sid)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return sid2, nil
|
||||
}
|
||||
|
||||
// LookupAccount retrieves the name of the account for this sid
|
||||
// and the name of the first domain on which this sid is found.
|
||||
// System specify target computer to search for.
|
||||
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
|
||||
var sys *uint16
|
||||
if len(system) > 0 {
|
||||
sys, err = UTF16PtrFromString(system)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
}
|
||||
n := uint32(50)
|
||||
dn := uint32(50)
|
||||
for {
|
||||
b := make([]uint16, n)
|
||||
db := make([]uint16, dn)
|
||||
e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
|
||||
if e == nil {
|
||||
return UTF16ToString(b), UTF16ToString(db), accType, nil
|
||||
}
|
||||
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||
return "", "", 0, e
|
||||
}
|
||||
if n <= uint32(len(b)) {
|
||||
return "", "", 0, e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// do not reorder
|
||||
TOKEN_ASSIGN_PRIMARY = 1 << iota
|
||||
TOKEN_DUPLICATE
|
||||
TOKEN_IMPERSONATE
|
||||
TOKEN_QUERY
|
||||
TOKEN_QUERY_SOURCE
|
||||
TOKEN_ADJUST_PRIVILEGES
|
||||
TOKEN_ADJUST_GROUPS
|
||||
TOKEN_ADJUST_DEFAULT
|
||||
|
||||
TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
|
||||
TOKEN_ASSIGN_PRIMARY |
|
||||
TOKEN_DUPLICATE |
|
||||
TOKEN_IMPERSONATE |
|
||||
TOKEN_QUERY |
|
||||
TOKEN_QUERY_SOURCE |
|
||||
TOKEN_ADJUST_PRIVILEGES |
|
||||
TOKEN_ADJUST_GROUPS |
|
||||
TOKEN_ADJUST_DEFAULT
|
||||
TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
|
||||
TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
|
||||
TOKEN_ADJUST_PRIVILEGES |
|
||||
TOKEN_ADJUST_GROUPS |
|
||||
TOKEN_ADJUST_DEFAULT
|
||||
TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
|
||||
)
|
||||
|
||||
const (
|
||||
// do not reorder
|
||||
TokenUser = 1 + iota
|
||||
TokenGroups
|
||||
TokenPrivileges
|
||||
TokenOwner
|
||||
TokenPrimaryGroup
|
||||
TokenDefaultDacl
|
||||
TokenSource
|
||||
TokenType
|
||||
TokenImpersonationLevel
|
||||
TokenStatistics
|
||||
TokenRestrictedSids
|
||||
TokenSessionId
|
||||
TokenGroupsAndPrivileges
|
||||
TokenSessionReference
|
||||
TokenSandBoxInert
|
||||
TokenAuditPolicy
|
||||
TokenOrigin
|
||||
TokenElevationType
|
||||
TokenLinkedToken
|
||||
TokenElevation
|
||||
TokenHasRestrictions
|
||||
TokenAccessInformation
|
||||
TokenVirtualizationAllowed
|
||||
TokenVirtualizationEnabled
|
||||
TokenIntegrityLevel
|
||||
TokenUIAccess
|
||||
TokenMandatoryPolicy
|
||||
TokenLogonSid
|
||||
MaxTokenInfoClass
|
||||
)
|
||||
|
||||
type SIDAndAttributes struct {
|
||||
Sid *SID
|
||||
Attributes uint32
|
||||
}
|
||||
|
||||
type Tokenuser struct {
|
||||
User SIDAndAttributes
|
||||
}
|
||||
|
||||
type Tokenprimarygroup struct {
|
||||
PrimaryGroup *SID
|
||||
}
|
||||
|
||||
type Tokengroups struct {
|
||||
GroupCount uint32
|
||||
Groups [1]SIDAndAttributes
|
||||
}
|
||||
|
||||
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
|
||||
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
|
||||
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
||||
|
||||
// An access token contains the security information for a logon session.
|
||||
// The system creates an access token when a user logs on, and every
|
||||
// process executed on behalf of the user has a copy of the token.
|
||||
// The token identifies the user, the user's groups, and the user's
|
||||
// privileges. The system uses the token to control access to securable
|
||||
// objects and to control the ability of the user to perform various
|
||||
// system-related operations on the local computer.
|
||||
type Token Handle
|
||||
|
||||
// OpenCurrentProcessToken opens the access token
|
||||
// associated with current process.
|
||||
func OpenCurrentProcessToken() (Token, error) {
|
||||
p, e := GetCurrentProcess()
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
var t Token
|
||||
e = OpenProcessToken(p, TOKEN_QUERY, &t)
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// Close releases access to access token.
|
||||
func (t Token) Close() error {
|
||||
return CloseHandle(Handle(t))
|
||||
}
|
||||
|
||||
// getInfo retrieves a specified type of information about an access token.
|
||||
func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
|
||||
n := uint32(initSize)
|
||||
for {
|
||||
b := make([]byte, n)
|
||||
e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
|
||||
if e == nil {
|
||||
return unsafe.Pointer(&b[0]), nil
|
||||
}
|
||||
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||
return nil, e
|
||||
}
|
||||
if n <= uint32(len(b)) {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetTokenUser retrieves access token t user account information.
|
||||
func (t Token) GetTokenUser() (*Tokenuser, error) {
|
||||
i, e := t.getInfo(TokenUser, 50)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return (*Tokenuser)(i), nil
|
||||
}
|
||||
|
||||
// GetTokenGroups retrieves group accounts associated with access token t.
|
||||
func (t Token) GetTokenGroups() (*Tokengroups, error) {
|
||||
i, e := t.getInfo(TokenGroups, 50)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return (*Tokengroups)(i), nil
|
||||
}
|
||||
|
||||
// GetTokenPrimaryGroup retrieves access token t primary group information.
|
||||
// A pointer to a SID structure representing a group that will become
|
||||
// the primary group of any objects created by a process using this access token.
|
||||
func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
|
||||
i, e := t.getInfo(TokenPrimaryGroup, 50)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return (*Tokenprimarygroup)(i), nil
|
||||
}
|
||||
|
||||
// GetUserProfileDirectory retrieves path to the
|
||||
// root directory of the access token t user's profile.
|
||||
func (t Token) GetUserProfileDirectory() (string, error) {
|
||||
n := uint32(100)
|
||||
for {
|
||||
b := make([]uint16, n)
|
||||
e := GetUserProfileDirectory(t, &b[0], &n)
|
||||
if e == nil {
|
||||
return UTF16ToString(b), nil
|
||||
}
|
||||
if e != ERROR_INSUFFICIENT_BUFFER {
|
||||
return "", e
|
||||
}
|
||||
if n <= uint32(len(b)) {
|
||||
return "", e
|
||||
}
|
||||
}
|
||||
}
|
||||
143
vendor/golang.org/x/sys/windows/service.go
generated
vendored
Normal file
143
vendor/golang.org/x/sys/windows/service.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
const (
|
||||
SC_MANAGER_CONNECT = 1
|
||||
SC_MANAGER_CREATE_SERVICE = 2
|
||||
SC_MANAGER_ENUMERATE_SERVICE = 4
|
||||
SC_MANAGER_LOCK = 8
|
||||
SC_MANAGER_QUERY_LOCK_STATUS = 16
|
||||
SC_MANAGER_MODIFY_BOOT_CONFIG = 32
|
||||
SC_MANAGER_ALL_ACCESS = 0xf003f
|
||||
)
|
||||
|
||||
//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW
|
||||
|
||||
const (
|
||||
SERVICE_KERNEL_DRIVER = 1
|
||||
SERVICE_FILE_SYSTEM_DRIVER = 2
|
||||
SERVICE_ADAPTER = 4
|
||||
SERVICE_RECOGNIZER_DRIVER = 8
|
||||
SERVICE_WIN32_OWN_PROCESS = 16
|
||||
SERVICE_WIN32_SHARE_PROCESS = 32
|
||||
SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS
|
||||
SERVICE_INTERACTIVE_PROCESS = 256
|
||||
SERVICE_DRIVER = SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER
|
||||
SERVICE_TYPE_ALL = SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS
|
||||
|
||||
SERVICE_BOOT_START = 0
|
||||
SERVICE_SYSTEM_START = 1
|
||||
SERVICE_AUTO_START = 2
|
||||
SERVICE_DEMAND_START = 3
|
||||
SERVICE_DISABLED = 4
|
||||
|
||||
SERVICE_ERROR_IGNORE = 0
|
||||
SERVICE_ERROR_NORMAL = 1
|
||||
SERVICE_ERROR_SEVERE = 2
|
||||
SERVICE_ERROR_CRITICAL = 3
|
||||
|
||||
SC_STATUS_PROCESS_INFO = 0
|
||||
|
||||
SERVICE_STOPPED = 1
|
||||
SERVICE_START_PENDING = 2
|
||||
SERVICE_STOP_PENDING = 3
|
||||
SERVICE_RUNNING = 4
|
||||
SERVICE_CONTINUE_PENDING = 5
|
||||
SERVICE_PAUSE_PENDING = 6
|
||||
SERVICE_PAUSED = 7
|
||||
SERVICE_NO_CHANGE = 0xffffffff
|
||||
|
||||
SERVICE_ACCEPT_STOP = 1
|
||||
SERVICE_ACCEPT_PAUSE_CONTINUE = 2
|
||||
SERVICE_ACCEPT_SHUTDOWN = 4
|
||||
SERVICE_ACCEPT_PARAMCHANGE = 8
|
||||
SERVICE_ACCEPT_NETBINDCHANGE = 16
|
||||
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32
|
||||
SERVICE_ACCEPT_POWEREVENT = 64
|
||||
SERVICE_ACCEPT_SESSIONCHANGE = 128
|
||||
|
||||
SERVICE_CONTROL_STOP = 1
|
||||
SERVICE_CONTROL_PAUSE = 2
|
||||
SERVICE_CONTROL_CONTINUE = 3
|
||||
SERVICE_CONTROL_INTERROGATE = 4
|
||||
SERVICE_CONTROL_SHUTDOWN = 5
|
||||
SERVICE_CONTROL_PARAMCHANGE = 6
|
||||
SERVICE_CONTROL_NETBINDADD = 7
|
||||
SERVICE_CONTROL_NETBINDREMOVE = 8
|
||||
SERVICE_CONTROL_NETBINDENABLE = 9
|
||||
SERVICE_CONTROL_NETBINDDISABLE = 10
|
||||
SERVICE_CONTROL_DEVICEEVENT = 11
|
||||
SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12
|
||||
SERVICE_CONTROL_POWEREVENT = 13
|
||||
SERVICE_CONTROL_SESSIONCHANGE = 14
|
||||
|
||||
SERVICE_ACTIVE = 1
|
||||
SERVICE_INACTIVE = 2
|
||||
SERVICE_STATE_ALL = 3
|
||||
|
||||
SERVICE_QUERY_CONFIG = 1
|
||||
SERVICE_CHANGE_CONFIG = 2
|
||||
SERVICE_QUERY_STATUS = 4
|
||||
SERVICE_ENUMERATE_DEPENDENTS = 8
|
||||
SERVICE_START = 16
|
||||
SERVICE_STOP = 32
|
||||
SERVICE_PAUSE_CONTINUE = 64
|
||||
SERVICE_INTERROGATE = 128
|
||||
SERVICE_USER_DEFINED_CONTROL = 256
|
||||
SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL
|
||||
SERVICE_RUNS_IN_SYSTEM_PROCESS = 1
|
||||
SERVICE_CONFIG_DESCRIPTION = 1
|
||||
SERVICE_CONFIG_FAILURE_ACTIONS = 2
|
||||
|
||||
NO_ERROR = 0
|
||||
)
|
||||
|
||||
type SERVICE_STATUS struct {
|
||||
ServiceType uint32
|
||||
CurrentState uint32
|
||||
ControlsAccepted uint32
|
||||
Win32ExitCode uint32
|
||||
ServiceSpecificExitCode uint32
|
||||
CheckPoint uint32
|
||||
WaitHint uint32
|
||||
}
|
||||
|
||||
type SERVICE_TABLE_ENTRY struct {
|
||||
ServiceName *uint16
|
||||
ServiceProc uintptr
|
||||
}
|
||||
|
||||
type QUERY_SERVICE_CONFIG struct {
|
||||
ServiceType uint32
|
||||
StartType uint32
|
||||
ErrorControl uint32
|
||||
BinaryPathName *uint16
|
||||
LoadOrderGroup *uint16
|
||||
TagId uint32
|
||||
Dependencies *uint16
|
||||
ServiceStartName *uint16
|
||||
DisplayName *uint16
|
||||
}
|
||||
|
||||
type SERVICE_DESCRIPTION struct {
|
||||
Description *uint16
|
||||
}
|
||||
|
||||
//sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle
|
||||
//sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW
|
||||
//sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW
|
||||
//sys DeleteService(service Handle) (err error) = advapi32.DeleteService
|
||||
//sys StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) = advapi32.StartServiceW
|
||||
//sys QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus
|
||||
//sys ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) = advapi32.ControlService
|
||||
//sys StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) = advapi32.StartServiceCtrlDispatcherW
|
||||
//sys SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) = advapi32.SetServiceStatus
|
||||
//sys ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) = advapi32.ChangeServiceConfigW
|
||||
//sys QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfigW
|
||||
//sys ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) = advapi32.ChangeServiceConfig2W
|
||||
//sys QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceConfig2W
|
||||
22
vendor/golang.org/x/sys/windows/str.go
generated
vendored
Normal file
22
vendor/golang.org/x/sys/windows/str.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
|
||||
if val < 0 {
|
||||
return "-" + itoa(-val)
|
||||
}
|
||||
var buf [32]byte // big enough for int64
|
||||
i := len(buf) - 1
|
||||
for val >= 10 {
|
||||
buf[i] = byte(val%10 + '0')
|
||||
i--
|
||||
val /= 10
|
||||
}
|
||||
buf[i] = byte(val + '0')
|
||||
return string(buf[i:])
|
||||
}
|
||||
71
vendor/golang.org/x/sys/windows/syscall.go
generated
vendored
Normal file
71
vendor/golang.org/x/sys/windows/syscall.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
// Package windows contains an interface to the low-level operating system
|
||||
// primitives. OS details vary depending on the underlying system, and
|
||||
// by default, godoc will display the OS-specific documentation for the current
|
||||
// system. If you want godoc to display syscall documentation for another
|
||||
// system, set $GOOS and $GOARCH to the desired system. For example, if
|
||||
// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
|
||||
// to freebsd and $GOARCH to arm.
|
||||
// The primary use of this package is inside other packages that provide a more
|
||||
// portable interface to the system, such as "os", "time" and "net". Use
|
||||
// those packages rather than this one if you can.
|
||||
// For details of the functions and data types in this package consult
|
||||
// the manuals for the appropriate operating system.
|
||||
// These calls return err == nil to indicate success; otherwise
|
||||
// err represents an operating system error describing the failure and
|
||||
// holds a value of type syscall.Errno.
|
||||
package windows // import "golang.org/x/sys/windows"
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||
// containing the text of s. If s contains a NUL byte at any
|
||||
// location, it returns (nil, syscall.EINVAL).
|
||||
func ByteSliceFromString(s string) ([]byte, error) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == 0 {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
}
|
||||
a := make([]byte, len(s)+1)
|
||||
copy(a, s)
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// BytePtrFromString returns a pointer to a NUL-terminated array of
|
||||
// bytes containing the text of s. If s contains a NUL byte at any
|
||||
// location, it returns (nil, syscall.EINVAL).
|
||||
func BytePtrFromString(s string) (*byte, error) {
|
||||
a, err := ByteSliceFromString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &a[0], nil
|
||||
}
|
||||
|
||||
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||
// See mksyscall.pl.
|
||||
var _zero uintptr
|
||||
|
||||
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
||||
return int64(ts.Sec), int64(ts.Nsec)
|
||||
}
|
||||
|
||||
func (tv *Timeval) Unix() (sec int64, nsec int64) {
|
||||
return int64(tv.Sec), int64(tv.Usec) * 1000
|
||||
}
|
||||
|
||||
func (ts *Timespec) Nano() int64 {
|
||||
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
|
||||
}
|
||||
|
||||
func (tv *Timeval) Nano() int64 {
|
||||
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
|
||||
}
|
||||
991
vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
Normal file
991
vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
Normal file
@@ -0,0 +1,991 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Windows system calls.
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
errorspkg "errors"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -xsys -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go
|
||||
|
||||
type Handle uintptr
|
||||
|
||||
const InvalidHandle = ^Handle(0)
|
||||
|
||||
// StringToUTF16 is deprecated. Use UTF16FromString instead.
|
||||
// If s contains a NUL byte this function panics instead of
|
||||
// returning an error.
|
||||
func StringToUTF16(s string) []uint16 {
|
||||
a, err := UTF16FromString(s)
|
||||
if err != nil {
|
||||
panic("windows: string with NUL passed to StringToUTF16")
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// UTF16FromString returns the UTF-16 encoding of the UTF-8 string
|
||||
// s, with a terminating NUL added. If s contains a NUL byte at any
|
||||
// location, it returns (nil, syscall.EINVAL).
|
||||
func UTF16FromString(s string) ([]uint16, error) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == 0 {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return utf16.Encode([]rune(s + "\x00")), nil
|
||||
}
|
||||
|
||||
// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
|
||||
// with a terminating NUL removed.
|
||||
func UTF16ToString(s []uint16) string {
|
||||
for i, v := range s {
|
||||
if v == 0 {
|
||||
s = s[0:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
return string(utf16.Decode(s))
|
||||
}
|
||||
|
||||
// StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead.
|
||||
// If s contains a NUL byte this function panics instead of
|
||||
// returning an error.
|
||||
func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
|
||||
|
||||
// UTF16PtrFromString returns pointer to the UTF-16 encoding of
|
||||
// the UTF-8 string s, with a terminating NUL added. If s
|
||||
// contains a NUL byte at any location, it returns (nil, syscall.EINVAL).
|
||||
func UTF16PtrFromString(s string) (*uint16, error) {
|
||||
a, err := UTF16FromString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &a[0], nil
|
||||
}
|
||||
|
||||
func Getpagesize() int { return 4096 }
|
||||
|
||||
// Converts a Go function to a function pointer conforming
|
||||
// to the stdcall or cdecl calling convention. This is useful when
|
||||
// interoperating with Windows code requiring callbacks.
|
||||
// Implemented in runtime/syscall_windows.goc
|
||||
func NewCallback(fn interface{}) uintptr
|
||||
func NewCallbackCDecl(fn interface{}) uintptr
|
||||
|
||||
// windows api calls
|
||||
|
||||
//sys GetLastError() (lasterr error)
|
||||
//sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW
|
||||
//sys LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) = LoadLibraryExW
|
||||
//sys FreeLibrary(handle Handle) (err error)
|
||||
//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error)
|
||||
//sys GetVersion() (ver uint32, err error)
|
||||
//sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
|
||||
//sys ExitProcess(exitcode uint32)
|
||||
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
|
||||
//sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
|
||||
//sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
|
||||
//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
|
||||
//sys CloseHandle(handle Handle) (err error)
|
||||
//sys GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle]
|
||||
//sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW
|
||||
//sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW
|
||||
//sys FindClose(handle Handle) (err error)
|
||||
//sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error)
|
||||
//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW
|
||||
//sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW
|
||||
//sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW
|
||||
//sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW
|
||||
//sys DeleteFile(path *uint16) (err error) = DeleteFileW
|
||||
//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW
|
||||
//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
|
||||
//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
|
||||
//sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
|
||||
//sys SetEndOfFile(handle Handle) (err error)
|
||||
//sys GetSystemTimeAsFileTime(time *Filetime)
|
||||
//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
|
||||
//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error)
|
||||
//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error)
|
||||
//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error)
|
||||
//sys CancelIo(s Handle) (err error)
|
||||
//sys CancelIoEx(s Handle, o *Overlapped) (err error)
|
||||
//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
|
||||
//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error)
|
||||
//sys TerminateProcess(handle Handle, exitcode uint32) (err error)
|
||||
//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
|
||||
//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW
|
||||
//sys GetCurrentProcess() (pseudoHandle Handle, err error)
|
||||
//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
|
||||
//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
|
||||
//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]
|
||||
//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW
|
||||
//sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error)
|
||||
//sys GetFileType(filehandle Handle) (n uint32, err error)
|
||||
//sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW
|
||||
//sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext
|
||||
//sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom
|
||||
//sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW
|
||||
//sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW
|
||||
//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW
|
||||
//sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW
|
||||
//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error)
|
||||
//sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
|
||||
//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
|
||||
//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW
|
||||
//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
|
||||
//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
|
||||
//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0]
|
||||
//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
|
||||
//sys FlushFileBuffers(handle Handle) (err error)
|
||||
//sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW
|
||||
//sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW
|
||||
//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW
|
||||
//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW
|
||||
//sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error)
|
||||
//sys UnmapViewOfFile(addr uintptr) (err error)
|
||||
//sys FlushViewOfFile(addr uintptr, length uintptr) (err error)
|
||||
//sys VirtualLock(addr uintptr, length uintptr) (err error)
|
||||
//sys VirtualUnlock(addr uintptr, length uintptr) (err error)
|
||||
//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
|
||||
//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
|
||||
//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
|
||||
//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore
|
||||
//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
|
||||
//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore
|
||||
//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
|
||||
//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain
|
||||
//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain
|
||||
//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext
|
||||
//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext
|
||||
//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy
|
||||
//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
|
||||
//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
|
||||
//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW
|
||||
//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
|
||||
//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
|
||||
//sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
|
||||
//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
|
||||
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
|
||||
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
|
||||
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
|
||||
//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW
|
||||
//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW
|
||||
//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error)
|
||||
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
|
||||
//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW
|
||||
//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW
|
||||
//sys GetCurrentThreadId() (id uint32)
|
||||
//sys CreateEvent(eventAttrs *syscall.SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) = kernel32.CreateEventW
|
||||
//sys SetEvent(event Handle) (err error) = kernel32.SetEvent
|
||||
|
||||
// syscall interface implementation for other packages
|
||||
|
||||
func Exit(code int) { ExitProcess(uint32(code)) }
|
||||
|
||||
func makeInheritSa() *SecurityAttributes {
|
||||
var sa SecurityAttributes
|
||||
sa.Length = uint32(unsafe.Sizeof(sa))
|
||||
sa.InheritHandle = 1
|
||||
return &sa
|
||||
}
|
||||
|
||||
func Open(path string, mode int, perm uint32) (fd Handle, err error) {
|
||||
if len(path) == 0 {
|
||||
return InvalidHandle, ERROR_FILE_NOT_FOUND
|
||||
}
|
||||
pathp, err := UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return InvalidHandle, err
|
||||
}
|
||||
var access uint32
|
||||
switch mode & (O_RDONLY | O_WRONLY | O_RDWR) {
|
||||
case O_RDONLY:
|
||||
access = GENERIC_READ
|
||||
case O_WRONLY:
|
||||
access = GENERIC_WRITE
|
||||
case O_RDWR:
|
||||
access = GENERIC_READ | GENERIC_WRITE
|
||||
}
|
||||
if mode&O_CREAT != 0 {
|
||||
access |= GENERIC_WRITE
|
||||
}
|
||||
if mode&O_APPEND != 0 {
|
||||
access &^= GENERIC_WRITE
|
||||
access |= FILE_APPEND_DATA
|
||||
}
|
||||
sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
|
||||
var sa *SecurityAttributes
|
||||
if mode&O_CLOEXEC == 0 {
|
||||
sa = makeInheritSa()
|
||||
}
|
||||
var createmode uint32
|
||||
switch {
|
||||
case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
|
||||
createmode = CREATE_NEW
|
||||
case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
|
||||
createmode = CREATE_ALWAYS
|
||||
case mode&O_CREAT == O_CREAT:
|
||||
createmode = OPEN_ALWAYS
|
||||
case mode&O_TRUNC == O_TRUNC:
|
||||
createmode = TRUNCATE_EXISTING
|
||||
default:
|
||||
createmode = OPEN_EXISTING
|
||||
}
|
||||
h, e := CreateFile(pathp, access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
|
||||
return h, e
|
||||
}
|
||||
|
||||
func Read(fd Handle, p []byte) (n int, err error) {
|
||||
var done uint32
|
||||
e := ReadFile(fd, p, &done, nil)
|
||||
if e != nil {
|
||||
if e == ERROR_BROKEN_PIPE {
|
||||
// NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin
|
||||
return 0, nil
|
||||
}
|
||||
return 0, e
|
||||
}
|
||||
if raceenabled {
|
||||
if done > 0 {
|
||||
raceWriteRange(unsafe.Pointer(&p[0]), int(done))
|
||||
}
|
||||
raceAcquire(unsafe.Pointer(&ioSync))
|
||||
}
|
||||
return int(done), nil
|
||||
}
|
||||
|
||||
func Write(fd Handle, p []byte) (n int, err error) {
|
||||
if raceenabled {
|
||||
raceReleaseMerge(unsafe.Pointer(&ioSync))
|
||||
}
|
||||
var done uint32
|
||||
e := WriteFile(fd, p, &done, nil)
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
if raceenabled && done > 0 {
|
||||
raceReadRange(unsafe.Pointer(&p[0]), int(done))
|
||||
}
|
||||
return int(done), nil
|
||||
}
|
||||
|
||||
var ioSync int64
|
||||
|
||||
func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
|
||||
var w uint32
|
||||
switch whence {
|
||||
case 0:
|
||||
w = FILE_BEGIN
|
||||
case 1:
|
||||
w = FILE_CURRENT
|
||||
case 2:
|
||||
w = FILE_END
|
||||
}
|
||||
hi := int32(offset >> 32)
|
||||
lo := int32(offset)
|
||||
// use GetFileType to check pipe, pipe can't do seek
|
||||
ft, _ := GetFileType(fd)
|
||||
if ft == FILE_TYPE_PIPE {
|
||||
return 0, syscall.EPIPE
|
||||
}
|
||||
rlo, e := SetFilePointer(fd, lo, &hi, w)
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
return int64(hi)<<32 + int64(rlo), nil
|
||||
}
|
||||
|
||||
func Close(fd Handle) (err error) {
|
||||
return CloseHandle(fd)
|
||||
}
|
||||
|
||||
var (
|
||||
Stdin = getStdHandle(STD_INPUT_HANDLE)
|
||||
Stdout = getStdHandle(STD_OUTPUT_HANDLE)
|
||||
Stderr = getStdHandle(STD_ERROR_HANDLE)
|
||||
)
|
||||
|
||||
func getStdHandle(h int) (fd Handle) {
|
||||
r, _ := GetStdHandle(h)
|
||||
CloseOnExec(r)
|
||||
return r
|
||||
}
|
||||
|
||||
const ImplementsGetwd = true
|
||||
|
||||
func Getwd() (wd string, err error) {
|
||||
b := make([]uint16, 300)
|
||||
n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
return string(utf16.Decode(b[0:n])), nil
|
||||
}
|
||||
|
||||
func Chdir(path string) (err error) {
|
||||
pathp, err := UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return SetCurrentDirectory(pathp)
|
||||
}
|
||||
|
||||
func Mkdir(path string, mode uint32) (err error) {
|
||||
pathp, err := UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return CreateDirectory(pathp, nil)
|
||||
}
|
||||
|
||||
func Rmdir(path string) (err error) {
|
||||
pathp, err := UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return RemoveDirectory(pathp)
|
||||
}
|
||||
|
||||
func Unlink(path string) (err error) {
|
||||
pathp, err := UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return DeleteFile(pathp)
|
||||
}
|
||||
|
||||
func Rename(oldpath, newpath string) (err error) {
|
||||
from, err := UTF16PtrFromString(oldpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
to, err := UTF16PtrFromString(newpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
func ComputerName() (name string, err error) {
|
||||
var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
|
||||
b := make([]uint16, n)
|
||||
e := GetComputerName(&b[0], &n)
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
return string(utf16.Decode(b[0:n])), nil
|
||||
}
|
||||
|
||||
func Ftruncate(fd Handle, length int64) (err error) {
|
||||
curoffset, e := Seek(fd, 0, 1)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
defer Seek(fd, curoffset, 0)
|
||||
_, e = Seek(fd, length, 0)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
e = SetEndOfFile(fd)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Gettimeofday(tv *Timeval) (err error) {
|
||||
var ft Filetime
|
||||
GetSystemTimeAsFileTime(&ft)
|
||||
*tv = NsecToTimeval(ft.Nanoseconds())
|
||||
return nil
|
||||
}
|
||||
|
||||
func Pipe(p []Handle) (err error) {
|
||||
if len(p) != 2 {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
var r, w Handle
|
||||
e := CreatePipe(&r, &w, makeInheritSa(), 0)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
p[0] = r
|
||||
p[1] = w
|
||||
return nil
|
||||
}
|
||||
|
||||
func Utimes(path string, tv []Timeval) (err error) {
|
||||
if len(tv) != 2 {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
pathp, e := UTF16PtrFromString(path)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
h, e := CreateFile(pathp,
|
||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
defer Close(h)
|
||||
a := NsecToFiletime(tv[0].Nanoseconds())
|
||||
w := NsecToFiletime(tv[1].Nanoseconds())
|
||||
return SetFileTime(h, nil, &a, &w)
|
||||
}
|
||||
|
||||
func UtimesNano(path string, ts []Timespec) (err error) {
|
||||
if len(ts) != 2 {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
pathp, e := UTF16PtrFromString(path)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
h, e := CreateFile(pathp,
|
||||
FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
defer Close(h)
|
||||
a := NsecToFiletime(TimespecToNsec(ts[0]))
|
||||
w := NsecToFiletime(TimespecToNsec(ts[1]))
|
||||
return SetFileTime(h, nil, &a, &w)
|
||||
}
|
||||
|
||||
func Fsync(fd Handle) (err error) {
|
||||
return FlushFileBuffers(fd)
|
||||
}
|
||||
|
||||
func Chmod(path string, mode uint32) (err error) {
|
||||
if mode == 0 {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
p, e := UTF16PtrFromString(path)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
attrs, e := GetFileAttributes(p)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
if mode&S_IWRITE != 0 {
|
||||
attrs &^= FILE_ATTRIBUTE_READONLY
|
||||
} else {
|
||||
attrs |= FILE_ATTRIBUTE_READONLY
|
||||
}
|
||||
return SetFileAttributes(p, attrs)
|
||||
}
|
||||
|
||||
func LoadCancelIoEx() error {
|
||||
return procCancelIoEx.Find()
|
||||
}
|
||||
|
||||
func LoadSetFileCompletionNotificationModes() error {
|
||||
return procSetFileCompletionNotificationModes.Find()
|
||||
}
|
||||
|
||||
// net api calls
|
||||
|
||||
const socket_error = uintptr(^uint32(0))
|
||||
|
||||
//sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup
|
||||
//sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup
|
||||
//sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl
|
||||
//sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket
|
||||
//sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt
|
||||
//sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt
|
||||
//sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind
|
||||
//sys connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect
|
||||
//sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname
|
||||
//sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername
|
||||
//sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen
|
||||
//sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown
|
||||
//sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket
|
||||
//sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx
|
||||
//sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs
|
||||
//sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv
|
||||
//sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend
|
||||
//sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom
|
||||
//sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo
|
||||
//sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname
|
||||
//sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname
|
||||
//sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs
|
||||
//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname
|
||||
//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W
|
||||
//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
|
||||
//sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W
|
||||
//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW
|
||||
//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW
|
||||
//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry
|
||||
//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo
|
||||
//sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes
|
||||
//sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW
|
||||
//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
|
||||
//sys GetACP() (acp uint32) = kernel32.GetACP
|
||||
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
|
||||
|
||||
// For testing: clients can set this flag to force
|
||||
// creation of IPv6 sockets to return EAFNOSUPPORT.
|
||||
var SocketDisableIPv6 bool
|
||||
|
||||
type RawSockaddrInet4 struct {
|
||||
Family uint16
|
||||
Port uint16
|
||||
Addr [4]byte /* in_addr */
|
||||
Zero [8]uint8
|
||||
}
|
||||
|
||||
type RawSockaddrInet6 struct {
|
||||
Family uint16
|
||||
Port uint16
|
||||
Flowinfo uint32
|
||||
Addr [16]byte /* in6_addr */
|
||||
Scope_id uint32
|
||||
}
|
||||
|
||||
type RawSockaddr struct {
|
||||
Family uint16
|
||||
Data [14]int8
|
||||
}
|
||||
|
||||
type RawSockaddrAny struct {
|
||||
Addr RawSockaddr
|
||||
Pad [96]int8
|
||||
}
|
||||
|
||||
type Sockaddr interface {
|
||||
sockaddr() (ptr unsafe.Pointer, len int32, err error) // lowercase; only we can define Sockaddrs
|
||||
}
|
||||
|
||||
type SockaddrInet4 struct {
|
||||
Port int
|
||||
Addr [4]byte
|
||||
raw RawSockaddrInet4
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) {
|
||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
sa.raw.Family = AF_INET
|
||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
|
||||
}
|
||||
|
||||
type SockaddrInet6 struct {
|
||||
Port int
|
||||
ZoneId uint32
|
||||
Addr [16]byte
|
||||
raw RawSockaddrInet6
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
|
||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
sa.raw.Family = AF_INET6
|
||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
sa.raw.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
|
||||
}
|
||||
|
||||
type SockaddrUnix struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
|
||||
// TODO(brainman): implement SockaddrUnix.sockaddr()
|
||||
return nil, 0, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
|
||||
switch rsa.Addr.Family {
|
||||
case AF_UNIX:
|
||||
return nil, syscall.EWINDOWS
|
||||
|
||||
case AF_INET:
|
||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
||||
sa := new(SockaddrInet4)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
return sa, nil
|
||||
|
||||
case AF_INET6:
|
||||
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
|
||||
sa := new(SockaddrInet6)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.ZoneId = pp.Scope_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
return sa, nil
|
||||
}
|
||||
return nil, syscall.EAFNOSUPPORT
|
||||
}
|
||||
|
||||
func Socket(domain, typ, proto int) (fd Handle, err error) {
|
||||
if domain == AF_INET6 && SocketDisableIPv6 {
|
||||
return InvalidHandle, syscall.EAFNOSUPPORT
|
||||
}
|
||||
return socket(int32(domain), int32(typ), int32(proto))
|
||||
}
|
||||
|
||||
func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
|
||||
v := int32(value)
|
||||
return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
|
||||
}
|
||||
|
||||
func Bind(fd Handle, sa Sockaddr) (err error) {
|
||||
ptr, n, err := sa.sockaddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return bind(fd, ptr, n)
|
||||
}
|
||||
|
||||
func Connect(fd Handle, sa Sockaddr) (err error) {
|
||||
ptr, n, err := sa.sockaddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return connect(fd, ptr, n)
|
||||
}
|
||||
|
||||
func Getsockname(fd Handle) (sa Sockaddr, err error) {
|
||||
var rsa RawSockaddrAny
|
||||
l := int32(unsafe.Sizeof(rsa))
|
||||
if err = getsockname(fd, &rsa, &l); err != nil {
|
||||
return
|
||||
}
|
||||
return rsa.Sockaddr()
|
||||
}
|
||||
|
||||
func Getpeername(fd Handle) (sa Sockaddr, err error) {
|
||||
var rsa RawSockaddrAny
|
||||
l := int32(unsafe.Sizeof(rsa))
|
||||
if err = getpeername(fd, &rsa, &l); err != nil {
|
||||
return
|
||||
}
|
||||
return rsa.Sockaddr()
|
||||
}
|
||||
|
||||
func Listen(s Handle, n int) (err error) {
|
||||
return listen(s, int32(n))
|
||||
}
|
||||
|
||||
func Shutdown(fd Handle, how int) (err error) {
|
||||
return shutdown(fd, int32(how))
|
||||
}
|
||||
|
||||
func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
|
||||
rsa, l, err := to.sockaddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine)
|
||||
}
|
||||
|
||||
func LoadGetAddrInfo() error {
|
||||
return procGetAddrInfoW.Find()
|
||||
}
|
||||
|
||||
var connectExFunc struct {
|
||||
once sync.Once
|
||||
addr uintptr
|
||||
err error
|
||||
}
|
||||
|
||||
func LoadConnectEx() error {
|
||||
connectExFunc.once.Do(func() {
|
||||
var s Handle
|
||||
s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
|
||||
if connectExFunc.err != nil {
|
||||
return
|
||||
}
|
||||
defer CloseHandle(s)
|
||||
var n uint32
|
||||
connectExFunc.err = WSAIoctl(s,
|
||||
SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
(*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
|
||||
uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
|
||||
(*byte)(unsafe.Pointer(&connectExFunc.addr)),
|
||||
uint32(unsafe.Sizeof(connectExFunc.addr)),
|
||||
&n, nil, 0)
|
||||
})
|
||||
return connectExFunc.err
|
||||
}
|
||||
|
||||
func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
|
||||
err := LoadConnectEx()
|
||||
if err != nil {
|
||||
return errorspkg.New("failed to find ConnectEx: " + err.Error())
|
||||
}
|
||||
ptr, n, err := sa.sockaddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
|
||||
}
|
||||
|
||||
// Invented structures to support what package os expects.
|
||||
type Rusage struct {
|
||||
CreationTime Filetime
|
||||
ExitTime Filetime
|
||||
KernelTime Filetime
|
||||
UserTime Filetime
|
||||
}
|
||||
|
||||
type WaitStatus struct {
|
||||
ExitCode uint32
|
||||
}
|
||||
|
||||
func (w WaitStatus) Exited() bool { return true }
|
||||
|
||||
func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
|
||||
|
||||
func (w WaitStatus) Signal() Signal { return -1 }
|
||||
|
||||
func (w WaitStatus) CoreDump() bool { return false }
|
||||
|
||||
func (w WaitStatus) Stopped() bool { return false }
|
||||
|
||||
func (w WaitStatus) Continued() bool { return false }
|
||||
|
||||
func (w WaitStatus) StopSignal() Signal { return -1 }
|
||||
|
||||
func (w WaitStatus) Signaled() bool { return false }
|
||||
|
||||
func (w WaitStatus) TrapCause() int { return -1 }
|
||||
|
||||
// Timespec is an invented structure on Windows, but here for
|
||||
// consistency with the corresponding package for other operating systems.
|
||||
type Timespec struct {
|
||||
Sec int64
|
||||
Nsec int64
|
||||
}
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = nsec / 1e9
|
||||
ts.Nsec = nsec % 1e9
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(brainman): fix all needed for net
|
||||
|
||||
func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, syscall.EWINDOWS }
|
||||
func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
|
||||
return 0, nil, syscall.EWINDOWS
|
||||
}
|
||||
func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return syscall.EWINDOWS }
|
||||
func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return syscall.EWINDOWS }
|
||||
|
||||
// The Linger struct is wrong but we only noticed after Go 1.
|
||||
// sysLinger is the real system call structure.
|
||||
|
||||
// BUG(brainman): The definition of Linger is not appropriate for direct use
|
||||
// with Setsockopt and Getsockopt.
|
||||
// Use SetsockoptLinger instead.
|
||||
|
||||
type Linger struct {
|
||||
Onoff int32
|
||||
Linger int32
|
||||
}
|
||||
|
||||
type sysLinger struct {
|
||||
Onoff uint16
|
||||
Linger uint16
|
||||
}
|
||||
|
||||
type IPMreq struct {
|
||||
Multiaddr [4]byte /* in_addr */
|
||||
Interface [4]byte /* in_addr */
|
||||
}
|
||||
|
||||
type IPv6Mreq struct {
|
||||
Multiaddr [16]byte /* in6_addr */
|
||||
Interface uint32
|
||||
}
|
||||
|
||||
func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, syscall.EWINDOWS }
|
||||
|
||||
func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
|
||||
sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
|
||||
return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
|
||||
}
|
||||
|
||||
func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
|
||||
return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
|
||||
}
|
||||
func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
|
||||
return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
|
||||
}
|
||||
func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) {
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func Getpid() (pid int) { return int(getCurrentProcessId()) }
|
||||
|
||||
func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
|
||||
// NOTE(rsc): The Win32finddata struct is wrong for the system call:
|
||||
// the two paths are each one uint16 short. Use the correct struct,
|
||||
// a win32finddata1, and then copy the results out.
|
||||
// There is no loss of expressivity here, because the final
|
||||
// uint16, if it is used, is supposed to be a NUL, and Go doesn't need that.
|
||||
// For Go 1.1, we might avoid the allocation of win32finddata1 here
|
||||
// by adding a final Bug [2]uint16 field to the struct and then
|
||||
// adjusting the fields in the result directly.
|
||||
var data1 win32finddata1
|
||||
handle, err = findFirstFile1(name, &data1)
|
||||
if err == nil {
|
||||
copyFindData(data, &data1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func FindNextFile(handle Handle, data *Win32finddata) (err error) {
|
||||
var data1 win32finddata1
|
||||
err = findNextFile1(handle, &data1)
|
||||
if err == nil {
|
||||
copyFindData(data, &data1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getProcessEntry(pid int) (*ProcessEntry32, error) {
|
||||
snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer CloseHandle(snapshot)
|
||||
var procEntry ProcessEntry32
|
||||
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
|
||||
if err = Process32First(snapshot, &procEntry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
if procEntry.ProcessID == uint32(pid) {
|
||||
return &procEntry, nil
|
||||
}
|
||||
err = Process32Next(snapshot, &procEntry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Getppid() (ppid int) {
|
||||
pe, err := getProcessEntry(Getpid())
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return int(pe.ParentProcessID)
|
||||
}
|
||||
|
||||
// TODO(brainman): fix all needed for os
|
||||
func Fchdir(fd Handle) (err error) { return syscall.EWINDOWS }
|
||||
func Link(oldpath, newpath string) (err error) { return syscall.EWINDOWS }
|
||||
func Symlink(path, link string) (err error) { return syscall.EWINDOWS }
|
||||
|
||||
func Fchmod(fd Handle, mode uint32) (err error) { return syscall.EWINDOWS }
|
||||
func Chown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS }
|
||||
func Lchown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS }
|
||||
func Fchown(fd Handle, uid int, gid int) (err error) { return syscall.EWINDOWS }
|
||||
|
||||
func Getuid() (uid int) { return -1 }
|
||||
func Geteuid() (euid int) { return -1 }
|
||||
func Getgid() (gid int) { return -1 }
|
||||
func Getegid() (egid int) { return -1 }
|
||||
func Getgroups() (gids []int, err error) { return nil, syscall.EWINDOWS }
|
||||
|
||||
type Signal int
|
||||
|
||||
func (s Signal) Signal() {}
|
||||
|
||||
func (s Signal) String() string {
|
||||
if 0 <= s && int(s) < len(signals) {
|
||||
str := signals[s]
|
||||
if str != "" {
|
||||
return str
|
||||
}
|
||||
}
|
||||
return "signal " + itoa(int(s))
|
||||
}
|
||||
|
||||
func LoadCreateSymbolicLink() error {
|
||||
return procCreateSymbolicLinkW.Find()
|
||||
}
|
||||
|
||||
// Readlink returns the destination of the named symbolic link.
|
||||
func Readlink(path string, buf []byte) (n int, err error) {
|
||||
fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer CloseHandle(fd)
|
||||
|
||||
rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
|
||||
var bytesReturned uint32
|
||||
err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
|
||||
var s string
|
||||
switch rdb.ReparseTag {
|
||||
case IO_REPARSE_TAG_SYMLINK:
|
||||
data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
|
||||
p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
|
||||
s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2])
|
||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
|
||||
p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
|
||||
s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2])
|
||||
default:
|
||||
// the path is not a symlink or junction but another type of reparse
|
||||
// point
|
||||
return -1, syscall.ENOENT
|
||||
}
|
||||
n = copy(buf, []byte(s))
|
||||
|
||||
return n, nil
|
||||
}
|
||||
2245
vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
Normal file
2245
vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1242
vendor/golang.org/x/sys/windows/ztypes_windows.go
generated
vendored
Normal file
1242
vendor/golang.org/x/sys/windows/ztypes_windows.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
22
vendor/golang.org/x/sys/windows/ztypes_windows_386.go
generated
vendored
Normal file
22
vendor/golang.org/x/sys/windows/ztypes_windows_386.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package windows
|
||||
|
||||
type WSAData struct {
|
||||
Version uint16
|
||||
HighVersion uint16
|
||||
Description [WSADESCRIPTION_LEN + 1]byte
|
||||
SystemStatus [WSASYS_STATUS_LEN + 1]byte
|
||||
MaxSockets uint16
|
||||
MaxUdpDg uint16
|
||||
VendorInfo *byte
|
||||
}
|
||||
|
||||
type Servent struct {
|
||||
Name *byte
|
||||
Aliases **byte
|
||||
Port uint16
|
||||
Proto *byte
|
||||
}
|
||||
22
vendor/golang.org/x/sys/windows/ztypes_windows_amd64.go
generated
vendored
Normal file
22
vendor/golang.org/x/sys/windows/ztypes_windows_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package windows
|
||||
|
||||
type WSAData struct {
|
||||
Version uint16
|
||||
HighVersion uint16
|
||||
MaxSockets uint16
|
||||
MaxUdpDg uint16
|
||||
VendorInfo *byte
|
||||
Description [WSADESCRIPTION_LEN + 1]byte
|
||||
SystemStatus [WSASYS_STATUS_LEN + 1]byte
|
||||
}
|
||||
|
||||
type Servent struct {
|
||||
Name *byte
|
||||
Aliases **byte
|
||||
Proto *byte
|
||||
Port uint16
|
||||
}
|
||||
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@@ -578,6 +578,12 @@
|
||||
{
|
||||
"path": "golang.org/x/sys/unix",
|
||||
"revision": "50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "6aa7Y4gpUDxYNt48cOT95zMjp9E=",
|
||||
"path": "golang.org/x/sys/windows",
|
||||
"revision": "b776ec39b3e54652e09028aaaaac9757f4f8211a",
|
||||
"revisionTime": "2016-04-21T02:29:30Z"
|
||||
}
|
||||
],
|
||||
"rootPath": "github.com/hashicorp/nomad"
|
||||
|
||||
@@ -19,7 +19,7 @@ the Nomad agent.
|
||||
When specifying multiple config file options on the command-line, the files are
|
||||
loaded in the order they are specified. For example:
|
||||
|
||||
nomad agent -config server.conf /etc/nomad extra.json
|
||||
nomad agent -config server.conf -config /etc/nomad -config extra.json
|
||||
|
||||
Will load configuration from `server.conf`, from `.hcl` and `.json` files under
|
||||
`/etc/nomad`, and finally from `extra.json`.
|
||||
|
||||
@@ -61,3 +61,185 @@ Below is sample output of a telemetry dump:
|
||||
[2015-09-17 16:59:40 -0700 PDT][S] 'nomad.nomad.eval.dequeue': Count: 21 Min: 500.610 Mean: 501.753 Max: 503.361 Stddev: 1.030 Sum: 10536.813
|
||||
[2015-09-17 16:59:40 -0700 PDT][S] 'nomad.memberlist.gossip': Count: 12 Min: 0.009 Mean: 0.017 Max: 0.025 Stddev: 0.005 Sum: 0.204
|
||||
```
|
||||
|
||||
# Key Metrics
|
||||
|
||||
When telemetry is being streamed to statsite or statsd, `interval` is defined to
|
||||
be their flush interval. Otherwise, the interval can be assumed to be 10 seconds
|
||||
when retrieving metrics using the above described signals.
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr>
|
||||
<th>Metric</th>
|
||||
<th>Description</th>
|
||||
<th>Unit</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.runtime.num_goroutines`</td>
|
||||
<td>Number of goroutines and general load pressure indicator</td>
|
||||
<td># of goroutines</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.runtime.alloc_bytes`</td>
|
||||
<td>Memory utilization</td>
|
||||
<td># of bytes</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.runtime.heap_objects`</td>
|
||||
<td>Number of objects on the heap. General memory pressure indicator</td>
|
||||
<td># of heap objects</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.raft.apply`</td>
|
||||
<td>Number of Raft transactions</td>
|
||||
<td>Raft transactions / `interval`</td>
|
||||
<td>Counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.raft.replication.appendEntries`</td>
|
||||
<td>Raft transaction commit time</td>
|
||||
<td>ms / Raft Log Append</td>
|
||||
<td>Timer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.raft.leader.lastContact`</td>
|
||||
<td>Time since last contact to leader. General indicator of Raft latency</td>
|
||||
<td>ms / Leader Contact</td>
|
||||
<td>Timer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.broker.total_ready`</td>
|
||||
<td>Number of evaluations ready to be processed</td>
|
||||
<td># of evaluations</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.broker.total_unacked`</td>
|
||||
<td>Evaluations dispatched for processing but incomplete</td>
|
||||
<td># of evaluations</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.broker.total_blocked`</td>
|
||||
<td>
|
||||
Evaluations that are blocked til an existing evaluation for the same job
|
||||
completes
|
||||
</td>
|
||||
<td># of evaluations</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.plan.queue_depth`</td>
|
||||
<td>Number of scheduler Plans waiting to be evaluated</td>
|
||||
<td># of plans</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.plan.submit`</td>
|
||||
<td>
|
||||
Time to submit a scheduler Plan. Higher values cause lower scheduling
|
||||
throughput
|
||||
</td>
|
||||
<td>ms / Plan Submit</td>
|
||||
<td>Timer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.plan.evaluate`</td>
|
||||
<td>
|
||||
Time to validate a scheduler Plan. Higher values cause lower scheduling
|
||||
throughput. Similar to `nomad.plan.submit` but does not include RPC time
|
||||
or time in the Plan Queue
|
||||
</td>
|
||||
<td>ms / Plan Evaluation</td>
|
||||
<td>Timer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.worker.invoke_scheduler.<type>`</td>
|
||||
<td>Time to run the scheduler of the given type</td>
|
||||
<td>ms / Scheduler Run</td>
|
||||
<td>Timer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.worker.wait_for_index`</td>
|
||||
<td>
|
||||
Time waiting for Raft log replication from leader. High delays result in
|
||||
lower scheduling throughput
|
||||
</td>
|
||||
<td>ms / Raft Index Wait</td>
|
||||
<td>Timer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.heartbeat.active`</td>
|
||||
<td>
|
||||
Number of active heartbeat timers. Each timer represents a Nomad Client
|
||||
connection
|
||||
</td>
|
||||
<td># of heartbeat timers</td>
|
||||
<td>Gauge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.heartbeat.invalidate`</td>
|
||||
<td>
|
||||
The length of time it takes to invalidate a Nomad Client due to failed
|
||||
heartbeats
|
||||
</td>
|
||||
<td>ms / Heartbeat Invalidation</td>
|
||||
<td>Timer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.rpc.query`</td>
|
||||
<td>Number of RPC queries</td>
|
||||
<td>RPC Queries / `interval`</td>
|
||||
<td>Counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.rpc.request`</td>
|
||||
<td>Number of RPC requests being handled</td>
|
||||
<td>RPC Requests / `interval`</td>
|
||||
<td>Counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`nomad.rpc.request_error`</td>
|
||||
<td>Number of RPC requests being handled that result in an error</td>
|
||||
<td>RPC Errors / `interval`</td>
|
||||
<td>Counter</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
# Metric Types
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Quantiles</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gauge</td>
|
||||
<td>
|
||||
Gauge types report an absolute number at the end of the aggregation
|
||||
interval
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Counter</td>
|
||||
<td>
|
||||
Counts are incremented and flushed at the end of the aggregation
|
||||
interval and then are reset to zero
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Timer</td>
|
||||
<td>
|
||||
Timers measure the time to complete a task and will include quantiles,
|
||||
means, standard deviation, etc per interval.
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -241,47 +241,79 @@ The `Job` object supports the following keys:
|
||||
|
||||
### Task Group
|
||||
|
||||
`TaskGroups` is a list of `Task Group`, and each object supports the following
|
||||
`TaskGroups` is a list of `TaskGroup` objects, each supports the following
|
||||
attributes:
|
||||
|
||||
* `Constraints` - This is a list of `Constraint` objects. See the constraint
|
||||
reference for more details.
|
||||
|
||||
* `Count` - Specifies the number of the task groups that should
|
||||
be running. Must be non-negative, defaults to one.
|
||||
|
||||
* `Constraints` - This is a list of `Constraint` objects. See the constraint
|
||||
reference for more details.
|
||||
* `Meta` - A key/value map that annotates the task group with opaque metadata.
|
||||
|
||||
* `Name` - The name of the task group. Must be specified.
|
||||
|
||||
* `RestartPolicy` - Specifies the restart policy to be applied to tasks in this group.
|
||||
If omitted, a default policy for batch and non-batch jobs is used based on the
|
||||
job type. See the restart policy reference for more details.
|
||||
|
||||
* `Tasks` - It's a list of `Task` object, allows adding tasks as
|
||||
part of the group.
|
||||
|
||||
* `Meta` - A key/value map that annotates the task group with opaque metadata.
|
||||
* `Tasks` - A list of `Task` object that are part of the task group.
|
||||
|
||||
### Task
|
||||
|
||||
The `Task` object supports the following keys:
|
||||
|
||||
* `Driver` - Specifies the task driver that should be used to run the
|
||||
task. See the [driver documentation](/docs/drivers/index.html) for what
|
||||
is available. Examples include `docker`, `qemu`, `java`, and `exec`.
|
||||
|
||||
* `User` - Set the user that will run the task. It defaults to the same user
|
||||
the Nomad client is being run as.
|
||||
|
||||
* `Constraints` - This is a list of `Constraint` objects. See the constraint
|
||||
* `Artifacts` - `Artifacts` is a list of `Artifact` objects which define
|
||||
artifacts to be downloaded before the task is run. See the artifacts
|
||||
reference for more details.
|
||||
|
||||
* `Config` - A map of key/value configuration passed into the driver
|
||||
to start the task. The details of configurations are specific to
|
||||
each driver.
|
||||
|
||||
* `Services` - Nomad integrates with Consul for service discovery. A service
|
||||
block represents a routable and discoverable service on the network. Nomad
|
||||
automatically registers when a task is started and de-registers it when the
|
||||
task transitions to the dead state. [Click
|
||||
here](/docs/jobspec/servicediscovery.html) to learn more about services.
|
||||
* `Constraints` - This is a list of `Constraint` objects. See the constraint
|
||||
reference for more details.
|
||||
|
||||
* `Driver` - Specifies the task driver that should be used to run the
|
||||
task. See the [driver documentation](/docs/drivers/index.html) for what
|
||||
is available. Examples include `docker`, `qemu`, `java`, and `exec`.
|
||||
|
||||
* `Env` - A map of key/value representing environment variables that
|
||||
will be passed along to the running process. Nomad variables are
|
||||
interpreted when set in the environment variable values. See the table of
|
||||
interpreted variables [here](/docs/jobspec/interpreted.html).
|
||||
|
||||
For example the below environment map will be reinterpreted:
|
||||
|
||||
```
|
||||
"Env": {
|
||||
"NODE_CLASS" : "${nomad.class}"
|
||||
}
|
||||
```
|
||||
|
||||
* `KillTimeout` - `KillTimeout` is a time duration in nanoseconds. It can be
|
||||
used to configure the time between signaling a task it will be killed and
|
||||
actually killing it. Drivers first sends a task the `SIGINT` signal and then
|
||||
sends `SIGTERM` if the task doesn't die after the `KillTimeout` duration has
|
||||
elapsed.
|
||||
|
||||
* `LogConfig` - This allows configuring log rotation for the `stdout` and `stderr`
|
||||
buffers of a Task. See the log rotation reference below for more details.
|
||||
|
||||
* `Meta` - Annotates the task group with opaque metadata.
|
||||
|
||||
* `Name` - The name of the task. This field is required.
|
||||
|
||||
* `Resources` - Provides the resource requirements of the task.
|
||||
See the resources reference for more details.
|
||||
|
||||
* `Services` - `Services` is a list of `Service` objects. Nomad integrates with
|
||||
Consul for service discovery. A `Service` object represents a routable and
|
||||
discoverable service on the network. Nomad automatically registers when a task
|
||||
is started and de-registers it when the task transitions to the dead state.
|
||||
[Click here](/docs/jobspec/servicediscovery.html) to learn more about
|
||||
services. Below is the fields in the `Service` object:
|
||||
|
||||
* `Name`: Nomad automatically determines the name of a Task. By default the
|
||||
name of a service is `$(job-name)-$(task-group)-$(task-name)`. Users can
|
||||
@@ -296,16 +328,16 @@ The `Task` object supports the following keys:
|
||||
limited to alphanumeric and hyphen characters (i.e. `[a-z0-9\-]`), and be
|
||||
less than 64 characters in length.
|
||||
|
||||
* `Tags`: A list of tags associated with this Service. String interpolation
|
||||
is supported in tags.
|
||||
* `Tags`: A list of string tags associated with this Service. String
|
||||
interpolation is supported in tags.
|
||||
|
||||
* `PortLabel`: `PortLabel` is optional and is used to associate the port
|
||||
with the service. If specified, the port label must match one defined in
|
||||
the resources block. This could be a label to either a dynamic or a
|
||||
static port. If an incorrect port label is specified, Nomad doesn't
|
||||
register the IP:Port with Consul.
|
||||
* `PortLabel`: `PortLabel` is an optional string and is used to associate
|
||||
the port with the service. If specified, the port label must match one
|
||||
defined in the resources block. This could be a label to either a
|
||||
dynamic or a static port. If an incorrect port label is specified, Nomad
|
||||
doesn't register the IP:Port with Consul.
|
||||
|
||||
* `Checks`: `Checks` is an array of check objects.A check object defines a
|
||||
* `Checks`: `Checks` is an array of check objects. A check object defines a
|
||||
health check associated with the service. Nomad supports the `script`,
|
||||
`http` and `tcp` Consul Checks. Script checks are not supported for the
|
||||
qemu driver since the Nomad client doesn't have access to the file system
|
||||
@@ -337,36 +369,8 @@ The `Task` object supports the following keys:
|
||||
checks.
|
||||
|
||||
|
||||
* `Env` - A map of key/value representing environment variables that
|
||||
will be passed along to the running process. Nomad variables are
|
||||
interpreted when set in the environment variable values. See the table of
|
||||
interpreted variables [here](/docs/jobspec/interpreted.html).
|
||||
|
||||
For example the below environment map will be reinterpreted:
|
||||
|
||||
```
|
||||
"Env": {
|
||||
"NODE_CLASS" : "${nomad.class}"
|
||||
}
|
||||
```
|
||||
|
||||
* `Resources` - Provides the resource requirements of the task.
|
||||
See the resources reference for more details.
|
||||
|
||||
* `Meta` - Annotates the task group with opaque metadata.
|
||||
|
||||
* `KillTimeout` - `KillTimeout` is a time duration in nanoseconds. It can be
|
||||
used to configure the time between signaling a task it will be killed and
|
||||
actually killing it. Drivers first sends a task the `SIGINT` signal and then
|
||||
sends `SIGTERM` if the task doesn't die after the `KillTimeout` duration has
|
||||
elapsed.
|
||||
|
||||
* `LogConfig` - This allows configuring log rotation for the `stdout` and `stderr`
|
||||
buffers of a Task. See the log rotation reference below for more details.
|
||||
|
||||
* `Artifacts` - `Artifacts` is a list of `Artifact` objects which define
|
||||
artifacts to be downloaded before the task is run. See the artifacts
|
||||
reference for more details.
|
||||
* `User` - Set the user that will run the task. It defaults to the same user
|
||||
the Nomad client is being run as.
|
||||
|
||||
### Resources
|
||||
|
||||
@@ -386,9 +390,9 @@ The Network object supports the following keys:
|
||||
|
||||
* `MBits` - The number of MBits in bandwidth required.
|
||||
|
||||
Nomad can allocate two types of ports to a task - Dynamic and Static ports. A
|
||||
network object allows the user to specify a list of `DynamicPorts` and
|
||||
`StaticPorts`. Each object supports the following attributes:
|
||||
Nomad can allocate two types of ports to a task - Dynamic and Static/Reserved
|
||||
ports. A network object allows the user to specify a list of `DynamicPorts` and
|
||||
`ReservedPorts`. Each object supports the following attributes:
|
||||
|
||||
* `Value` - The port number for static ports. If the port is dynamic, then this
|
||||
attribute is ignored.
|
||||
@@ -455,7 +459,7 @@ The `LogConfig` object configures the log rotation policy for a task's `stdout`
|
||||
* `MaxFiles` - The maximum number of rotated files Nomad will retain for
|
||||
`stdout` and `stderr`, each tracked individually.
|
||||
|
||||
* `MaxFileSize` - The size of each rotated file. The size is specified in
|
||||
* `MaxFileSizeMB` - The size of each rotated file. The size is specified in
|
||||
`MB`.
|
||||
|
||||
If the amount of disk resource requested for the task is less than the total
|
||||
@@ -513,13 +517,15 @@ The `Artifact` object supports the following keys:
|
||||
An example of downloading and unzipping an archive is as simple as:
|
||||
|
||||
```
|
||||
"Artifacts": {
|
||||
# The archive will be extracted before the task is run, making
|
||||
# it easy to ship configurations with your binary.
|
||||
"GetterSource": "https://example.com/my.zip",
|
||||
"Artifacts": [
|
||||
{
|
||||
# The archive will be extracted before the task is run, making
|
||||
# it easy to ship configurations with your binary.
|
||||
"GetterSource": "https://example.com/my.zip",
|
||||
|
||||
"GetterOptions": {
|
||||
"checksum": "md5:7f4b3e3b4dd5150d4e5aaaa5efada4c3"
|
||||
"GetterOptions": {
|
||||
"checksum": "md5:7f4b3e3b4dd5150d4e5aaaa5efada4c3"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user