vendor: fix docker/docker vendoring (update to 9f28837c1d93
commitc41b006be1updated the version of docker/docker in go.mod, but possibly overlooked that there was still a replace rule present. As a result the version was not actually updated. This patch removes the replace rule, updating docker/docker to 9f28837c1d93 full diff:4634ce647c...9f28837c1dSigned-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
2
vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go
generated
vendored
2
vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go
generated
vendored
@@ -7,8 +7,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/term"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/moby/term"
|
||||
"github.com/morikuni/aec"
|
||||
)
|
||||
|
||||
|
||||
137
vendor/github.com/docker/docker/pkg/mount/flags.go
generated
vendored
137
vendor/github.com/docker/docker/pkg/mount/flags.go
generated
vendored
@@ -1,137 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var flags = map[string]struct {
|
||||
clear bool
|
||||
flag int
|
||||
}{
|
||||
"defaults": {false, 0},
|
||||
"ro": {false, RDONLY},
|
||||
"rw": {true, RDONLY},
|
||||
"suid": {true, NOSUID},
|
||||
"nosuid": {false, NOSUID},
|
||||
"dev": {true, NODEV},
|
||||
"nodev": {false, NODEV},
|
||||
"exec": {true, NOEXEC},
|
||||
"noexec": {false, NOEXEC},
|
||||
"sync": {false, SYNCHRONOUS},
|
||||
"async": {true, SYNCHRONOUS},
|
||||
"dirsync": {false, DIRSYNC},
|
||||
"remount": {false, REMOUNT},
|
||||
"mand": {false, MANDLOCK},
|
||||
"nomand": {true, MANDLOCK},
|
||||
"atime": {true, NOATIME},
|
||||
"noatime": {false, NOATIME},
|
||||
"diratime": {true, NODIRATIME},
|
||||
"nodiratime": {false, NODIRATIME},
|
||||
"bind": {false, BIND},
|
||||
"rbind": {false, RBIND},
|
||||
"unbindable": {false, UNBINDABLE},
|
||||
"runbindable": {false, RUNBINDABLE},
|
||||
"private": {false, PRIVATE},
|
||||
"rprivate": {false, RPRIVATE},
|
||||
"shared": {false, SHARED},
|
||||
"rshared": {false, RSHARED},
|
||||
"slave": {false, SLAVE},
|
||||
"rslave": {false, RSLAVE},
|
||||
"relatime": {false, RELATIME},
|
||||
"norelatime": {true, RELATIME},
|
||||
"strictatime": {false, STRICTATIME},
|
||||
"nostrictatime": {true, STRICTATIME},
|
||||
}
|
||||
|
||||
var validFlags = map[string]bool{
|
||||
"": true,
|
||||
"size": true,
|
||||
"mode": true,
|
||||
"uid": true,
|
||||
"gid": true,
|
||||
"nr_inodes": true,
|
||||
"nr_blocks": true,
|
||||
"mpol": true,
|
||||
}
|
||||
|
||||
var propagationFlags = map[string]bool{
|
||||
"bind": true,
|
||||
"rbind": true,
|
||||
"unbindable": true,
|
||||
"runbindable": true,
|
||||
"private": true,
|
||||
"rprivate": true,
|
||||
"shared": true,
|
||||
"rshared": true,
|
||||
"slave": true,
|
||||
"rslave": true,
|
||||
}
|
||||
|
||||
// MergeTmpfsOptions merge mount options to make sure there is no duplicate.
|
||||
func MergeTmpfsOptions(options []string) ([]string, error) {
|
||||
// We use collisions maps to remove duplicates.
|
||||
// For flag, the key is the flag value (the key for propagation flag is -1)
|
||||
// For data=value, the key is the data
|
||||
flagCollisions := map[int]bool{}
|
||||
dataCollisions := map[string]bool{}
|
||||
|
||||
var newOptions []string
|
||||
// We process in reverse order
|
||||
for i := len(options) - 1; i >= 0; i-- {
|
||||
option := options[i]
|
||||
if option == "defaults" {
|
||||
continue
|
||||
}
|
||||
if f, ok := flags[option]; ok && f.flag != 0 {
|
||||
// There is only one propagation mode
|
||||
key := f.flag
|
||||
if propagationFlags[option] {
|
||||
key = -1
|
||||
}
|
||||
// Check to see if there is collision for flag
|
||||
if !flagCollisions[key] {
|
||||
// We prepend the option and add to collision map
|
||||
newOptions = append([]string{option}, newOptions...)
|
||||
flagCollisions[key] = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
opt := strings.SplitN(option, "=", 2)
|
||||
if len(opt) != 2 || !validFlags[opt[0]] {
|
||||
return nil, fmt.Errorf("Invalid tmpfs option %q", opt)
|
||||
}
|
||||
if !dataCollisions[opt[0]] {
|
||||
// We prepend the option and add to collision map
|
||||
newOptions = append([]string{option}, newOptions...)
|
||||
dataCollisions[opt[0]] = true
|
||||
}
|
||||
}
|
||||
|
||||
return newOptions, nil
|
||||
}
|
||||
|
||||
// Parse fstab type mount options into mount() flags
|
||||
// and device specific data
|
||||
func parseOptions(options string) (int, string) {
|
||||
var (
|
||||
flag int
|
||||
data []string
|
||||
)
|
||||
|
||||
for _, o := range strings.Split(options, ",") {
|
||||
// If the option does not exist in the flags table or the flag
|
||||
// is not supported on the platform,
|
||||
// then it is a data value for a specific fs type
|
||||
if f, exists := flags[o]; exists && f.flag != 0 {
|
||||
if f.clear {
|
||||
flag &= ^f.flag
|
||||
} else {
|
||||
flag |= f.flag
|
||||
}
|
||||
} else {
|
||||
data = append(data, o)
|
||||
}
|
||||
}
|
||||
return flag, strings.Join(data, ",")
|
||||
}
|
||||
49
vendor/github.com/docker/docker/pkg/mount/flags_freebsd.go
generated
vendored
49
vendor/github.com/docker/docker/pkg/mount/flags_freebsd.go
generated
vendored
@@ -1,49 +0,0 @@
|
||||
// +build freebsd,cgo
|
||||
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
/*
|
||||
#include <sys/mount.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
// RDONLY will mount the filesystem as read-only.
|
||||
RDONLY = C.MNT_RDONLY
|
||||
|
||||
// NOSUID will not allow set-user-identifier or set-group-identifier bits to
|
||||
// take effect.
|
||||
NOSUID = C.MNT_NOSUID
|
||||
|
||||
// NOEXEC will not allow execution of any binaries on the mounted file system.
|
||||
NOEXEC = C.MNT_NOEXEC
|
||||
|
||||
// SYNCHRONOUS will allow any I/O to the file system to be done synchronously.
|
||||
SYNCHRONOUS = C.MNT_SYNCHRONOUS
|
||||
|
||||
// NOATIME will not update the file access time when reading from a file.
|
||||
NOATIME = C.MNT_NOATIME
|
||||
)
|
||||
|
||||
// These flags are unsupported.
|
||||
const (
|
||||
BIND = 0
|
||||
DIRSYNC = 0
|
||||
MANDLOCK = 0
|
||||
NODEV = 0
|
||||
NODIRATIME = 0
|
||||
UNBINDABLE = 0
|
||||
RUNBINDABLE = 0
|
||||
PRIVATE = 0
|
||||
RPRIVATE = 0
|
||||
SHARED = 0
|
||||
RSHARED = 0
|
||||
SLAVE = 0
|
||||
RSLAVE = 0
|
||||
RBIND = 0
|
||||
RELATIVE = 0
|
||||
RELATIME = 0
|
||||
REMOUNT = 0
|
||||
STRICTATIME = 0
|
||||
mntDetach = 0
|
||||
)
|
||||
87
vendor/github.com/docker/docker/pkg/mount/flags_linux.go
generated
vendored
87
vendor/github.com/docker/docker/pkg/mount/flags_linux.go
generated
vendored
@@ -1,87 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// RDONLY will mount the file system read-only.
|
||||
RDONLY = unix.MS_RDONLY
|
||||
|
||||
// NOSUID will not allow set-user-identifier or set-group-identifier bits to
|
||||
// take effect.
|
||||
NOSUID = unix.MS_NOSUID
|
||||
|
||||
// NODEV will not interpret character or block special devices on the file
|
||||
// system.
|
||||
NODEV = unix.MS_NODEV
|
||||
|
||||
// NOEXEC will not allow execution of any binaries on the mounted file system.
|
||||
NOEXEC = unix.MS_NOEXEC
|
||||
|
||||
// SYNCHRONOUS will allow I/O to the file system to be done synchronously.
|
||||
SYNCHRONOUS = unix.MS_SYNCHRONOUS
|
||||
|
||||
// DIRSYNC will force all directory updates within the file system to be done
|
||||
// synchronously. This affects the following system calls: create, link,
|
||||
// unlink, symlink, mkdir, rmdir, mknod and rename.
|
||||
DIRSYNC = unix.MS_DIRSYNC
|
||||
|
||||
// REMOUNT will attempt to remount an already-mounted file system. This is
|
||||
// commonly used to change the mount flags for a file system, especially to
|
||||
// make a readonly file system writeable. It does not change device or mount
|
||||
// point.
|
||||
REMOUNT = unix.MS_REMOUNT
|
||||
|
||||
// MANDLOCK will force mandatory locks on a filesystem.
|
||||
MANDLOCK = unix.MS_MANDLOCK
|
||||
|
||||
// NOATIME will not update the file access time when reading from a file.
|
||||
NOATIME = unix.MS_NOATIME
|
||||
|
||||
// NODIRATIME will not update the directory access time.
|
||||
NODIRATIME = unix.MS_NODIRATIME
|
||||
|
||||
// BIND remounts a subtree somewhere else.
|
||||
BIND = unix.MS_BIND
|
||||
|
||||
// RBIND remounts a subtree and all possible submounts somewhere else.
|
||||
RBIND = unix.MS_BIND | unix.MS_REC
|
||||
|
||||
// UNBINDABLE creates a mount which cannot be cloned through a bind operation.
|
||||
UNBINDABLE = unix.MS_UNBINDABLE
|
||||
|
||||
// RUNBINDABLE marks the entire mount tree as UNBINDABLE.
|
||||
RUNBINDABLE = unix.MS_UNBINDABLE | unix.MS_REC
|
||||
|
||||
// PRIVATE creates a mount which carries no propagation abilities.
|
||||
PRIVATE = unix.MS_PRIVATE
|
||||
|
||||
// RPRIVATE marks the entire mount tree as PRIVATE.
|
||||
RPRIVATE = unix.MS_PRIVATE | unix.MS_REC
|
||||
|
||||
// SLAVE creates a mount which receives propagation from its master, but not
|
||||
// vice versa.
|
||||
SLAVE = unix.MS_SLAVE
|
||||
|
||||
// RSLAVE marks the entire mount tree as SLAVE.
|
||||
RSLAVE = unix.MS_SLAVE | unix.MS_REC
|
||||
|
||||
// SHARED creates a mount which provides the ability to create mirrors of
|
||||
// that mount such that mounts and unmounts within any of the mirrors
|
||||
// propagate to the other mirrors.
|
||||
SHARED = unix.MS_SHARED
|
||||
|
||||
// RSHARED marks the entire mount tree as SHARED.
|
||||
RSHARED = unix.MS_SHARED | unix.MS_REC
|
||||
|
||||
// RELATIME updates inode access times relative to modify or change time.
|
||||
RELATIME = unix.MS_RELATIME
|
||||
|
||||
// STRICTATIME allows to explicitly request full atime updates. This makes
|
||||
// it possible for the kernel to default to relatime or noatime but still
|
||||
// allow userspace to override it.
|
||||
STRICTATIME = unix.MS_STRICTATIME
|
||||
|
||||
mntDetach = unix.MNT_DETACH
|
||||
)
|
||||
31
vendor/github.com/docker/docker/pkg/mount/flags_unsupported.go
generated
vendored
31
vendor/github.com/docker/docker/pkg/mount/flags_unsupported.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
// +build !linux,!freebsd freebsd,!cgo
|
||||
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
// These flags are unsupported.
|
||||
const (
|
||||
BIND = 0
|
||||
DIRSYNC = 0
|
||||
MANDLOCK = 0
|
||||
NOATIME = 0
|
||||
NODEV = 0
|
||||
NODIRATIME = 0
|
||||
NOEXEC = 0
|
||||
NOSUID = 0
|
||||
UNBINDABLE = 0
|
||||
RUNBINDABLE = 0
|
||||
PRIVATE = 0
|
||||
RPRIVATE = 0
|
||||
SHARED = 0
|
||||
RSHARED = 0
|
||||
SLAVE = 0
|
||||
RSLAVE = 0
|
||||
RBIND = 0
|
||||
RELATIME = 0
|
||||
RELATIVE = 0
|
||||
REMOUNT = 0
|
||||
STRICTATIME = 0
|
||||
SYNCHRONOUS = 0
|
||||
RDONLY = 0
|
||||
mntDetach = 0
|
||||
)
|
||||
159
vendor/github.com/docker/docker/pkg/mount/mount.go
generated
vendored
159
vendor/github.com/docker/docker/pkg/mount/mount.go
generated
vendored
@@ -1,159 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// mountError records an error from mount or unmount operation
|
||||
type mountError struct {
|
||||
op string
|
||||
source, target string
|
||||
flags uintptr
|
||||
data string
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *mountError) Error() string {
|
||||
out := e.op + " "
|
||||
|
||||
if e.source != "" {
|
||||
out += e.source + ":" + e.target
|
||||
} else {
|
||||
out += e.target
|
||||
}
|
||||
|
||||
if e.flags != uintptr(0) {
|
||||
out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16)
|
||||
}
|
||||
if e.data != "" {
|
||||
out += ", data: " + e.data
|
||||
}
|
||||
|
||||
out += ": " + e.err.Error()
|
||||
return out
|
||||
}
|
||||
|
||||
// Cause returns the underlying cause of the error
|
||||
func (e *mountError) Cause() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
// FilterFunc is a type defining a callback function
|
||||
// to filter out unwanted entries. It takes a pointer
|
||||
// to an Info struct (not fully populated, currently
|
||||
// only Mountpoint is filled in), and returns two booleans:
|
||||
// - skip: true if the entry should be skipped
|
||||
// - stop: true if parsing should be stopped after the entry
|
||||
type FilterFunc func(*Info) (skip, stop bool)
|
||||
|
||||
// PrefixFilter discards all entries whose mount points
|
||||
// do not start with a prefix specified
|
||||
func PrefixFilter(prefix string) FilterFunc {
|
||||
return func(m *Info) (bool, bool) {
|
||||
skip := !strings.HasPrefix(m.Mountpoint, prefix)
|
||||
return skip, false
|
||||
}
|
||||
}
|
||||
|
||||
// SingleEntryFilter looks for a specific entry
|
||||
func SingleEntryFilter(mp string) FilterFunc {
|
||||
return func(m *Info) (bool, bool) {
|
||||
if m.Mountpoint == mp {
|
||||
return false, true // don't skip, stop now
|
||||
}
|
||||
return true, false // skip, keep going
|
||||
}
|
||||
}
|
||||
|
||||
// ParentsFilter returns all entries whose mount points
|
||||
// can be parents of a path specified, discarding others.
|
||||
// For example, given `/var/lib/docker/something`, entries
|
||||
// like `/var/lib/docker`, `/var` and `/` are returned.
|
||||
func ParentsFilter(path string) FilterFunc {
|
||||
return func(m *Info) (bool, bool) {
|
||||
skip := !strings.HasPrefix(path, m.Mountpoint)
|
||||
return skip, false
|
||||
}
|
||||
}
|
||||
|
||||
// GetMounts retrieves a list of mounts for the current running process,
|
||||
// with an optional filter applied (use nil for no filter).
|
||||
func GetMounts(f FilterFunc) ([]*Info, error) {
|
||||
return parseMountTable(f)
|
||||
}
|
||||
|
||||
// Mounted determines if a specified mountpoint has been mounted.
|
||||
// On Linux it looks at /proc/self/mountinfo.
|
||||
func Mounted(mountpoint string) (bool, error) {
|
||||
entries, err := GetMounts(SingleEntryFilter(mountpoint))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return len(entries) > 0, nil
|
||||
}
|
||||
|
||||
// Mount will mount filesystem according to the specified configuration, on the
|
||||
// condition that the target path is *not* already mounted. Options must be
|
||||
// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
|
||||
// flags.go for supported option flags.
|
||||
func Mount(device, target, mType, options string) error {
|
||||
flag, data := parseOptions(options)
|
||||
if flag&REMOUNT != REMOUNT {
|
||||
if mounted, err := Mounted(target); err != nil || mounted {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return mount(device, target, mType, uintptr(flag), data)
|
||||
}
|
||||
|
||||
// ForceMount will mount a filesystem according to the specified configuration,
|
||||
// *regardless* if the target path is not already mounted. Options must be
|
||||
// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
|
||||
// flags.go for supported option flags.
|
||||
func ForceMount(device, target, mType, options string) error {
|
||||
flag, data := parseOptions(options)
|
||||
return mount(device, target, mType, uintptr(flag), data)
|
||||
}
|
||||
|
||||
// Unmount lazily unmounts a filesystem on supported platforms, otherwise
|
||||
// does a normal unmount.
|
||||
func Unmount(target string) error {
|
||||
return unmount(target, mntDetach)
|
||||
}
|
||||
|
||||
// RecursiveUnmount unmounts the target and all mounts underneath, starting with
|
||||
// the deepsest mount first.
|
||||
func RecursiveUnmount(target string) error {
|
||||
mounts, err := parseMountTable(PrefixFilter(target))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make the deepest mount be first
|
||||
sort.Slice(mounts, func(i, j int) bool {
|
||||
return len(mounts[i].Mountpoint) > len(mounts[j].Mountpoint)
|
||||
})
|
||||
|
||||
for i, m := range mounts {
|
||||
logrus.Debugf("Trying to unmount %s", m.Mountpoint)
|
||||
err = unmount(m.Mountpoint, mntDetach)
|
||||
if err != nil {
|
||||
if i == len(mounts)-1 { // last mount
|
||||
if mounted, e := Mounted(m.Mountpoint); e != nil || mounted {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem
|
||||
logrus.WithError(err).Warnf("Failed to unmount submount %s", m.Mountpoint)
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf("Unmounted %s", m.Mountpoint)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
59
vendor/github.com/docker/docker/pkg/mount/mounter_freebsd.go
generated
vendored
59
vendor/github.com/docker/docker/pkg/mount/mounter_freebsd.go
generated
vendored
@@ -1,59 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
/*
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/_iovec.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func allocateIOVecs(options []string) []C.struct_iovec {
|
||||
out := make([]C.struct_iovec, len(options))
|
||||
for i, option := range options {
|
||||
out[i].iov_base = unsafe.Pointer(C.CString(option))
|
||||
out[i].iov_len = C.size_t(len(option) + 1)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func mount(device, target, mType string, flag uintptr, data string) error {
|
||||
isNullFS := false
|
||||
|
||||
xs := strings.Split(data, ",")
|
||||
for _, x := range xs {
|
||||
if x == "bind" {
|
||||
isNullFS = true
|
||||
}
|
||||
}
|
||||
|
||||
options := []string{"fspath", target}
|
||||
if isNullFS {
|
||||
options = append(options, "fstype", "nullfs", "target", device)
|
||||
} else {
|
||||
options = append(options, "fstype", mType, "from", device)
|
||||
}
|
||||
rawOptions := allocateIOVecs(options)
|
||||
for _, rawOption := range rawOptions {
|
||||
defer C.free(rawOption.iov_base)
|
||||
}
|
||||
|
||||
if errno := C.nmount(&rawOptions[0], C.uint(len(options)), C.int(flag)); errno != 0 {
|
||||
return &mountError{
|
||||
op: "mount",
|
||||
source: device,
|
||||
target: target,
|
||||
flags: flag,
|
||||
err: syscall.Errno(errno),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
73
vendor/github.com/docker/docker/pkg/mount/mounter_linux.go
generated
vendored
73
vendor/github.com/docker/docker/pkg/mount/mounter_linux.go
generated
vendored
@@ -1,73 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// ptypes is the set propagation types.
|
||||
ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE
|
||||
|
||||
// pflags is the full set valid flags for a change propagation call.
|
||||
pflags = ptypes | unix.MS_REC | unix.MS_SILENT
|
||||
|
||||
// broflags is the combination of bind and read only
|
||||
broflags = unix.MS_BIND | unix.MS_RDONLY
|
||||
)
|
||||
|
||||
// isremount returns true if either device name or flags identify a remount request, false otherwise.
|
||||
func isremount(device string, flags uintptr) bool {
|
||||
switch {
|
||||
// We treat device "" and "none" as a remount request to provide compatibility with
|
||||
// requests that don't explicitly set MS_REMOUNT such as those manipulating bind mounts.
|
||||
case flags&unix.MS_REMOUNT != 0, device == "", device == "none":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func mount(device, target, mType string, flags uintptr, data string) error {
|
||||
oflags := flags &^ ptypes
|
||||
if !isremount(device, flags) || data != "" {
|
||||
// Initial call applying all non-propagation flags for mount
|
||||
// or remount with changed data
|
||||
if err := unix.Mount(device, target, mType, oflags, data); err != nil {
|
||||
return &mountError{
|
||||
op: "mount",
|
||||
source: device,
|
||||
target: target,
|
||||
flags: oflags,
|
||||
data: data,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if flags&ptypes != 0 {
|
||||
// Change the propagation type.
|
||||
if err := unix.Mount("", target, "", flags&pflags, ""); err != nil {
|
||||
return &mountError{
|
||||
op: "remount",
|
||||
target: target,
|
||||
flags: flags & pflags,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if oflags&broflags == broflags {
|
||||
// Remount the bind to apply read only.
|
||||
if err := unix.Mount("", target, "", oflags|unix.MS_REMOUNT, ""); err != nil {
|
||||
return &mountError{
|
||||
op: "remount-ro",
|
||||
target: target,
|
||||
flags: oflags | unix.MS_REMOUNT,
|
||||
err: err,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
7
vendor/github.com/docker/docker/pkg/mount/mounter_unsupported.go
generated
vendored
7
vendor/github.com/docker/docker/pkg/mount/mounter_unsupported.go
generated
vendored
@@ -1,7 +0,0 @@
|
||||
// +build !linux,!freebsd freebsd,!cgo
|
||||
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
func mount(device, target, mType string, flag uintptr, data string) error {
|
||||
panic("Not implemented")
|
||||
}
|
||||
40
vendor/github.com/docker/docker/pkg/mount/mountinfo.go
generated
vendored
40
vendor/github.com/docker/docker/pkg/mount/mountinfo.go
generated
vendored
@@ -1,40 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
// Info reveals information about a particular mounted filesystem. This
|
||||
// struct is populated from the content in the /proc/<pid>/mountinfo file.
|
||||
type Info struct {
|
||||
// ID is a unique identifier of the mount (may be reused after umount).
|
||||
ID int
|
||||
|
||||
// Parent indicates the ID of the mount parent (or of self for the top of the
|
||||
// mount tree).
|
||||
Parent int
|
||||
|
||||
// Major indicates one half of the device ID which identifies the device class.
|
||||
Major int
|
||||
|
||||
// Minor indicates one half of the device ID which identifies a specific
|
||||
// instance of device.
|
||||
Minor int
|
||||
|
||||
// Root of the mount within the filesystem.
|
||||
Root string
|
||||
|
||||
// Mountpoint indicates the mount point relative to the process's root.
|
||||
Mountpoint string
|
||||
|
||||
// Opts represents mount-specific options.
|
||||
Opts string
|
||||
|
||||
// Optional represents optional fields.
|
||||
Optional string
|
||||
|
||||
// Fstype indicates the type of filesystem, such as EXT3.
|
||||
Fstype string
|
||||
|
||||
// Source indicates filesystem specific information or "none".
|
||||
Source string
|
||||
|
||||
// VfsOpts represents per super block options.
|
||||
VfsOpts string
|
||||
}
|
||||
54
vendor/github.com/docker/docker/pkg/mount/mountinfo_freebsd.go
generated
vendored
54
vendor/github.com/docker/docker/pkg/mount/mountinfo_freebsd.go
generated
vendored
@@ -1,54 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
/*
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// parseMountTable returns information about mounted filesystems
|
||||
func parseMountTable(filter FilterFunc) ([]*Info, error) {
|
||||
var rawEntries *C.struct_statfs
|
||||
|
||||
count := int(C.getmntinfo(&rawEntries, C.MNT_WAIT))
|
||||
if count == 0 {
|
||||
return nil, fmt.Errorf("Failed to call getmntinfo")
|
||||
}
|
||||
|
||||
var entries []C.struct_statfs
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(&entries))
|
||||
header.Cap = count
|
||||
header.Len = count
|
||||
header.Data = uintptr(unsafe.Pointer(rawEntries))
|
||||
|
||||
var out []*Info
|
||||
for _, entry := range entries {
|
||||
var mountinfo Info
|
||||
var skip, stop bool
|
||||
mountinfo.Mountpoint = C.GoString(&entry.f_mntonname[0])
|
||||
|
||||
if filter != nil {
|
||||
// filter out entries we're not interested in
|
||||
skip, stop = filter(&mountinfo)
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
mountinfo.Source = C.GoString(&entry.f_mntfromname[0])
|
||||
mountinfo.Fstype = C.GoString(&entry.f_fstypename[0])
|
||||
|
||||
out = append(out, &mountinfo)
|
||||
if stop {
|
||||
break
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
143
vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go
generated
vendored
143
vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go
generated
vendored
@@ -1,143 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) {
|
||||
s := bufio.NewScanner(r)
|
||||
out := []*Info{}
|
||||
var err error
|
||||
for s.Scan() {
|
||||
if err = s.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
/*
|
||||
See http://man7.org/linux/man-pages/man5/proc.5.html
|
||||
|
||||
36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
|
||||
(1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
|
||||
|
||||
(1) mount ID: unique identifier of the mount (may be reused after umount)
|
||||
(2) parent ID: ID of parent (or of self for the top of the mount tree)
|
||||
(3) major:minor: value of st_dev for files on filesystem
|
||||
(4) root: root of the mount within the filesystem
|
||||
(5) mount point: mount point relative to the process's root
|
||||
(6) mount options: per mount options
|
||||
(7) optional fields: zero or more fields of the form "tag[:value]"
|
||||
(8) separator: marks the end of the optional fields
|
||||
(9) filesystem type: name of filesystem of the form "type[.subtype]"
|
||||
(10) mount source: filesystem specific information or "none"
|
||||
(11) super options: per super block options
|
||||
*/
|
||||
|
||||
text := s.Text()
|
||||
fields := strings.Split(text, " ")
|
||||
numFields := len(fields)
|
||||
if numFields < 10 {
|
||||
// should be at least 10 fields
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: not enough fields (%d)", text, numFields)
|
||||
}
|
||||
|
||||
p := &Info{}
|
||||
// ignore any numbers parsing errors, as there should not be any
|
||||
p.ID, _ = strconv.Atoi(fields[0])
|
||||
p.Parent, _ = strconv.Atoi(fields[1])
|
||||
mm := strings.Split(fields[2], ":")
|
||||
if len(mm) != 2 {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: unexpected minor:major pair %s", text, mm)
|
||||
}
|
||||
p.Major, _ = strconv.Atoi(mm[0])
|
||||
p.Minor, _ = strconv.Atoi(mm[1])
|
||||
|
||||
p.Root, err = strconv.Unquote(`"` + fields[3] + `"`)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Parsing '%s' failed: unable to unquote root field", fields[3])
|
||||
}
|
||||
|
||||
p.Mountpoint, err = strconv.Unquote(`"` + fields[4] + `"`)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Parsing '%s' failed: unable to unquote mount point field", fields[4])
|
||||
}
|
||||
p.Opts = fields[5]
|
||||
|
||||
var skip, stop bool
|
||||
if filter != nil {
|
||||
// filter out entries we're not interested in
|
||||
skip, stop = filter(p)
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// one or more optional fields, when a separator (-)
|
||||
i := 6
|
||||
for ; i < numFields && fields[i] != "-"; i++ {
|
||||
switch i {
|
||||
case 6:
|
||||
p.Optional = fields[6]
|
||||
default:
|
||||
/* NOTE there might be more optional fields before the such as
|
||||
fields[7]...fields[N] (where N < sepIndex), although
|
||||
as of Linux kernel 4.15 the only known ones are
|
||||
mount propagation flags in fields[6]. The correct
|
||||
behavior is to ignore any unknown optional fields.
|
||||
*/
|
||||
}
|
||||
}
|
||||
if i == numFields {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: missing separator ('-')", text)
|
||||
}
|
||||
|
||||
// There should be 3 fields after the separator...
|
||||
if i+4 > numFields {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: not enough fields after a separator", text)
|
||||
}
|
||||
// ... but in Linux <= 3.9 mounting a cifs with spaces in a share name
|
||||
// (like "//serv/My Documents") _may_ end up having a space in the last field
|
||||
// of mountinfo (like "unc=//serv/My Documents"). Since kernel 3.10-rc1, cifs
|
||||
// option unc= is ignored, so a space should not appear. In here we ignore
|
||||
// those "extra" fields caused by extra spaces.
|
||||
p.Fstype = fields[i+1]
|
||||
p.Source = fields[i+2]
|
||||
p.VfsOpts = fields[i+3]
|
||||
|
||||
out = append(out, p)
|
||||
if stop {
|
||||
break
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Parse /proc/self/mountinfo because comparing Dev and ino does not work from
|
||||
// bind mounts
|
||||
func parseMountTable(filter FilterFunc) ([]*Info, error) {
|
||||
f, err := os.Open("/proc/self/mountinfo")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return parseInfoFile(f, filter)
|
||||
}
|
||||
|
||||
// PidMountInfo collects the mounts for a specific process ID. If the process
|
||||
// ID is unknown, it is better to use `GetMounts` which will inspect
|
||||
// "/proc/self/mountinfo" instead.
|
||||
func PidMountInfo(pid int) ([]*Info, error) {
|
||||
f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return parseInfoFile(f, nil)
|
||||
}
|
||||
12
vendor/github.com/docker/docker/pkg/mount/mountinfo_unsupported.go
generated
vendored
12
vendor/github.com/docker/docker/pkg/mount/mountinfo_unsupported.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
// +build !windows,!linux,!freebsd freebsd,!cgo
|
||||
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func parseMountTable(f FilterFunc) ([]*Info, error) {
|
||||
return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
6
vendor/github.com/docker/docker/pkg/mount/mountinfo_windows.go
generated
vendored
6
vendor/github.com/docker/docker/pkg/mount/mountinfo_windows.go
generated
vendored
@@ -1,6 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
func parseMountTable(f FilterFunc) ([]*Info, error) {
|
||||
// Do NOT return an error!
|
||||
return nil, nil
|
||||
}
|
||||
71
vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go
generated
vendored
71
vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go
generated
vendored
@@ -1,71 +0,0 @@
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
// MakeShared ensures a mounted filesystem has the SHARED mount option enabled.
|
||||
// See the supported options in flags.go for further reference.
|
||||
func MakeShared(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, SHARED)
|
||||
}
|
||||
|
||||
// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled.
|
||||
// See the supported options in flags.go for further reference.
|
||||
func MakeRShared(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, RSHARED)
|
||||
}
|
||||
|
||||
// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled.
|
||||
// See the supported options in flags.go for further reference.
|
||||
func MakePrivate(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, PRIVATE)
|
||||
}
|
||||
|
||||
// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option
|
||||
// enabled. See the supported options in flags.go for further reference.
|
||||
func MakeRPrivate(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, RPRIVATE)
|
||||
}
|
||||
|
||||
// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled.
|
||||
// See the supported options in flags.go for further reference.
|
||||
func MakeSlave(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, SLAVE)
|
||||
}
|
||||
|
||||
// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled.
|
||||
// See the supported options in flags.go for further reference.
|
||||
func MakeRSlave(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, RSLAVE)
|
||||
}
|
||||
|
||||
// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option
|
||||
// enabled. See the supported options in flags.go for further reference.
|
||||
func MakeUnbindable(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, UNBINDABLE)
|
||||
}
|
||||
|
||||
// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount
|
||||
// option enabled. See the supported options in flags.go for further reference.
|
||||
func MakeRUnbindable(mountPoint string) error {
|
||||
return ensureMountedAs(mountPoint, RUNBINDABLE)
|
||||
}
|
||||
|
||||
// MakeMount ensures that the file or directory given is a mount point,
|
||||
// bind mounting it to itself it case it is not.
|
||||
func MakeMount(mnt string) error {
|
||||
mounted, err := Mounted(mnt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if mounted {
|
||||
return nil
|
||||
}
|
||||
|
||||
return mount(mnt, mnt, "none", uintptr(BIND), "")
|
||||
}
|
||||
|
||||
func ensureMountedAs(mnt string, flags int) error {
|
||||
if err := MakeMount(mnt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return mount("", mnt, "none", uintptr(flags), "")
|
||||
}
|
||||
22
vendor/github.com/docker/docker/pkg/mount/unmount_unix.go
generated
vendored
22
vendor/github.com/docker/docker/pkg/mount/unmount_unix.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
func unmount(target string, flags int) error {
|
||||
err := unix.Unmount(target, flags)
|
||||
if err == nil || err == unix.EINVAL {
|
||||
// Ignore "not mounted" error here. Note the same error
|
||||
// can be returned if flags are invalid, so this code
|
||||
// assumes that the flags value is always correct.
|
||||
return nil
|
||||
}
|
||||
|
||||
return &mountError{
|
||||
op: "umount",
|
||||
target: target,
|
||||
flags: uintptr(flags),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
7
vendor/github.com/docker/docker/pkg/mount/unmount_unsupported.go
generated
vendored
7
vendor/github.com/docker/docker/pkg/mount/unmount_unsupported.go
generated
vendored
@@ -1,7 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
package mount // import "github.com/docker/docker/pkg/mount"
|
||||
|
||||
func unmount(target string, flag int) error {
|
||||
panic("Not implemented")
|
||||
}
|
||||
4
vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go
generated
vendored
4
vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go
generated
vendored
@@ -497,7 +497,7 @@ var (
|
||||
// Har Gobind Khorana - Indian-American biochemist who shared the 1968 Nobel Prize for Physiology - https://en.wikipedia.org/wiki/Har_Gobind_Khorana
|
||||
"khorana",
|
||||
|
||||
// Jack Kilby invented silicone integrated circuits and gave Silicon Valley its name. - https://en.wikipedia.org/wiki/Jack_Kilby
|
||||
// Jack Kilby invented silicon integrated circuits and gave Silicon Valley its name. - https://en.wikipedia.org/wiki/Jack_Kilby
|
||||
"kilby",
|
||||
|
||||
// Maria Kirch - German astronomer and first woman to discover a comet - https://en.wikipedia.org/wiki/Maria_Margarethe_Kirch
|
||||
@@ -632,7 +632,7 @@ var (
|
||||
// Poppy Northcutt. Poppy Northcutt was the first woman to work as part of NASA’s Mission Control. http://www.businessinsider.com/poppy-northcutt-helped-apollo-astronauts-2014-12?op=1
|
||||
"northcutt",
|
||||
|
||||
// Robert Noyce invented silicone integrated circuits and gave Silicon Valley its name. - https://en.wikipedia.org/wiki/Robert_Noyce
|
||||
// Robert Noyce invented silicon integrated circuits and gave Silicon Valley its name. - https://en.wikipedia.org/wiki/Robert_Noyce
|
||||
"noyce",
|
||||
|
||||
// Panini - Ancient Indian linguist and grammarian from 4th century CE who worked on the world's first formal system - https://en.wikipedia.org/wiki/P%C4%81%E1%B9%87ini#Comparison_with_modern_formal_systems
|
||||
|
||||
8
vendor/github.com/docker/docker/pkg/system/filesys_windows.go
generated
vendored
8
vendor/github.com/docker/docker/pkg/system/filesys_windows.go
generated
vendored
@@ -130,12 +130,10 @@ func mkdirWithACL(name string, sddl string) error {
|
||||
// by the daemon. This SHOULD be treated as absolute from a docker processing
|
||||
// perspective.
|
||||
func IsAbs(path string) bool {
|
||||
if !filepath.IsAbs(path) {
|
||||
if !strings.HasPrefix(path, string(os.PathSeparator)) {
|
||||
return false
|
||||
}
|
||||
if filepath.IsAbs(path) || strings.HasPrefix(path, string(os.PathSeparator)) {
|
||||
return true
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
// The origin of the functions below here are the golang OS and windows packages,
|
||||
|
||||
12
vendor/github.com/docker/docker/pkg/system/init_unix.go
generated
vendored
12
vendor/github.com/docker/docker/pkg/system/init_unix.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package system // import "github.com/docker/docker/pkg/system"
|
||||
|
||||
// InitLCOW does nothing since LCOW is a windows only feature
|
||||
func InitLCOW(experimental bool) {
|
||||
}
|
||||
|
||||
// ContainerdRuntimeSupported returns true if the use of ContainerD runtime is supported.
|
||||
func ContainerdRuntimeSupported(_ bool, _ string) bool {
|
||||
return true
|
||||
}
|
||||
11
vendor/github.com/docker/docker/pkg/system/init_windows.go
generated
vendored
11
vendor/github.com/docker/docker/pkg/system/init_windows.go
generated
vendored
@@ -3,26 +3,15 @@ package system // import "github.com/docker/docker/pkg/system"
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Microsoft/hcsshim/osversion"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
// lcowSupported determines if Linux Containers on Windows are supported.
|
||||
lcowSupported = false
|
||||
|
||||
// containerdRuntimeSupported determines if ContainerD should be the runtime.
|
||||
// As of March 2019, this is an experimental feature.
|
||||
containerdRuntimeSupported = false
|
||||
)
|
||||
|
||||
// InitLCOW sets whether LCOW is supported or not. Requires RS5+
|
||||
func InitLCOW(experimental bool) {
|
||||
if experimental && osversion.Build() >= osversion.RS5 {
|
||||
lcowSupported = true
|
||||
}
|
||||
}
|
||||
|
||||
// InitContainerdRuntime sets whether to use ContainerD for runtime
|
||||
// on Windows. This is an experimental feature still in development, and
|
||||
// also requires an environment variable to be set (so as not to turn the
|
||||
|
||||
44
vendor/github.com/docker/docker/pkg/system/lcow.go
generated
vendored
44
vendor/github.com/docker/docker/pkg/system/lcow.go
generated
vendored
@@ -1,16 +1,44 @@
|
||||
// +build windows,!no_lcow
|
||||
|
||||
package system // import "github.com/docker/docker/pkg/system"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/Microsoft/hcsshim/osversion"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// lcowSupported determines if Linux Containers on Windows are supported.
|
||||
lcowSupported = false
|
||||
)
|
||||
|
||||
// InitLCOW sets whether LCOW is supported or not. Requires RS5+
|
||||
func InitLCOW(experimental bool) {
|
||||
if experimental && osversion.Build() >= osversion.RS5 {
|
||||
lcowSupported = true
|
||||
}
|
||||
}
|
||||
|
||||
func LCOWSupported() bool {
|
||||
return lcowSupported
|
||||
}
|
||||
|
||||
// ValidatePlatform determines if a platform structure is valid.
|
||||
// TODO This is a temporary windows-only function, should be replaced by
|
||||
// comparison of worker capabilities
|
||||
func ValidatePlatform(platform specs.Platform) error {
|
||||
if !IsOSSupported(platform.OS) {
|
||||
return errors.Errorf("unsupported os %s", platform.OS)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsOSSupported determines if an operating system is supported by the host
|
||||
func IsOSSupported(os string) bool {
|
||||
if strings.EqualFold(runtime.GOOS, os) {
|
||||
if strings.EqualFold("windows", os) {
|
||||
return true
|
||||
}
|
||||
if LCOWSupported() && strings.EqualFold(os, "linux") {
|
||||
@@ -18,15 +46,3 @@ func IsOSSupported(os string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidatePlatform determines if a platform structure is valid.
|
||||
// TODO This is a temporary windows-only function, should be replaced by
|
||||
// comparison of worker capabilities
|
||||
func ValidatePlatform(platform specs.Platform) error {
|
||||
if runtime.GOOS == "windows" {
|
||||
if !(platform.OS == runtime.GOOS || (LCOWSupported() && platform.OS == "linux")) {
|
||||
return errors.Errorf("unsupported os %s", platform.OS)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
8
vendor/github.com/docker/docker/pkg/system/lcow_unix.go
generated
vendored
8
vendor/github.com/docker/docker/pkg/system/lcow_unix.go
generated
vendored
@@ -1,8 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package system // import "github.com/docker/docker/pkg/system"
|
||||
|
||||
// LCOWSupported returns true if Linux containers on Windows are supported.
|
||||
func LCOWSupported() bool {
|
||||
return false
|
||||
}
|
||||
28
vendor/github.com/docker/docker/pkg/system/lcow_unsupported.go
generated
vendored
Normal file
28
vendor/github.com/docker/docker/pkg/system/lcow_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// +build !windows windows,no_lcow
|
||||
|
||||
package system // import "github.com/docker/docker/pkg/system"
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// InitLCOW does nothing since LCOW is a windows only feature
|
||||
func InitLCOW(_ bool) {}
|
||||
|
||||
// LCOWSupported returns true if Linux containers on Windows are supported.
|
||||
func LCOWSupported() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidatePlatform determines if a platform structure is valid. This function
|
||||
// is used for LCOW, and is a no-op on non-windows platforms.
|
||||
func ValidatePlatform(_ specs.Platform) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsOSSupported determines if an operating system is supported by the host.
|
||||
func IsOSSupported(os string) bool {
|
||||
return strings.EqualFold(runtime.GOOS, os)
|
||||
}
|
||||
6
vendor/github.com/docker/docker/pkg/system/lcow_windows.go
generated
vendored
6
vendor/github.com/docker/docker/pkg/system/lcow_windows.go
generated
vendored
@@ -1,6 +0,0 @@
|
||||
package system // import "github.com/docker/docker/pkg/system"
|
||||
|
||||
// LCOWSupported returns true if Linux containers on Windows are supported.
|
||||
func LCOWSupported() bool {
|
||||
return lcowSupported
|
||||
}
|
||||
20
vendor/github.com/docker/docker/pkg/system/process_unix.go
generated
vendored
20
vendor/github.com/docker/docker/pkg/system/process_unix.go
generated
vendored
@@ -3,6 +3,9 @@
|
||||
package system // import "github.com/docker/docker/pkg/system"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -22,3 +25,20 @@ func IsProcessAlive(pid int) bool {
|
||||
func KillProcess(pid int) {
|
||||
unix.Kill(pid, unix.SIGKILL)
|
||||
}
|
||||
|
||||
// IsProcessZombie return true if process has a state with "Z"
|
||||
// http://man7.org/linux/man-pages/man5/proc.5.html
|
||||
func IsProcessZombie(pid int) (bool, error) {
|
||||
statPath := fmt.Sprintf("/proc/%d/stat", pid)
|
||||
dataBytes, err := ioutil.ReadFile(statPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
data := string(dataBytes)
|
||||
sdata := strings.SplitN(data, " ", 4)
|
||||
if len(sdata) >= 3 && sdata[2] == "Z" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
2
vendor/github.com/docker/docker/pkg/system/process_windows.go
generated
vendored
2
vendor/github.com/docker/docker/pkg/system/process_windows.go
generated
vendored
@@ -13,6 +13,6 @@ func IsProcessAlive(pid int) bool {
|
||||
func KillProcess(pid int) {
|
||||
p, err := os.FindProcess(pid)
|
||||
if err == nil {
|
||||
p.Kill()
|
||||
_ = p.Kill()
|
||||
}
|
||||
}
|
||||
|
||||
10
vendor/github.com/docker/docker/pkg/system/rm.go
generated
vendored
10
vendor/github.com/docker/docker/pkg/system/rm.go
generated
vendored
@@ -5,7 +5,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/moby/sys/mount"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -63,12 +63,8 @@ func EnsureRemoveAll(dir string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if mounted, _ := mount.Mounted(pe.Path); mounted {
|
||||
if e := mount.Unmount(pe.Path); e != nil {
|
||||
if mounted, _ := mount.Mounted(pe.Path); mounted {
|
||||
return errors.Wrapf(e, "error while removing %s", dir)
|
||||
}
|
||||
}
|
||||
if e := mount.Unmount(pe.Path); e != nil {
|
||||
return errors.Wrapf(e, "error while removing %s", dir)
|
||||
}
|
||||
|
||||
if exitOnErr[pe.Path] == maxRetry {
|
||||
|
||||
6
vendor/github.com/docker/docker/pkg/system/syscall_unix.go
generated
vendored
6
vendor/github.com/docker/docker/pkg/system/syscall_unix.go
generated
vendored
@@ -9,9 +9,3 @@ import "golang.org/x/sys/unix"
|
||||
func Unmount(dest string) error {
|
||||
return unix.Unmount(dest, 0)
|
||||
}
|
||||
|
||||
// CommandLineToArgv should not be used on Unix.
|
||||
// It simply returns commandLine in the only element in the returned array.
|
||||
func CommandLineToArgv(commandLine string) ([]string, error) {
|
||||
return []string{commandLine}, nil
|
||||
}
|
||||
|
||||
25
vendor/github.com/docker/docker/pkg/system/syscall_windows.go
generated
vendored
25
vendor/github.com/docker/docker/pkg/system/syscall_windows.go
generated
vendored
@@ -104,29 +104,6 @@ func Unmount(_ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommandLineToArgv wraps the Windows syscall to turn a commandline into an argument array.
|
||||
func CommandLineToArgv(commandLine string) ([]string, error) {
|
||||
var argc int32
|
||||
|
||||
argsPtr, err := windows.UTF16PtrFromString(commandLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
argv, err := windows.CommandLineToArgv(argsPtr, &argc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(argv))))
|
||||
|
||||
newArgs := make([]string, argc)
|
||||
for i, v := range (*argv)[:argc] {
|
||||
newArgs[i] = windows.UTF16ToString((*v)[:])
|
||||
}
|
||||
|
||||
return newArgs, nil
|
||||
}
|
||||
|
||||
// HasWin32KSupport determines whether containers that depend on win32k can
|
||||
// run on this machine. Win32k is the driver used to implement windowing.
|
||||
func HasWin32KSupport() bool {
|
||||
@@ -136,6 +113,7 @@ func HasWin32KSupport() bool {
|
||||
return ntuserApiset.Load() == nil
|
||||
}
|
||||
|
||||
// Deprecated: use golang.org/x/sys/windows.SetNamedSecurityInfo()
|
||||
func SetNamedSecurityInfo(objectName *uint16, objectType uint32, securityInformation uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *byte, sacl *byte) (result error) {
|
||||
r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfo.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(sidOwner)), uintptr(unsafe.Pointer(sidGroup)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0)
|
||||
if r0 != 0 {
|
||||
@@ -144,6 +122,7 @@ func SetNamedSecurityInfo(objectName *uint16, objectType uint32, securityInforma
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: uses golang.org/x/sys/windows.SecurityDescriptorFromString() and golang.org/x/sys/windows.SECURITY_DESCRIPTOR.DACL()
|
||||
func GetSecurityDescriptorDacl(securityDescriptor *byte, daclPresent *uint32, dacl **byte, daclDefaulted *uint32) (result error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(securityDescriptor)), uintptr(unsafe.Pointer(daclPresent)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclDefaulted)), 0, 0)
|
||||
if r1 == 0 {
|
||||
|
||||
66
vendor/github.com/docker/docker/pkg/term/ascii.go
generated
vendored
66
vendor/github.com/docker/docker/pkg/term/ascii.go
generated
vendored
@@ -1,66 +0,0 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ASCII list the possible supported ASCII key sequence
|
||||
var ASCII = []string{
|
||||
"ctrl-@",
|
||||
"ctrl-a",
|
||||
"ctrl-b",
|
||||
"ctrl-c",
|
||||
"ctrl-d",
|
||||
"ctrl-e",
|
||||
"ctrl-f",
|
||||
"ctrl-g",
|
||||
"ctrl-h",
|
||||
"ctrl-i",
|
||||
"ctrl-j",
|
||||
"ctrl-k",
|
||||
"ctrl-l",
|
||||
"ctrl-m",
|
||||
"ctrl-n",
|
||||
"ctrl-o",
|
||||
"ctrl-p",
|
||||
"ctrl-q",
|
||||
"ctrl-r",
|
||||
"ctrl-s",
|
||||
"ctrl-t",
|
||||
"ctrl-u",
|
||||
"ctrl-v",
|
||||
"ctrl-w",
|
||||
"ctrl-x",
|
||||
"ctrl-y",
|
||||
"ctrl-z",
|
||||
"ctrl-[",
|
||||
"ctrl-\\",
|
||||
"ctrl-]",
|
||||
"ctrl-^",
|
||||
"ctrl-_",
|
||||
}
|
||||
|
||||
// ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code.
|
||||
func ToBytes(keys string) ([]byte, error) {
|
||||
codes := []byte{}
|
||||
next:
|
||||
for _, key := range strings.Split(keys, ",") {
|
||||
if len(key) != 1 {
|
||||
for code, ctrl := range ASCII {
|
||||
if ctrl == key {
|
||||
codes = append(codes, byte(code))
|
||||
continue next
|
||||
}
|
||||
}
|
||||
if key == "DEL" {
|
||||
codes = append(codes, 127)
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unknown character: '%s'", key)
|
||||
}
|
||||
} else {
|
||||
codes = append(codes, key[0])
|
||||
}
|
||||
}
|
||||
return codes, nil
|
||||
}
|
||||
78
vendor/github.com/docker/docker/pkg/term/proxy.go
generated
vendored
78
vendor/github.com/docker/docker/pkg/term/proxy.go
generated
vendored
@@ -1,78 +0,0 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// EscapeError is special error which returned by a TTY proxy reader's Read()
|
||||
// method in case its detach escape sequence is read.
|
||||
type EscapeError struct{}
|
||||
|
||||
func (EscapeError) Error() string {
|
||||
return "read escape sequence"
|
||||
}
|
||||
|
||||
// escapeProxy is used only for attaches with a TTY. It is used to proxy
|
||||
// stdin keypresses from the underlying reader and look for the passed in
|
||||
// escape key sequence to signal a detach.
|
||||
type escapeProxy struct {
|
||||
escapeKeys []byte
|
||||
escapeKeyPos int
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader
|
||||
// and detects when the specified escape keys are read, in which case the Read
|
||||
// method will return an error of type EscapeError.
|
||||
func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader {
|
||||
return &escapeProxy{
|
||||
escapeKeys: escapeKeys,
|
||||
r: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *escapeProxy) Read(buf []byte) (int, error) {
|
||||
nr, err := r.r.Read(buf)
|
||||
|
||||
if len(r.escapeKeys) == 0 {
|
||||
return nr, err
|
||||
}
|
||||
|
||||
preserve := func() {
|
||||
// this preserves the original key presses in the passed in buffer
|
||||
nr += r.escapeKeyPos
|
||||
preserve := make([]byte, 0, r.escapeKeyPos+len(buf))
|
||||
preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...)
|
||||
preserve = append(preserve, buf...)
|
||||
r.escapeKeyPos = 0
|
||||
copy(buf[0:nr], preserve)
|
||||
}
|
||||
|
||||
if nr != 1 || err != nil {
|
||||
if r.escapeKeyPos > 0 {
|
||||
preserve()
|
||||
}
|
||||
return nr, err
|
||||
}
|
||||
|
||||
if buf[0] != r.escapeKeys[r.escapeKeyPos] {
|
||||
if r.escapeKeyPos > 0 {
|
||||
preserve()
|
||||
}
|
||||
return nr, nil
|
||||
}
|
||||
|
||||
if r.escapeKeyPos == len(r.escapeKeys)-1 {
|
||||
return 0, EscapeError{}
|
||||
}
|
||||
|
||||
// Looks like we've got an escape key, but we need to match again on the next
|
||||
// read.
|
||||
// Store the current escape key we found so we can look for the next one on
|
||||
// the next read.
|
||||
// Since this is an escape key, make sure we don't let the caller read it
|
||||
// If later on we find that this is not the escape sequence, we'll add the
|
||||
// keys back
|
||||
r.escapeKeyPos++
|
||||
return nr - r.escapeKeyPos, nil
|
||||
}
|
||||
20
vendor/github.com/docker/docker/pkg/term/tc.go
generated
vendored
20
vendor/github.com/docker/docker/pkg/term/tc.go
generated
vendored
@@ -1,20 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func tcget(fd uintptr, p *Termios) syscall.Errno {
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(p)))
|
||||
return err
|
||||
}
|
||||
|
||||
func tcset(fd uintptr, p *Termios) syscall.Errno {
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(p)))
|
||||
return err
|
||||
}
|
||||
124
vendor/github.com/docker/docker/pkg/term/term.go
generated
vendored
124
vendor/github.com/docker/docker/pkg/term/term.go
generated
vendored
@@ -1,124 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
// Package term provides structures and helper functions to work with
|
||||
// terminal (state, sizes).
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidState is returned if the state of the terminal is invalid.
|
||||
ErrInvalidState = errors.New("Invalid terminal state")
|
||||
)
|
||||
|
||||
// State represents the state of the terminal.
|
||||
type State struct {
|
||||
termios Termios
|
||||
}
|
||||
|
||||
// Winsize represents the size of the terminal window.
|
||||
type Winsize struct {
|
||||
Height uint16
|
||||
Width uint16
|
||||
x uint16
|
||||
y uint16
|
||||
}
|
||||
|
||||
// StdStreams returns the standard streams (stdin, stdout, stderr).
|
||||
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
|
||||
return os.Stdin, os.Stdout, os.Stderr
|
||||
}
|
||||
|
||||
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
|
||||
func GetFdInfo(in interface{}) (uintptr, bool) {
|
||||
var inFd uintptr
|
||||
var isTerminalIn bool
|
||||
if file, ok := in.(*os.File); ok {
|
||||
inFd = file.Fd()
|
||||
isTerminalIn = IsTerminal(inFd)
|
||||
}
|
||||
return inFd, isTerminalIn
|
||||
}
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios Termios
|
||||
return tcget(fd, &termios) == 0
|
||||
}
|
||||
|
||||
// RestoreTerminal restores the terminal connected to the given file descriptor
|
||||
// to a previous state.
|
||||
func RestoreTerminal(fd uintptr, state *State) error {
|
||||
if state == nil {
|
||||
return ErrInvalidState
|
||||
}
|
||||
if err := tcset(fd, &state.termios); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveState saves the state of the terminal connected to the given file descriptor.
|
||||
func SaveState(fd uintptr) (*State, error) {
|
||||
var oldState State
|
||||
if err := tcget(fd, &oldState.termios); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
}
|
||||
|
||||
// DisableEcho applies the specified state to the terminal connected to the file
|
||||
// descriptor, with echo disabled.
|
||||
func DisableEcho(fd uintptr, state *State) error {
|
||||
newState := state.termios
|
||||
newState.Lflag &^= unix.ECHO
|
||||
|
||||
if err := tcset(fd, &newState); err != 0 {
|
||||
return err
|
||||
}
|
||||
handleInterrupt(fd, state)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRawTerminal puts the terminal connected to the given file descriptor into
|
||||
// raw mode and returns the previous state. On UNIX, this puts both the input
|
||||
// and output into raw mode. On Windows, it only puts the input into raw mode.
|
||||
func SetRawTerminal(fd uintptr) (*State, error) {
|
||||
oldState, err := MakeRaw(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
handleInterrupt(fd, oldState)
|
||||
return oldState, err
|
||||
}
|
||||
|
||||
// SetRawTerminalOutput puts the output of terminal connected to the given file
|
||||
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the
|
||||
// state. On Windows, it disables LF -> CRLF translation.
|
||||
func SetRawTerminalOutput(fd uintptr) (*State, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func handleInterrupt(fd uintptr, state *State) {
|
||||
sigchan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigchan, os.Interrupt)
|
||||
go func() {
|
||||
for range sigchan {
|
||||
// quit cleanly and the new terminal item is on a new line
|
||||
fmt.Println()
|
||||
signal.Stop(sigchan)
|
||||
close(sigchan)
|
||||
RestoreTerminal(fd, state)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
}
|
||||
221
vendor/github.com/docker/docker/pkg/term/term_windows.go
generated
vendored
221
vendor/github.com/docker/docker/pkg/term/term_windows.go
generated
vendored
@@ -1,221 +0,0 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall" // used for STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE
|
||||
|
||||
"github.com/Azure/go-ansiterm/winterm"
|
||||
windowsconsole "github.com/docker/docker/pkg/term/windows"
|
||||
)
|
||||
|
||||
// State holds the console mode for the terminal.
|
||||
type State struct {
|
||||
mode uint32
|
||||
}
|
||||
|
||||
// Winsize is used for window size.
|
||||
type Winsize struct {
|
||||
Height uint16
|
||||
Width uint16
|
||||
}
|
||||
|
||||
// vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console
|
||||
var vtInputSupported bool
|
||||
|
||||
// StdStreams returns the standard streams (stdin, stdout, stderr).
|
||||
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
|
||||
// Turn on VT handling on all std handles, if possible. This might
|
||||
// fail, in which case we will fall back to terminal emulation.
|
||||
var emulateStdin, emulateStdout, emulateStderr bool
|
||||
fd := os.Stdin.Fd()
|
||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
||||
// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
|
||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
|
||||
emulateStdin = true
|
||||
} else {
|
||||
vtInputSupported = true
|
||||
}
|
||||
// Unconditionally set the console mode back even on failure because SetConsoleMode
|
||||
// remembers invalid bits on input handles.
|
||||
winterm.SetConsoleMode(fd, mode)
|
||||
}
|
||||
|
||||
fd = os.Stdout.Fd()
|
||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
||||
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||
emulateStdout = true
|
||||
} else {
|
||||
winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
}
|
||||
}
|
||||
|
||||
fd = os.Stderr.Fd()
|
||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
||||
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||
emulateStderr = true
|
||||
} else {
|
||||
winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
}
|
||||
}
|
||||
|
||||
// Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and
|
||||
// STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as
|
||||
// go-ansiterm hasn't switch to x/sys/windows.
|
||||
// TODO: switch back to x/sys/windows once go-ansiterm has switched
|
||||
if emulateStdin {
|
||||
stdIn = windowsconsole.NewAnsiReader(syscall.STD_INPUT_HANDLE)
|
||||
} else {
|
||||
stdIn = os.Stdin
|
||||
}
|
||||
|
||||
if emulateStdout {
|
||||
stdOut = windowsconsole.NewAnsiWriter(syscall.STD_OUTPUT_HANDLE)
|
||||
} else {
|
||||
stdOut = os.Stdout
|
||||
}
|
||||
|
||||
if emulateStderr {
|
||||
stdErr = windowsconsole.NewAnsiWriter(syscall.STD_ERROR_HANDLE)
|
||||
} else {
|
||||
stdErr = os.Stderr
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
|
||||
func GetFdInfo(in interface{}) (uintptr, bool) {
|
||||
return windowsconsole.GetHandleInfo(in)
|
||||
}
|
||||
|
||||
// GetWinsize returns the window size based on the specified file descriptor.
|
||||
func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||
info, err := winterm.GetConsoleScreenBufferInfo(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
winsize := &Winsize{
|
||||
Width: uint16(info.Window.Right - info.Window.Left + 1),
|
||||
Height: uint16(info.Window.Bottom - info.Window.Top + 1),
|
||||
}
|
||||
|
||||
return winsize, nil
|
||||
}
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
return windowsconsole.IsConsole(fd)
|
||||
}
|
||||
|
||||
// RestoreTerminal restores the terminal connected to the given file descriptor
|
||||
// to a previous state.
|
||||
func RestoreTerminal(fd uintptr, state *State) error {
|
||||
return winterm.SetConsoleMode(fd, state.mode)
|
||||
}
|
||||
|
||||
// SaveState saves the state of the terminal connected to the given file descriptor.
|
||||
func SaveState(fd uintptr) (*State, error) {
|
||||
mode, e := winterm.GetConsoleMode(fd)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &State{mode: mode}, nil
|
||||
}
|
||||
|
||||
// DisableEcho disables echo for the terminal connected to the given file descriptor.
|
||||
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
||||
func DisableEcho(fd uintptr, state *State) error {
|
||||
mode := state.mode
|
||||
mode &^= winterm.ENABLE_ECHO_INPUT
|
||||
mode |= winterm.ENABLE_PROCESSED_INPUT | winterm.ENABLE_LINE_INPUT
|
||||
err := winterm.SetConsoleMode(fd, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Register an interrupt handler to catch and restore prior state
|
||||
restoreAtInterrupt(fd, state)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRawTerminal puts the terminal connected to the given file descriptor into
|
||||
// raw mode and returns the previous state. On UNIX, this puts both the input
|
||||
// and output into raw mode. On Windows, it only puts the input into raw mode.
|
||||
func SetRawTerminal(fd uintptr) (*State, error) {
|
||||
state, err := MakeRaw(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Register an interrupt handler to catch and restore prior state
|
||||
restoreAtInterrupt(fd, state)
|
||||
return state, err
|
||||
}
|
||||
|
||||
// SetRawTerminalOutput puts the output of terminal connected to the given file
|
||||
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the
|
||||
// state. On Windows, it disables LF -> CRLF translation.
|
||||
func SetRawTerminalOutput(fd uintptr) (*State, error) {
|
||||
state, err := SaveState(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
|
||||
// version of Windows.
|
||||
winterm.SetConsoleMode(fd, state.mode|winterm.DISABLE_NEWLINE_AUTO_RETURN)
|
||||
return state, err
|
||||
}
|
||||
|
||||
// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be restored.
|
||||
func MakeRaw(fd uintptr) (*State, error) {
|
||||
state, err := SaveState(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mode := state.mode
|
||||
|
||||
// See
|
||||
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
|
||||
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
||||
|
||||
// Disable these modes
|
||||
mode &^= winterm.ENABLE_ECHO_INPUT
|
||||
mode &^= winterm.ENABLE_LINE_INPUT
|
||||
mode &^= winterm.ENABLE_MOUSE_INPUT
|
||||
mode &^= winterm.ENABLE_WINDOW_INPUT
|
||||
mode &^= winterm.ENABLE_PROCESSED_INPUT
|
||||
|
||||
// Enable these modes
|
||||
mode |= winterm.ENABLE_EXTENDED_FLAGS
|
||||
mode |= winterm.ENABLE_INSERT_MODE
|
||||
mode |= winterm.ENABLE_QUICK_EDIT_MODE
|
||||
if vtInputSupported {
|
||||
mode |= winterm.ENABLE_VIRTUAL_TERMINAL_INPUT
|
||||
}
|
||||
|
||||
err = winterm.SetConsoleMode(fd, mode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func restoreAtInterrupt(fd uintptr, state *State) {
|
||||
sigchan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigchan, os.Interrupt)
|
||||
|
||||
go func() {
|
||||
_ = <-sigchan
|
||||
RestoreTerminal(fd, state)
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
||||
42
vendor/github.com/docker/docker/pkg/term/termios_bsd.go
generated
vendored
42
vendor/github.com/docker/docker/pkg/term/termios_bsd.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
// +build darwin freebsd openbsd netbsd
|
||||
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = unix.TIOCGETA
|
||||
setTermios = unix.TIOCSETA
|
||||
)
|
||||
|
||||
// Termios is the Unix API for terminal I/O.
|
||||
type Termios unix.Termios
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd uintptr) (*State, error) {
|
||||
var oldState State
|
||||
if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newState := oldState.termios
|
||||
newState.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
|
||||
newState.Oflag &^= unix.OPOST
|
||||
newState.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
|
||||
newState.Cflag &^= (unix.CSIZE | unix.PARENB)
|
||||
newState.Cflag |= unix.CS8
|
||||
newState.Cc[unix.VMIN] = 1
|
||||
newState.Cc[unix.VTIME] = 0
|
||||
|
||||
if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
}
|
||||
39
vendor/github.com/docker/docker/pkg/term/termios_linux.go
generated
vendored
39
vendor/github.com/docker/docker/pkg/term/termios_linux.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = unix.TCGETS
|
||||
setTermios = unix.TCSETS
|
||||
)
|
||||
|
||||
// Termios is the Unix API for terminal I/O.
|
||||
type Termios unix.Termios
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd uintptr) (*State, error) {
|
||||
termios, err := unix.IoctlGetTermios(int(fd), getTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var oldState State
|
||||
oldState.termios = Termios(*termios)
|
||||
|
||||
termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
|
||||
termios.Oflag &^= unix.OPOST
|
||||
termios.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
|
||||
termios.Cflag &^= (unix.CSIZE | unix.PARENB)
|
||||
termios.Cflag |= unix.CS8
|
||||
termios.Cc[unix.VMIN] = 1
|
||||
termios.Cc[unix.VTIME] = 0
|
||||
|
||||
if err := unix.IoctlSetTermios(int(fd), setTermios, termios); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &oldState, nil
|
||||
}
|
||||
263
vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go
generated
vendored
263
vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go
generated
vendored
@@ -1,263 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
ansiterm "github.com/Azure/go-ansiterm"
|
||||
"github.com/Azure/go-ansiterm/winterm"
|
||||
)
|
||||
|
||||
const (
|
||||
escapeSequence = ansiterm.KEY_ESC_CSI
|
||||
)
|
||||
|
||||
// ansiReader wraps a standard input file (e.g., os.Stdin) providing ANSI sequence translation.
|
||||
type ansiReader struct {
|
||||
file *os.File
|
||||
fd uintptr
|
||||
buffer []byte
|
||||
cbBuffer int
|
||||
command []byte
|
||||
}
|
||||
|
||||
// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a
|
||||
// Windows console input handle.
|
||||
func NewAnsiReader(nFile int) io.ReadCloser {
|
||||
initLogger()
|
||||
file, fd := winterm.GetStdFile(nFile)
|
||||
return &ansiReader{
|
||||
file: file,
|
||||
fd: fd,
|
||||
command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH),
|
||||
buffer: make([]byte, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the wrapped file.
|
||||
func (ar *ansiReader) Close() (err error) {
|
||||
return ar.file.Close()
|
||||
}
|
||||
|
||||
// Fd returns the file descriptor of the wrapped file.
|
||||
func (ar *ansiReader) Fd() uintptr {
|
||||
return ar.fd
|
||||
}
|
||||
|
||||
// Read reads up to len(p) bytes of translated input events into p.
|
||||
func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Previously read bytes exist, read as much as we can and return
|
||||
if len(ar.buffer) > 0 {
|
||||
logger.Debugf("Reading previously cached bytes")
|
||||
|
||||
originalLength := len(ar.buffer)
|
||||
copiedLength := copy(p, ar.buffer)
|
||||
|
||||
if copiedLength == originalLength {
|
||||
ar.buffer = make([]byte, 0, len(p))
|
||||
} else {
|
||||
ar.buffer = ar.buffer[copiedLength:]
|
||||
}
|
||||
|
||||
logger.Debugf("Read from cache p[%d]: % x", copiedLength, p)
|
||||
return copiedLength, nil
|
||||
}
|
||||
|
||||
// Read and translate key events
|
||||
events, err := readInputEvents(ar.fd, len(p))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else if len(events) == 0 {
|
||||
logger.Debug("No input events detected")
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
keyBytes := translateKeyEvents(events, []byte(escapeSequence))
|
||||
|
||||
// Save excess bytes and right-size keyBytes
|
||||
if len(keyBytes) > len(p) {
|
||||
logger.Debugf("Received %d keyBytes, only room for %d bytes", len(keyBytes), len(p))
|
||||
ar.buffer = keyBytes[len(p):]
|
||||
keyBytes = keyBytes[:len(p)]
|
||||
} else if len(keyBytes) == 0 {
|
||||
logger.Debug("No key bytes returned from the translator")
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
copiedLength := copy(p, keyBytes)
|
||||
if copiedLength != len(keyBytes) {
|
||||
return 0, errors.New("unexpected copy length encountered")
|
||||
}
|
||||
|
||||
logger.Debugf("Read p[%d]: % x", copiedLength, p)
|
||||
logger.Debugf("Read keyBytes[%d]: % x", copiedLength, keyBytes)
|
||||
return copiedLength, nil
|
||||
}
|
||||
|
||||
// readInputEvents polls until at least one event is available.
|
||||
func readInputEvents(fd uintptr, maxBytes int) ([]winterm.INPUT_RECORD, error) {
|
||||
// Determine the maximum number of records to retrieve
|
||||
// -- Cast around the type system to obtain the size of a single INPUT_RECORD.
|
||||
// unsafe.Sizeof requires an expression vs. a type-reference; the casting
|
||||
// tricks the type system into believing it has such an expression.
|
||||
recordSize := int(unsafe.Sizeof(*((*winterm.INPUT_RECORD)(unsafe.Pointer(&maxBytes)))))
|
||||
countRecords := maxBytes / recordSize
|
||||
if countRecords > ansiterm.MAX_INPUT_EVENTS {
|
||||
countRecords = ansiterm.MAX_INPUT_EVENTS
|
||||
} else if countRecords == 0 {
|
||||
countRecords = 1
|
||||
}
|
||||
logger.Debugf("[windows] readInputEvents: Reading %v records (buffer size %v, record size %v)", countRecords, maxBytes, recordSize)
|
||||
|
||||
// Wait for and read input events
|
||||
events := make([]winterm.INPUT_RECORD, countRecords)
|
||||
nEvents := uint32(0)
|
||||
eventsExist, err := winterm.WaitForSingleObject(fd, winterm.WAIT_INFINITE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if eventsExist {
|
||||
err = winterm.ReadConsoleInput(fd, events, &nEvents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Return a slice restricted to the number of returned records
|
||||
logger.Debugf("[windows] readInputEvents: Read %v events", nEvents)
|
||||
return events[:nEvents], nil
|
||||
}
|
||||
|
||||
// KeyEvent Translation Helpers
|
||||
|
||||
var arrowKeyMapPrefix = map[uint16]string{
|
||||
winterm.VK_UP: "%s%sA",
|
||||
winterm.VK_DOWN: "%s%sB",
|
||||
winterm.VK_RIGHT: "%s%sC",
|
||||
winterm.VK_LEFT: "%s%sD",
|
||||
}
|
||||
|
||||
var keyMapPrefix = map[uint16]string{
|
||||
winterm.VK_UP: "\x1B[%sA",
|
||||
winterm.VK_DOWN: "\x1B[%sB",
|
||||
winterm.VK_RIGHT: "\x1B[%sC",
|
||||
winterm.VK_LEFT: "\x1B[%sD",
|
||||
winterm.VK_HOME: "\x1B[1%s~", // showkey shows ^[[1
|
||||
winterm.VK_END: "\x1B[4%s~", // showkey shows ^[[4
|
||||
winterm.VK_INSERT: "\x1B[2%s~",
|
||||
winterm.VK_DELETE: "\x1B[3%s~",
|
||||
winterm.VK_PRIOR: "\x1B[5%s~",
|
||||
winterm.VK_NEXT: "\x1B[6%s~",
|
||||
winterm.VK_F1: "",
|
||||
winterm.VK_F2: "",
|
||||
winterm.VK_F3: "\x1B[13%s~",
|
||||
winterm.VK_F4: "\x1B[14%s~",
|
||||
winterm.VK_F5: "\x1B[15%s~",
|
||||
winterm.VK_F6: "\x1B[17%s~",
|
||||
winterm.VK_F7: "\x1B[18%s~",
|
||||
winterm.VK_F8: "\x1B[19%s~",
|
||||
winterm.VK_F9: "\x1B[20%s~",
|
||||
winterm.VK_F10: "\x1B[21%s~",
|
||||
winterm.VK_F11: "\x1B[23%s~",
|
||||
winterm.VK_F12: "\x1B[24%s~",
|
||||
}
|
||||
|
||||
// translateKeyEvents converts the input events into the appropriate ANSI string.
|
||||
func translateKeyEvents(events []winterm.INPUT_RECORD, escapeSequence []byte) []byte {
|
||||
var buffer bytes.Buffer
|
||||
for _, event := range events {
|
||||
if event.EventType == winterm.KEY_EVENT && event.KeyEvent.KeyDown != 0 {
|
||||
buffer.WriteString(keyToString(&event.KeyEvent, escapeSequence))
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.Bytes()
|
||||
}
|
||||
|
||||
// keyToString maps the given input event record to the corresponding string.
|
||||
func keyToString(keyEvent *winterm.KEY_EVENT_RECORD, escapeSequence []byte) string {
|
||||
if keyEvent.UnicodeChar == 0 {
|
||||
return formatVirtualKey(keyEvent.VirtualKeyCode, keyEvent.ControlKeyState, escapeSequence)
|
||||
}
|
||||
|
||||
_, alt, control := getControlKeys(keyEvent.ControlKeyState)
|
||||
if control {
|
||||
// TODO(azlinux): Implement following control sequences
|
||||
// <Ctrl>-D Signals the end of input from the keyboard; also exits current shell.
|
||||
// <Ctrl>-H Deletes the first character to the left of the cursor. Also called the ERASE key.
|
||||
// <Ctrl>-Q Restarts printing after it has been stopped with <Ctrl>-s.
|
||||
// <Ctrl>-S Suspends printing on the screen (does not stop the program).
|
||||
// <Ctrl>-U Deletes all characters on the current line. Also called the KILL key.
|
||||
// <Ctrl>-E Quits current command and creates a core
|
||||
|
||||
}
|
||||
|
||||
// <Alt>+Key generates ESC N Key
|
||||
if !control && alt {
|
||||
return ansiterm.KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar))
|
||||
}
|
||||
|
||||
return string(keyEvent.UnicodeChar)
|
||||
}
|
||||
|
||||
// formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string.
|
||||
func formatVirtualKey(key uint16, controlState uint32, escapeSequence []byte) string {
|
||||
shift, alt, control := getControlKeys(controlState)
|
||||
modifier := getControlKeysModifier(shift, alt, control)
|
||||
|
||||
if format, ok := arrowKeyMapPrefix[key]; ok {
|
||||
return fmt.Sprintf(format, escapeSequence, modifier)
|
||||
}
|
||||
|
||||
if format, ok := keyMapPrefix[key]; ok {
|
||||
return fmt.Sprintf(format, modifier)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// getControlKeys extracts the shift, alt, and ctrl key states.
|
||||
func getControlKeys(controlState uint32) (shift, alt, control bool) {
|
||||
shift = 0 != (controlState & winterm.SHIFT_PRESSED)
|
||||
alt = 0 != (controlState & (winterm.LEFT_ALT_PRESSED | winterm.RIGHT_ALT_PRESSED))
|
||||
control = 0 != (controlState & (winterm.LEFT_CTRL_PRESSED | winterm.RIGHT_CTRL_PRESSED))
|
||||
return shift, alt, control
|
||||
}
|
||||
|
||||
// getControlKeysModifier returns the ANSI modifier for the given combination of control keys.
|
||||
func getControlKeysModifier(shift, alt, control bool) string {
|
||||
if shift && alt && control {
|
||||
return ansiterm.KEY_CONTROL_PARAM_8
|
||||
}
|
||||
if alt && control {
|
||||
return ansiterm.KEY_CONTROL_PARAM_7
|
||||
}
|
||||
if shift && control {
|
||||
return ansiterm.KEY_CONTROL_PARAM_6
|
||||
}
|
||||
if control {
|
||||
return ansiterm.KEY_CONTROL_PARAM_5
|
||||
}
|
||||
if shift && alt {
|
||||
return ansiterm.KEY_CONTROL_PARAM_4
|
||||
}
|
||||
if alt {
|
||||
return ansiterm.KEY_CONTROL_PARAM_3
|
||||
}
|
||||
if shift {
|
||||
return ansiterm.KEY_CONTROL_PARAM_2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
64
vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go
generated
vendored
64
vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go
generated
vendored
@@ -1,64 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
ansiterm "github.com/Azure/go-ansiterm"
|
||||
"github.com/Azure/go-ansiterm/winterm"
|
||||
)
|
||||
|
||||
// ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation.
|
||||
type ansiWriter struct {
|
||||
file *os.File
|
||||
fd uintptr
|
||||
infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO
|
||||
command []byte
|
||||
escapeSequence []byte
|
||||
inAnsiSequence bool
|
||||
parser *ansiterm.AnsiParser
|
||||
}
|
||||
|
||||
// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a
|
||||
// Windows console output handle.
|
||||
func NewAnsiWriter(nFile int) io.Writer {
|
||||
initLogger()
|
||||
file, fd := winterm.GetStdFile(nFile)
|
||||
info, err := winterm.GetConsoleScreenBufferInfo(fd)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file))
|
||||
logger.Infof("newAnsiWriter: parser %p", parser)
|
||||
|
||||
aw := &ansiWriter{
|
||||
file: file,
|
||||
fd: fd,
|
||||
infoReset: info,
|
||||
command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH),
|
||||
escapeSequence: []byte(ansiterm.KEY_ESC_CSI),
|
||||
parser: parser,
|
||||
}
|
||||
|
||||
logger.Infof("newAnsiWriter: aw.parser %p", aw.parser)
|
||||
logger.Infof("newAnsiWriter: %v", aw)
|
||||
return aw
|
||||
}
|
||||
|
||||
func (aw *ansiWriter) Fd() uintptr {
|
||||
return aw.fd
|
||||
}
|
||||
|
||||
// Write writes len(p) bytes from p to the underlying data stream.
|
||||
func (aw *ansiWriter) Write(p []byte) (total int, err error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
logger.Infof("Write: % x", p)
|
||||
logger.Infof("Write: %s", string(p))
|
||||
return aw.parser.Parse(p)
|
||||
}
|
||||
35
vendor/github.com/docker/docker/pkg/term/windows/console.go
generated
vendored
35
vendor/github.com/docker/docker/pkg/term/windows/console.go
generated
vendored
@@ -1,35 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Azure/go-ansiterm/winterm"
|
||||
)
|
||||
|
||||
// GetHandleInfo returns file descriptor and bool indicating whether the file is a console.
|
||||
func GetHandleInfo(in interface{}) (uintptr, bool) {
|
||||
switch t := in.(type) {
|
||||
case *ansiReader:
|
||||
return t.Fd(), true
|
||||
case *ansiWriter:
|
||||
return t.Fd(), true
|
||||
}
|
||||
|
||||
var inFd uintptr
|
||||
var isTerminal bool
|
||||
|
||||
if file, ok := in.(*os.File); ok {
|
||||
inFd = file.Fd()
|
||||
isTerminal = IsConsole(inFd)
|
||||
}
|
||||
return inFd, isTerminal
|
||||
}
|
||||
|
||||
// IsConsole returns true if the given file descriptor is a Windows Console.
|
||||
// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console.
|
||||
func IsConsole(fd uintptr) bool {
|
||||
_, e := winterm.GetConsoleMode(fd)
|
||||
return e == nil
|
||||
}
|
||||
34
vendor/github.com/docker/docker/pkg/term/windows/windows.go
generated
vendored
34
vendor/github.com/docker/docker/pkg/term/windows/windows.go
generated
vendored
@@ -1,34 +0,0 @@
|
||||
// +build windows
|
||||
// These files implement ANSI-aware input and output streams for use by the Docker Windows client.
|
||||
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
|
||||
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
ansiterm "github.com/Azure/go-ansiterm"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var logger *logrus.Logger
|
||||
var initOnce sync.Once
|
||||
|
||||
func initLogger() {
|
||||
initOnce.Do(func() {
|
||||
logFile := ioutil.Discard
|
||||
|
||||
if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
|
||||
logFile, _ = os.Create("ansiReaderWriter.log")
|
||||
}
|
||||
|
||||
logger = &logrus.Logger{
|
||||
Out: logFile,
|
||||
Formatter: new(logrus.TextFormatter),
|
||||
Level: logrus.DebugLevel,
|
||||
}
|
||||
})
|
||||
}
|
||||
20
vendor/github.com/docker/docker/pkg/term/winsize.go
generated
vendored
20
vendor/github.com/docker/docker/pkg/term/winsize.go
generated
vendored
@@ -1,20 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// GetWinsize returns the window size based on the specified file descriptor.
|
||||
func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||
uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
|
||||
ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel}
|
||||
return ws, err
|
||||
}
|
||||
|
||||
// SetWinsize tries to set the specified window size for the specified file descriptor.
|
||||
func SetWinsize(fd uintptr, ws *Winsize) error {
|
||||
uws := &unix.Winsize{Row: ws.Height, Col: ws.Width, Xpixel: ws.x, Ypixel: ws.y}
|
||||
return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, uws)
|
||||
}
|
||||
Reference in New Issue
Block a user