update docker/docker, and docker/distribution

This commit is contained in:
David Ashpole 2017-09-01 11:17:14 -07:00
parent 03d7288c83
commit 20bd275f77
50 changed files with 854 additions and 463 deletions

21
Godeps/Godeps.json generated
View File

@ -30,11 +30,6 @@
"Comment": "v1.8.0", "Comment": "v1.8.0",
"Rev": "4ba9bba6adb6697bcec3841e1ecdfecf5227c3b9" "Rev": "4ba9bba6adb6697bcec3841e1ecdfecf5227c3b9"
}, },
{
"ImportPath": "github.com/Sirupsen/logrus",
"Comment": "v0.7.3-2-g26709e2",
"Rev": "26709e2714106fb8ad40b773b711ebce25b78914"
},
{ {
"ImportPath": "github.com/abbot/go-http-auth", "ImportPath": "github.com/abbot/go-http-auth",
"Rev": "c0ef4539dfab4d21c8ef20ba2924f9fc6f186d35" "Rev": "c0ef4539dfab4d21c8ef20ba2924f9fc6f186d35"
@ -190,23 +185,23 @@
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/longpath", "ImportPath": "github.com/docker/docker/pkg/longpath",
"Comment": "v1.13.1-rc2", "Comment": "docs-v1.12.0-rc4-2016-07-15-7415-g8af4db6f0",
"Rev": "54f71fd84a0dabab9d45f5fe7543a028b1200ca1" "Rev": "8af4db6f002ac907b6ef8610b237879dfcaa5b7a"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/mount", "ImportPath": "github.com/docker/docker/pkg/mount",
"Comment": "v1.13.1-rc2", "Comment": "docs-v1.12.0-rc4-2016-07-15-7415-g8af4db6f0",
"Rev": "54f71fd84a0dabab9d45f5fe7543a028b1200ca1" "Rev": "8af4db6f002ac907b6ef8610b237879dfcaa5b7a"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/symlink", "ImportPath": "github.com/docker/docker/pkg/symlink",
"Comment": "v1.13.1-rc2", "Comment": "docs-v1.12.0-rc4-2016-07-15-7415-g8af4db6f0",
"Rev": "54f71fd84a0dabab9d45f5fe7543a028b1200ca1" "Rev": "8af4db6f002ac907b6ef8610b237879dfcaa5b7a"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/system", "ImportPath": "github.com/docker/docker/pkg/system",
"Comment": "v1.13.1-rc2", "Comment": "docs-v1.12.0-rc4-2016-07-15-7415-g8af4db6f0",
"Rev": "54f71fd84a0dabab9d45f5fe7543a028b1200ca1" "Rev": "8af4db6f002ac907b6ef8610b237879dfcaa5b7a"
}, },
{ {
"ImportPath": "github.com/docker/engine-api/client", "ImportPath": "github.com/docker/engine-api/client",

File diff suppressed because it is too large Load Diff

View File

@ -176,7 +176,7 @@
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Copyright 2013-2016 Docker, Inc. Copyright 2013-2017 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
Docker Docker
Copyright 2012-2016 Docker, Inc. Copyright 2012-2017 Docker, Inc.
This product includes software developed at Docker, Inc. (https://www.docker.com). This product includes software developed at Docker, Inc. (https://www.docker.com).

View File

@ -45,4 +45,5 @@ const (
RELATIME = 0 RELATIME = 0
REMOUNT = 0 REMOUNT = 0
STRICTATIME = 0 STRICTATIME = 0
mntDetach = 0
) )

View File

@ -1,85 +1,87 @@
package mount package mount
import ( import (
"syscall" "golang.org/x/sys/unix"
) )
const ( const (
// RDONLY will mount the file system read-only. // RDONLY will mount the file system read-only.
RDONLY = syscall.MS_RDONLY RDONLY = unix.MS_RDONLY
// NOSUID will not allow set-user-identifier or set-group-identifier bits to // NOSUID will not allow set-user-identifier or set-group-identifier bits to
// take effect. // take effect.
NOSUID = syscall.MS_NOSUID NOSUID = unix.MS_NOSUID
// NODEV will not interpret character or block special devices on the file // NODEV will not interpret character or block special devices on the file
// system. // system.
NODEV = syscall.MS_NODEV NODEV = unix.MS_NODEV
// NOEXEC will not allow execution of any binaries on the mounted file system. // NOEXEC will not allow execution of any binaries on the mounted file system.
NOEXEC = syscall.MS_NOEXEC NOEXEC = unix.MS_NOEXEC
// SYNCHRONOUS will allow I/O to the file system to be done synchronously. // SYNCHRONOUS will allow I/O to the file system to be done synchronously.
SYNCHRONOUS = syscall.MS_SYNCHRONOUS SYNCHRONOUS = unix.MS_SYNCHRONOUS
// DIRSYNC will force all directory updates within the file system to be done // DIRSYNC will force all directory updates within the file system to be done
// synchronously. This affects the following system calls: create, link, // synchronously. This affects the following system calls: create, link,
// unlink, symlink, mkdir, rmdir, mknod and rename. // unlink, symlink, mkdir, rmdir, mknod and rename.
DIRSYNC = syscall.MS_DIRSYNC DIRSYNC = unix.MS_DIRSYNC
// REMOUNT will attempt to remount an already-mounted file system. This is // 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 // 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 // make a readonly file system writeable. It does not change device or mount
// point. // point.
REMOUNT = syscall.MS_REMOUNT REMOUNT = unix.MS_REMOUNT
// MANDLOCK will force mandatory locks on a filesystem. // MANDLOCK will force mandatory locks on a filesystem.
MANDLOCK = syscall.MS_MANDLOCK MANDLOCK = unix.MS_MANDLOCK
// NOATIME will not update the file access time when reading from a file. // NOATIME will not update the file access time when reading from a file.
NOATIME = syscall.MS_NOATIME NOATIME = unix.MS_NOATIME
// NODIRATIME will not update the directory access time. // NODIRATIME will not update the directory access time.
NODIRATIME = syscall.MS_NODIRATIME NODIRATIME = unix.MS_NODIRATIME
// BIND remounts a subtree somewhere else. // BIND remounts a subtree somewhere else.
BIND = syscall.MS_BIND BIND = unix.MS_BIND
// RBIND remounts a subtree and all possible submounts somewhere else. // RBIND remounts a subtree and all possible submounts somewhere else.
RBIND = syscall.MS_BIND | syscall.MS_REC RBIND = unix.MS_BIND | unix.MS_REC
// UNBINDABLE creates a mount which cannot be cloned through a bind operation. // UNBINDABLE creates a mount which cannot be cloned through a bind operation.
UNBINDABLE = syscall.MS_UNBINDABLE UNBINDABLE = unix.MS_UNBINDABLE
// RUNBINDABLE marks the entire mount tree as UNBINDABLE. // RUNBINDABLE marks the entire mount tree as UNBINDABLE.
RUNBINDABLE = syscall.MS_UNBINDABLE | syscall.MS_REC RUNBINDABLE = unix.MS_UNBINDABLE | unix.MS_REC
// PRIVATE creates a mount which carries no propagation abilities. // PRIVATE creates a mount which carries no propagation abilities.
PRIVATE = syscall.MS_PRIVATE PRIVATE = unix.MS_PRIVATE
// RPRIVATE marks the entire mount tree as PRIVATE. // RPRIVATE marks the entire mount tree as PRIVATE.
RPRIVATE = syscall.MS_PRIVATE | syscall.MS_REC RPRIVATE = unix.MS_PRIVATE | unix.MS_REC
// SLAVE creates a mount which receives propagation from its master, but not // SLAVE creates a mount which receives propagation from its master, but not
// vice versa. // vice versa.
SLAVE = syscall.MS_SLAVE SLAVE = unix.MS_SLAVE
// RSLAVE marks the entire mount tree as SLAVE. // RSLAVE marks the entire mount tree as SLAVE.
RSLAVE = syscall.MS_SLAVE | syscall.MS_REC RSLAVE = unix.MS_SLAVE | unix.MS_REC
// SHARED creates a mount which provides the ability to create mirrors of // SHARED creates a mount which provides the ability to create mirrors of
// that mount such that mounts and unmounts within any of the mirrors // that mount such that mounts and unmounts within any of the mirrors
// propagate to the other mirrors. // propagate to the other mirrors.
SHARED = syscall.MS_SHARED SHARED = unix.MS_SHARED
// RSHARED marks the entire mount tree as SHARED. // RSHARED marks the entire mount tree as SHARED.
RSHARED = syscall.MS_SHARED | syscall.MS_REC RSHARED = unix.MS_SHARED | unix.MS_REC
// RELATIME updates inode access times relative to modify or change time. // RELATIME updates inode access times relative to modify or change time.
RELATIME = syscall.MS_RELATIME RELATIME = unix.MS_RELATIME
// STRICTATIME allows to explicitly request full atime updates. This makes // STRICTATIME allows to explicitly request full atime updates. This makes
// it possible for the kernel to default to relatime or noatime but still // it possible for the kernel to default to relatime or noatime but still
// allow userspace to override it. // allow userspace to override it.
STRICTATIME = syscall.MS_STRICTATIME STRICTATIME = unix.MS_STRICTATIME
mntDetach = unix.MNT_DETACH
) )

View File

@ -27,4 +27,5 @@ const (
STRICTATIME = 0 STRICTATIME = 0
SYNCHRONOUS = 0 SYNCHRONOUS = 0
RDONLY = 0 RDONLY = 0
mntDetach = 0
) )

View File

@ -1,7 +1,8 @@
package mount package mount
import ( import (
"time" "sort"
"strings"
) )
// GetMounts retrieves a list of mounts for the current running process. // GetMounts retrieves a list of mounts for the current running process.
@ -46,29 +47,40 @@ func Mount(device, target, mType, options string) error {
// flags.go for supported option flags. // flags.go for supported option flags.
func ForceMount(device, target, mType, options string) error { func ForceMount(device, target, mType, options string) error {
flag, data := parseOptions(options) flag, data := parseOptions(options)
if err := mount(device, target, mType, uintptr(flag), data); err != nil { return mount(device, target, mType, uintptr(flag), data)
return err
}
return nil
} }
// Unmount will unmount the target filesystem, so long as it is mounted. // Unmount lazily unmounts a filesystem on supported platforms, otherwise
// does a normal unmount.
func Unmount(target string) error { func Unmount(target string) error {
if mounted, err := Mounted(target); err != nil || !mounted { if mounted, err := Mounted(target); err != nil || !mounted {
return err return err
} }
return ForceUnmount(target) return unmount(target, mntDetach)
} }
// ForceUnmount will force an unmount of the target filesystem, regardless if // RecursiveUnmount unmounts the target and all mounts underneath, starting with
// it is mounted or not. // the deepsest mount first.
func ForceUnmount(target string) (err error) { func RecursiveUnmount(target string) error {
// Simple retry logic for unmount mounts, err := GetMounts()
for i := 0; i < 10; i++ { if err != nil {
if err = unmount(target, 0); err == nil { return err
return nil
}
time.Sleep(100 * time.Millisecond)
} }
return
// Make the deepest mount be first
sort.Sort(sort.Reverse(byMountpoint(mounts)))
for i, m := range mounts {
if !strings.HasPrefix(m.Mountpoint, target) {
continue
}
if err := Unmount(m.Mountpoint); err != nil && i == len(mounts)-1 {
if mounted, err := Mounted(m.Mountpoint); err != nil || mounted {
return err
}
// Ignore errors for submounts and continue trying to unmount others
// The final unmount should fail if there ane any submounts remaining
}
}
return nil
} }

View File

@ -13,8 +13,9 @@ import "C"
import ( import (
"fmt" "fmt"
"strings" "strings"
"syscall"
"unsafe" "unsafe"
"golang.org/x/sys/unix"
) )
func allocateIOVecs(options []string) []C.struct_iovec { func allocateIOVecs(options []string) []C.struct_iovec {
@ -55,5 +56,5 @@ func mount(device, target, mType string, flag uintptr, data string) error {
} }
func unmount(target string, flag int) error { func unmount(target string, flag int) error {
return syscall.Unmount(target, flag) return unix.Unmount(target, flag)
} }

View File

@ -1,21 +1,57 @@
package mount package mount
import ( import (
"syscall" "golang.org/x/sys/unix"
) )
func mount(device, target, mType string, flag uintptr, data string) error { const (
if err := syscall.Mount(device, target, mType, flag, data); err != nil { // ptypes is the set propagation types.
return err 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 err
}
} }
// If we have a bind mount or remount, remount... if flags&ptypes != 0 {
if flag&syscall.MS_BIND == syscall.MS_BIND && flag&syscall.MS_RDONLY == syscall.MS_RDONLY { // Change the propagation type.
return syscall.Mount(device, target, mType, flag|syscall.MS_REMOUNT, data) if err := unix.Mount("", target, "", flags&pflags, ""); err != nil {
return err
}
} }
if oflags&broflags == broflags {
// Remount the bind to apply read only.
return unix.Mount("", target, "", oflags|unix.MS_REMOUNT, "")
}
return nil return nil
} }
func unmount(target string, flag int) error { func unmount(target string, flag int) error {
return syscall.Unmount(target, flag) return unix.Unmount(target, flag)
} }

View File

@ -38,3 +38,17 @@ type Info struct {
// VfsOpts represents per super block options. // VfsOpts represents per super block options.
VfsOpts string VfsOpts string
} }
type byMountpoint []*Info
func (by byMountpoint) Len() int {
return len(by)
}
func (by byMountpoint) Less(i, j int) bool {
return by[i].Mountpoint < by[j].Mountpoint
}
func (by byMountpoint) Swap(i, j int) {
by[i], by[j] = by[j], by[i]
}

View File

@ -176,7 +176,7 @@
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Copyright 2014-2016 Docker, Inc. Copyright 2014-2017 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
Copyright (c) 2014-2016 The Docker & Go Authors. All rights reserved. Copyright (c) 2014-2017 The Docker & Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are

View File

@ -40,7 +40,7 @@ func FollowSymlinkInScope(path, root string) (string, error) {
// //
// Example: // Example:
// If /foo/bar -> /outside, // If /foo/bar -> /outside,
// FollowSymlinkInScope("/foo/bar", "/foo") == "/foo/outside" instead of "/oustide" // FollowSymlinkInScope("/foo/bar", "/foo") == "/foo/outside" instead of "/outside"
// //
// IMPORTANT: it is the caller's responsibility to call evalSymlinksInScope *after* relevant symlinks // IMPORTANT: it is the caller's responsibility to call evalSymlinksInScope *after* relevant symlinks
// are created and not to create subsequently, additional symlinks that could potentially make a // are created and not to create subsequently, additional symlinks that could potentially make a

View File

@ -6,49 +6,49 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"syscall"
"github.com/docker/docker/pkg/longpath" "github.com/docker/docker/pkg/longpath"
"golang.org/x/sys/windows"
) )
func toShort(path string) (string, error) { func toShort(path string) (string, error) {
p, err := syscall.UTF16FromString(path) p, err := windows.UTF16FromString(path)
if err != nil { if err != nil {
return "", err return "", err
} }
b := p // GetShortPathName says we can reuse buffer b := p // GetShortPathName says we can reuse buffer
n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b))) n, err := windows.GetShortPathName(&p[0], &b[0], uint32(len(b)))
if err != nil { if err != nil {
return "", err return "", err
} }
if n > uint32(len(b)) { if n > uint32(len(b)) {
b = make([]uint16, n) b = make([]uint16, n)
if _, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b))); err != nil { if _, err = windows.GetShortPathName(&p[0], &b[0], uint32(len(b))); err != nil {
return "", err return "", err
} }
} }
return syscall.UTF16ToString(b), nil return windows.UTF16ToString(b), nil
} }
func toLong(path string) (string, error) { func toLong(path string) (string, error) {
p, err := syscall.UTF16FromString(path) p, err := windows.UTF16FromString(path)
if err != nil { if err != nil {
return "", err return "", err
} }
b := p // GetLongPathName says we can reuse buffer b := p // GetLongPathName says we can reuse buffer
n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) n, err := windows.GetLongPathName(&p[0], &b[0], uint32(len(b)))
if err != nil { if err != nil {
return "", err return "", err
} }
if n > uint32(len(b)) { if n > uint32(len(b)) {
b = make([]uint16, n) b = make([]uint16, n)
n, err = syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) n, err = windows.GetLongPathName(&p[0], &b[0], uint32(len(b)))
if err != nil { if err != nil {
return "", err return "", err
} }
} }
b = b[:n] b = b[:n]
return syscall.UTF16ToString(b), nil return windows.UTF16ToString(b), nil
} }
func evalSymlinks(path string) (string, error) { func evalSymlinks(path string) (string, error) {
@ -65,7 +65,7 @@ func evalSymlinks(path string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
// syscall.GetLongPathName does not change the case of the drive letter, // windows.GetLongPathName does not change the case of the drive letter,
// but the result of EvalSymlinks must be unique, so we have // but the result of EvalSymlinks must be unique, so we have
// EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`). // EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`).
// Make drive letter upper case. // Make drive letter upper case.

View File

@ -2,26 +2,9 @@ package system
import ( import (
"os" "os"
"syscall"
"time" "time"
"unsafe"
) )
var (
maxTime time.Time
)
func init() {
if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 {
// This is a 64 bit timespec
// os.Chtimes limits time to the following
maxTime = time.Unix(0, 1<<63-1)
} else {
// This is a 32 bit timespec
maxTime = time.Unix(1<<31-1, 0)
}
}
// Chtimes changes the access time and modified time of a file at the given path // Chtimes changes the access time and modified time of a file at the given path
func Chtimes(name string, atime time.Time, mtime time.Time) error { func Chtimes(name string, atime time.Time, mtime time.Time) error {
unixMinTime := time.Unix(0, 0) unixMinTime := time.Unix(0, 0)

View File

@ -3,25 +3,26 @@
package system package system
import ( import (
"syscall"
"time" "time"
"golang.org/x/sys/windows"
) )
//setCTime will set the create time on a file. On Windows, this requires //setCTime will set the create time on a file. On Windows, this requires
//calling SetFileTime and explicitly including the create time. //calling SetFileTime and explicitly including the create time.
func setCTime(path string, ctime time.Time) error { func setCTime(path string, ctime time.Time) error {
ctimespec := syscall.NsecToTimespec(ctime.UnixNano()) ctimespec := windows.NsecToTimespec(ctime.UnixNano())
pathp, e := syscall.UTF16PtrFromString(path) pathp, e := windows.UTF16PtrFromString(path)
if e != nil { if e != nil {
return e return e
} }
h, e := syscall.CreateFile(pathp, h, e := windows.CreateFile(pathp,
syscall.FILE_WRITE_ATTRIBUTES, syscall.FILE_SHARE_WRITE, nil, windows.FILE_WRITE_ATTRIBUTES, windows.FILE_SHARE_WRITE, nil,
syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0) windows.OPEN_EXISTING, windows.FILE_FLAG_BACKUP_SEMANTICS, 0)
if e != nil { if e != nil {
return e return e
} }
defer syscall.Close(h) defer windows.Close(h)
c := syscall.NsecToFiletime(syscall.TimespecToNsec(ctimespec)) c := windows.NsecToFiletime(windows.TimespecToNsec(ctimespec))
return syscall.SetFileTime(h, &c, nil, nil) return windows.SetFileTime(h, &c, nil, nil)
} }

View File

@ -19,8 +19,8 @@ var (
) )
// CreateEvent implements win32 CreateEventW func in golang. It will create an event object. // CreateEvent implements win32 CreateEventW func in golang. It will create an event object.
func CreateEvent(eventAttributes *syscall.SecurityAttributes, manualReset bool, initialState bool, name string) (handle syscall.Handle, err error) { func CreateEvent(eventAttributes *windows.SecurityAttributes, manualReset bool, initialState bool, name string) (handle windows.Handle, err error) {
namep, _ := syscall.UTF16PtrFromString(name) namep, _ := windows.UTF16PtrFromString(name)
var _p1 uint32 var _p1 uint32
if manualReset { if manualReset {
_p1 = 1 _p1 = 1
@ -31,45 +31,45 @@ func CreateEvent(eventAttributes *syscall.SecurityAttributes, manualReset bool,
} }
r0, _, e1 := procCreateEvent.Call(uintptr(unsafe.Pointer(eventAttributes)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(namep))) r0, _, e1 := procCreateEvent.Call(uintptr(unsafe.Pointer(eventAttributes)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(namep)))
use(unsafe.Pointer(namep)) use(unsafe.Pointer(namep))
handle = syscall.Handle(r0) handle = windows.Handle(r0)
if handle == syscall.InvalidHandle { if handle == windows.InvalidHandle {
err = e1 err = e1
} }
return return
} }
// OpenEvent implements win32 OpenEventW func in golang. It opens an event object. // OpenEvent implements win32 OpenEventW func in golang. It opens an event object.
func OpenEvent(desiredAccess uint32, inheritHandle bool, name string) (handle syscall.Handle, err error) { func OpenEvent(desiredAccess uint32, inheritHandle bool, name string) (handle windows.Handle, err error) {
namep, _ := syscall.UTF16PtrFromString(name) namep, _ := windows.UTF16PtrFromString(name)
var _p1 uint32 var _p1 uint32
if inheritHandle { if inheritHandle {
_p1 = 1 _p1 = 1
} }
r0, _, e1 := procOpenEvent.Call(uintptr(desiredAccess), uintptr(_p1), uintptr(unsafe.Pointer(namep))) r0, _, e1 := procOpenEvent.Call(uintptr(desiredAccess), uintptr(_p1), uintptr(unsafe.Pointer(namep)))
use(unsafe.Pointer(namep)) use(unsafe.Pointer(namep))
handle = syscall.Handle(r0) handle = windows.Handle(r0)
if handle == syscall.InvalidHandle { if handle == windows.InvalidHandle {
err = e1 err = e1
} }
return return
} }
// SetEvent implements win32 SetEvent func in golang. // SetEvent implements win32 SetEvent func in golang.
func SetEvent(handle syscall.Handle) (err error) { func SetEvent(handle windows.Handle) (err error) {
return setResetPulse(handle, procSetEvent) return setResetPulse(handle, procSetEvent)
} }
// ResetEvent implements win32 ResetEvent func in golang. // ResetEvent implements win32 ResetEvent func in golang.
func ResetEvent(handle syscall.Handle) (err error) { func ResetEvent(handle windows.Handle) (err error) {
return setResetPulse(handle, procResetEvent) return setResetPulse(handle, procResetEvent)
} }
// PulseEvent implements win32 PulseEvent func in golang. // PulseEvent implements win32 PulseEvent func in golang.
func PulseEvent(handle syscall.Handle) (err error) { func PulseEvent(handle windows.Handle) (err error) {
return setResetPulse(handle, procPulseEvent) return setResetPulse(handle, procPulseEvent)
} }
func setResetPulse(handle syscall.Handle, proc *windows.LazyProc) (err error) { func setResetPulse(handle windows.Handle, proc *windows.LazyProc) (err error) {
r0, _, _ := proc.Call(uintptr(handle)) r0, _, _ := proc.Call(uintptr(handle))
if r0 != 0 { if r0 != 0 {
err = syscall.Errno(r0) err = syscall.Errno(r0)

View File

@ -3,19 +3,19 @@
package system package system
import ( import (
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
) )
// MkdirAllWithACL is a wrapper for MkdirAll that creates a directory // MkdirAllWithACL is a wrapper for MkdirAll on unix systems.
// ACL'd for Builtin Administrators and Local System. func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error {
func MkdirAllWithACL(path string, perm os.FileMode) error { return MkdirAll(path, perm, sddl)
return MkdirAll(path, perm)
} }
// MkdirAll creates a directory named path along with any necessary parents, // MkdirAll creates a directory named path along with any necessary parents,
// with permission specified by attribute perm for all dir created. // with permission specified by attribute perm for all dir created.
func MkdirAll(path string, perm os.FileMode) error { func MkdirAll(path string, perm os.FileMode, sddl string) error {
return os.MkdirAll(path, perm) return os.MkdirAll(path, perm)
} }
@ -24,7 +24,7 @@ func IsAbs(path string) bool {
return filepath.IsAbs(path) return filepath.IsAbs(path)
} }
// The functions below here are wrappers for the equivalents in the os package. // The functions below here are wrappers for the equivalents in the os and ioutils packages.
// They are passthrough on Unix platforms, and only relevant on Windows. // They are passthrough on Unix platforms, and only relevant on Windows.
// CreateSequential creates the named file with mode 0666 (before umask), truncating // CreateSequential creates the named file with mode 0666 (before umask), truncating
@ -52,3 +52,16 @@ func OpenSequential(name string) (*os.File, error) {
func OpenFileSequential(name string, flag int, perm os.FileMode) (*os.File, error) { func OpenFileSequential(name string, flag int, perm os.FileMode) (*os.File, error) {
return os.OpenFile(name, flag, perm) return os.OpenFile(name, flag, perm)
} }
// TempFileSequential creates a new temporary file in the directory dir
// with a name beginning with prefix, opens the file for reading
// and writing, and returns the resulting *os.File.
// If dir is the empty string, TempFile uses the default directory
// for temporary files (see os.TempDir).
// Multiple programs calling TempFile simultaneously
// will not choose the same file. The caller can use f.Name()
// to find the pathname of the file. It is the caller's responsibility
// to remove the file when no longer needed.
func TempFileSequential(dir, prefix string) (f *os.File, err error) {
return ioutil.TempFile(dir, prefix)
}

View File

@ -6,28 +6,39 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv"
"strings" "strings"
"sync"
"syscall" "syscall"
"time"
"unsafe" "unsafe"
winio "github.com/Microsoft/go-winio" winio "github.com/Microsoft/go-winio"
"golang.org/x/sys/windows"
)
const (
// SddlAdministratorsLocalSystem is local administrators plus NT AUTHORITY\System
SddlAdministratorsLocalSystem = "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)"
// SddlNtvmAdministratorsLocalSystem is NT VIRTUAL MACHINE\Virtual Machines plus local administrators plus NT AUTHORITY\System
SddlNtvmAdministratorsLocalSystem = "D:P(A;OICI;GA;;;S-1-5-83-0)(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)"
) )
// MkdirAllWithACL is a wrapper for MkdirAll that creates a directory // MkdirAllWithACL is a wrapper for MkdirAll that creates a directory
// ACL'd for Builtin Administrators and Local System. // with an appropriate SDDL defined ACL.
func MkdirAllWithACL(path string, perm os.FileMode) error { func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error {
return mkdirall(path, true) return mkdirall(path, true, sddl)
} }
// MkdirAll implementation that is volume path aware for Windows. // MkdirAll implementation that is volume path aware for Windows.
func MkdirAll(path string, _ os.FileMode) error { func MkdirAll(path string, _ os.FileMode, sddl string) error {
return mkdirall(path, false) return mkdirall(path, false, sddl)
} }
// mkdirall is a custom version of os.MkdirAll modified for use on Windows // mkdirall is a custom version of os.MkdirAll modified for use on Windows
// so that it is both volume path aware, and can create a directory with // so that it is both volume path aware, and can create a directory with
// a DACL. // a DACL.
func mkdirall(path string, adminAndLocalSystem bool) error { func mkdirall(path string, applyACL bool, sddl string) error {
if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) { if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) {
return nil return nil
} }
@ -61,15 +72,15 @@ func mkdirall(path string, adminAndLocalSystem bool) error {
if j > 1 { if j > 1 {
// Create parent // Create parent
err = mkdirall(path[0:j-1], false) err = mkdirall(path[0:j-1], false, sddl)
if err != nil { if err != nil {
return err return err
} }
} }
// Parent now exists; invoke os.Mkdir or mkdirWithACL and use its result. // Parent now exists; invoke os.Mkdir or mkdirWithACL and use its result.
if adminAndLocalSystem { if applyACL {
err = mkdirWithACL(path) err = mkdirWithACL(path, sddl)
} else { } else {
err = os.Mkdir(path, 0) err = os.Mkdir(path, 0)
} }
@ -89,13 +100,12 @@ func mkdirall(path string, adminAndLocalSystem bool) error {
// mkdirWithACL creates a new directory. If there is an error, it will be of // mkdirWithACL creates a new directory. If there is an error, it will be of
// type *PathError. . // type *PathError. .
// //
// This is a modified and combined version of os.Mkdir and syscall.Mkdir // This is a modified and combined version of os.Mkdir and windows.Mkdir
// in golang to cater for creating a directory am ACL permitting full // in golang to cater for creating a directory am ACL permitting full
// access, with inheritance, to any subfolder/file for Built-in Administrators // access, with inheritance, to any subfolder/file for Built-in Administrators
// and Local System. // and Local System.
func mkdirWithACL(name string) error { func mkdirWithACL(name string, sddl string) error {
sa := syscall.SecurityAttributes{Length: 0} sa := windows.SecurityAttributes{Length: 0}
sddl := "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)"
sd, err := winio.SddlToSecurityDescriptor(sddl) sd, err := winio.SddlToSecurityDescriptor(sddl)
if err != nil { if err != nil {
return &os.PathError{Op: "mkdir", Path: name, Err: err} return &os.PathError{Op: "mkdir", Path: name, Err: err}
@ -104,12 +114,12 @@ func mkdirWithACL(name string) error {
sa.InheritHandle = 1 sa.InheritHandle = 1
sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0])) sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0]))
namep, err := syscall.UTF16PtrFromString(name) namep, err := windows.UTF16PtrFromString(name)
if err != nil { if err != nil {
return &os.PathError{Op: "mkdir", Path: name, Err: err} return &os.PathError{Op: "mkdir", Path: name, Err: err}
} }
e := syscall.CreateDirectory(namep, &sa) e := windows.CreateDirectory(namep, &sa)
if e != nil { if e != nil {
return &os.PathError{Op: "mkdir", Path: name, Err: e} return &os.PathError{Op: "mkdir", Path: name, Err: e}
} }
@ -132,7 +142,7 @@ func IsAbs(path string) bool {
return true return true
} }
// The origin of the functions below here are the golang OS and syscall packages, // The origin of the functions below here are the golang OS and windows packages,
// slightly modified to only cope with files, not directories due to the // slightly modified to only cope with files, not directories due to the
// specific use case. // specific use case.
// //
@ -164,73 +174,125 @@ func OpenFileSequential(name string, flag int, _ os.FileMode) (*os.File, error)
if name == "" { if name == "" {
return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT} return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT}
} }
r, errf := syscallOpenFileSequential(name, flag, 0) r, errf := windowsOpenFileSequential(name, flag, 0)
if errf == nil { if errf == nil {
return r, nil return r, nil
} }
return nil, &os.PathError{Op: "open", Path: name, Err: errf} return nil, &os.PathError{Op: "open", Path: name, Err: errf}
} }
func syscallOpenFileSequential(name string, flag int, _ os.FileMode) (file *os.File, err error) { func windowsOpenFileSequential(name string, flag int, _ os.FileMode) (file *os.File, err error) {
r, e := syscallOpenSequential(name, flag|syscall.O_CLOEXEC, 0) r, e := windowsOpenSequential(name, flag|windows.O_CLOEXEC, 0)
if e != nil { if e != nil {
return nil, e return nil, e
} }
return os.NewFile(uintptr(r), name), nil return os.NewFile(uintptr(r), name), nil
} }
func makeInheritSa() *syscall.SecurityAttributes { func makeInheritSa() *windows.SecurityAttributes {
var sa syscall.SecurityAttributes var sa windows.SecurityAttributes
sa.Length = uint32(unsafe.Sizeof(sa)) sa.Length = uint32(unsafe.Sizeof(sa))
sa.InheritHandle = 1 sa.InheritHandle = 1
return &sa return &sa
} }
func syscallOpenSequential(path string, mode int, _ uint32) (fd syscall.Handle, err error) { func windowsOpenSequential(path string, mode int, _ uint32) (fd windows.Handle, err error) {
if len(path) == 0 { if len(path) == 0 {
return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND return windows.InvalidHandle, windows.ERROR_FILE_NOT_FOUND
} }
pathp, err := syscall.UTF16PtrFromString(path) pathp, err := windows.UTF16PtrFromString(path)
if err != nil { if err != nil {
return syscall.InvalidHandle, err return windows.InvalidHandle, err
} }
var access uint32 var access uint32
switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) { switch mode & (windows.O_RDONLY | windows.O_WRONLY | windows.O_RDWR) {
case syscall.O_RDONLY: case windows.O_RDONLY:
access = syscall.GENERIC_READ access = windows.GENERIC_READ
case syscall.O_WRONLY: case windows.O_WRONLY:
access = syscall.GENERIC_WRITE access = windows.GENERIC_WRITE
case syscall.O_RDWR: case windows.O_RDWR:
access = syscall.GENERIC_READ | syscall.GENERIC_WRITE access = windows.GENERIC_READ | windows.GENERIC_WRITE
} }
if mode&syscall.O_CREAT != 0 { if mode&windows.O_CREAT != 0 {
access |= syscall.GENERIC_WRITE access |= windows.GENERIC_WRITE
} }
if mode&syscall.O_APPEND != 0 { if mode&windows.O_APPEND != 0 {
access &^= syscall.GENERIC_WRITE access &^= windows.GENERIC_WRITE
access |= syscall.FILE_APPEND_DATA access |= windows.FILE_APPEND_DATA
} }
sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE) sharemode := uint32(windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE)
var sa *syscall.SecurityAttributes var sa *windows.SecurityAttributes
if mode&syscall.O_CLOEXEC == 0 { if mode&windows.O_CLOEXEC == 0 {
sa = makeInheritSa() sa = makeInheritSa()
} }
var createmode uint32 var createmode uint32
switch { switch {
case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL): case mode&(windows.O_CREAT|windows.O_EXCL) == (windows.O_CREAT | windows.O_EXCL):
createmode = syscall.CREATE_NEW createmode = windows.CREATE_NEW
case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC): case mode&(windows.O_CREAT|windows.O_TRUNC) == (windows.O_CREAT | windows.O_TRUNC):
createmode = syscall.CREATE_ALWAYS createmode = windows.CREATE_ALWAYS
case mode&syscall.O_CREAT == syscall.O_CREAT: case mode&windows.O_CREAT == windows.O_CREAT:
createmode = syscall.OPEN_ALWAYS createmode = windows.OPEN_ALWAYS
case mode&syscall.O_TRUNC == syscall.O_TRUNC: case mode&windows.O_TRUNC == windows.O_TRUNC:
createmode = syscall.TRUNCATE_EXISTING createmode = windows.TRUNCATE_EXISTING
default: default:
createmode = syscall.OPEN_EXISTING createmode = windows.OPEN_EXISTING
} }
// Use FILE_FLAG_SEQUENTIAL_SCAN rather than FILE_ATTRIBUTE_NORMAL as implemented in golang. // Use FILE_FLAG_SEQUENTIAL_SCAN rather than FILE_ATTRIBUTE_NORMAL as implemented in golang.
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx //https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
const fileFlagSequentialScan = 0x08000000 // FILE_FLAG_SEQUENTIAL_SCAN const fileFlagSequentialScan = 0x08000000 // FILE_FLAG_SEQUENTIAL_SCAN
h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, fileFlagSequentialScan, 0) h, e := windows.CreateFile(pathp, access, sharemode, sa, createmode, fileFlagSequentialScan, 0)
return h, e return h, e
} }
// Helpers for TempFileSequential
var rand uint32
var randmu sync.Mutex
func reseed() uint32 {
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
}
func nextSuffix() string {
randmu.Lock()
r := rand
if r == 0 {
r = reseed()
}
r = r*1664525 + 1013904223 // constants from Numerical Recipes
rand = r
randmu.Unlock()
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}
// TempFileSequential is a copy of ioutil.TempFile, modified to use sequential
// file access. Below is the original comment from golang:
// TempFile creates a new temporary file in the directory dir
// with a name beginning with prefix, opens the file for reading
// and writing, and returns the resulting *os.File.
// If dir is the empty string, TempFile uses the default directory
// for temporary files (see os.TempDir).
// Multiple programs calling TempFile simultaneously
// will not choose the same file. The caller can use f.Name()
// to find the pathname of the file. It is the caller's responsibility
// to remove the file when no longer needed.
func TempFileSequential(dir, prefix string) (f *os.File, err error) {
if dir == "" {
dir = os.TempDir()
}
nconflict := 0
for i := 0; i < 10000; i++ {
name := filepath.Join(dir, prefix+nextSuffix())
f, err = OpenFileSequential(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
rand = reseed()
randmu.Unlock()
}
continue
}
break
}
return
}

22
vendor/github.com/docker/docker/pkg/system/init.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
package system
import (
"syscall"
"time"
"unsafe"
)
// Used by chtimes
var maxTime time.Time
func init() {
// chtimes initialization
if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 {
// This is a 64 bit timespec
// os.Chtimes limits time to the following
maxTime = time.Unix(0, 1<<63-1)
} else {
// This is a 32 bit timespec
maxTime = time.Unix(1<<31-1, 0)
}
}

View File

@ -0,0 +1,17 @@
package system
import "os"
// LCOWSupported determines if Linux Containers on Windows are supported.
// Note: This feature is in development (06/17) and enabled through an
// environment variable. At a future time, it will be enabled based
// on build number. @jhowardmsft
var lcowSupported = false
func init() {
// LCOW initialization
if os.Getenv("LCOW_SUPPORTED") != "" {
lcowSupported = true
}
}

View File

@ -0,0 +1,8 @@
// +build !windows
package system
// LCOWSupported returns true if Linux containers on Windows are supported.
func LCOWSupported() bool {
return false
}

View File

@ -0,0 +1,6 @@
package system
// LCOWSupported returns true if Linux containers on Windows are supported.
func LCOWSupported() bool {
return lcowSupported
}

View File

@ -1,25 +1,14 @@
// +build windows
package system package system
import ( import "os"
"os"
)
// Lstat calls os.Lstat to get a fileinfo interface back. // Lstat calls os.Lstat to get a fileinfo interface back.
// This is then copied into our own locally defined structure. // This is then copied into our own locally defined structure.
// Note the Linux version uses fromStatT to do the copy back,
// but that not strictly necessary when already in an OS specific module.
func Lstat(path string) (*StatT, error) { func Lstat(path string) (*StatT, error) {
fi, err := os.Lstat(path) fi, err := os.Lstat(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &StatT{ return fromStatT(&fi)
name: fi.Name(),
size: fi.Size(),
mode: fi.Mode(),
modTime: fi.ModTime(),
isDir: fi.IsDir()}, nil
} }

View File

@ -7,6 +7,7 @@ import (
"unsafe" "unsafe"
) )
// #cgo CFLAGS: -std=c99
// #cgo LDFLAGS: -lkstat // #cgo LDFLAGS: -lkstat
// #include <unistd.h> // #include <unistd.h>
// #include <stdlib.h> // #include <stdlib.h>

View File

@ -3,13 +3,13 @@
package system package system
import ( import (
"syscall" "golang.org/x/sys/unix"
) )
// Mknod creates a filesystem node (file, device special file or named pipe) named path // Mknod creates a filesystem node (file, device special file or named pipe) named path
// with attributes specified by mode and dev. // with attributes specified by mode and dev.
func Mknod(path string, mode uint32, dev int) error { func Mknod(path string, mode uint32, dev int) error {
return syscall.Mknod(path, mode, dev) return unix.Mknod(path, mode, dev)
} }
// Mkdev is used to build the value of linux devices (in /dev/) which specifies major // Mkdev is used to build the value of linux devices (in /dev/) which specifies major

21
vendor/github.com/docker/docker/pkg/system/path.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
package system
import "runtime"
const defaultUnixPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
// DefaultPathEnv is unix style list of directories to search for
// executables. Each directory is separated from the next by a colon
// ':' character .
func DefaultPathEnv(platform string) string {
if runtime.GOOS == "windows" {
if platform != runtime.GOOS && LCOWSupported() {
return defaultUnixPathEnv
}
// Deliberately empty on Windows containers on Windows as the default path will be set by
// the container. Docker has no context of what the default path should be.
return ""
}
return defaultUnixPathEnv
}

View File

@ -2,11 +2,6 @@
package system package system
// DefaultPathEnv is unix style list of directories to search for
// executables. Each directory is separated from the next by a colon
// ':' character .
const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
// CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter, // CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter,
// is the system drive. This is a no-op on Linux. // is the system drive. This is a no-op on Linux.
func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) { func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) {

View File

@ -8,15 +8,11 @@ import (
"strings" "strings"
) )
// DefaultPathEnv is deliberately empty on Windows as the default path will be set by
// the container. Docker has no context of what the default path should be.
const DefaultPathEnv = ""
// CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path. // CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path.
// This is used, for example, when validating a user provided path in docker cp. // This is used, for example, when validating a user provided path in docker cp.
// If a drive letter is supplied, it must be the system drive. The drive letter // If a drive letter is supplied, it must be the system drive. The drive letter
// is always removed. Also, it translates it to OS semantics (IOW / to \). We // is always removed. Also, it translates it to OS semantics (IOW / to \). We
// need the path in this syntax so that it can ultimately be contatenated with // need the path in this syntax so that it can ultimately be concatenated with
// a Windows long-path which doesn't support drive-letters. Examples: // a Windows long-path which doesn't support drive-letters. Examples:
// C: --> Fail // C: --> Fail
// C:\ --> \ // C:\ --> \

View File

@ -0,0 +1,24 @@
// +build linux freebsd solaris darwin
package system
import (
"syscall"
"golang.org/x/sys/unix"
)
// IsProcessAlive returns true if process with a given pid is running.
func IsProcessAlive(pid int) bool {
err := unix.Kill(pid, syscall.Signal(0))
if err == nil || err == unix.EPERM {
return true
}
return false
}
// KillProcess force-stops a process.
func KillProcess(pid int) {
unix.Kill(pid, unix.SIGKILL)
}

80
vendor/github.com/docker/docker/pkg/system/rm.go generated vendored Normal file
View File

@ -0,0 +1,80 @@
package system
import (
"os"
"syscall"
"time"
"github.com/docker/docker/pkg/mount"
"github.com/pkg/errors"
)
// EnsureRemoveAll wraps `os.RemoveAll` to check for specific errors that can
// often be remedied.
// Only use `EnsureRemoveAll` if you really want to make every effort to remove
// a directory.
//
// Because of the way `os.Remove` (and by extension `os.RemoveAll`) works, there
// can be a race between reading directory entries and then actually attempting
// to remove everything in the directory.
// These types of errors do not need to be returned since it's ok for the dir to
// be gone we can just retry the remove operation.
//
// This should not return a `os.ErrNotExist` kind of error under any circumstances
func EnsureRemoveAll(dir string) error {
notExistErr := make(map[string]bool)
// track retries
exitOnErr := make(map[string]int)
maxRetry := 5
// Attempt to unmount anything beneath this dir first
mount.RecursiveUnmount(dir)
for {
err := os.RemoveAll(dir)
if err == nil {
return err
}
pe, ok := err.(*os.PathError)
if !ok {
return err
}
if os.IsNotExist(err) {
if notExistErr[pe.Path] {
return err
}
notExistErr[pe.Path] = true
// There is a race where some subdir can be removed but after the parent
// dir entries have been read.
// So the path could be from `os.Remove(subdir)`
// If the reported non-existent path is not the passed in `dir` we
// should just retry, but otherwise return with no error.
if pe.Path == dir {
return nil
}
continue
}
if pe.Err != syscall.EBUSY {
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 exitOnErr[pe.Path] == maxRetry {
return err
}
exitOnErr[pe.Path]++
time.Sleep(100 * time.Millisecond)
}
}

View File

@ -1,10 +1,8 @@
package system package system
import ( import "syscall"
"syscall"
)
// fromStatT creates a system.StatT type from a syscall.Stat_t type // fromStatT converts a syscall.Stat_t type to a system.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) { func fromStatT(s *syscall.Stat_t) (*StatT, error) {
return &StatT{size: s.Size, return &StatT{size: s.Size,
mode: uint32(s.Mode), mode: uint32(s.Mode),
@ -13,20 +11,3 @@ func fromStatT(s *syscall.Stat_t) (*StatT, error) {
rdev: uint64(s.Rdev), rdev: uint64(s.Rdev),
mtim: s.Mtimespec}, nil mtim: s.Mtimespec}, nil
} }
// FromStatT loads a system.StatT from a syscall.Stat_t.
func FromStatT(s *syscall.Stat_t) (*StatT, error) {
return fromStatT(s)
}
// Stat takes a path to a file and returns
// a system.StatT type pertaining to that file.
//
// Throws an error if the file does not exist
func Stat(path string) (*StatT, error) {
s := &syscall.Stat_t{}
if err := syscall.Stat(path, s); err != nil {
return nil, err
}
return fromStatT(s)
}

View File

@ -1,8 +1,6 @@
package system package system
import ( import "syscall"
"syscall"
)
// fromStatT converts a syscall.Stat_t type to a system.Stat_t type // fromStatT converts a syscall.Stat_t type to a system.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) { func fromStatT(s *syscall.Stat_t) (*StatT, error) {
@ -13,15 +11,3 @@ func fromStatT(s *syscall.Stat_t) (*StatT, error) {
rdev: uint64(s.Rdev), rdev: uint64(s.Rdev),
mtim: s.Mtimespec}, nil mtim: s.Mtimespec}, nil
} }
// Stat takes a path to a file and returns
// a system.Stat_t type pertaining to that file.
//
// Throws an error if the file does not exist
func Stat(path string) (*StatT, error) {
s := &syscall.Stat_t{}
if err := syscall.Stat(path, s); err != nil {
return nil, err
}
return fromStatT(s)
}

View File

@ -1,33 +1,19 @@
package system package system
import ( import "syscall"
"syscall"
)
// fromStatT converts a syscall.Stat_t type to a system.Stat_t type // fromStatT converts a syscall.Stat_t type to a system.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) { func fromStatT(s *syscall.Stat_t) (*StatT, error) {
return &StatT{size: s.Size, return &StatT{size: s.Size,
mode: s.Mode, mode: uint32(s.Mode),
uid: s.Uid, uid: s.Uid,
gid: s.Gid, gid: s.Gid,
rdev: s.Rdev, rdev: uint64(s.Rdev),
mtim: s.Mtim}, nil mtim: s.Mtim}, nil
} }
// FromStatT exists only on linux, and loads a system.StatT from a // FromStatT converts a syscall.Stat_t type to a system.Stat_t type
// syscal.Stat_t. // This is exposed on Linux as pkg/archive/changes uses it.
func FromStatT(s *syscall.Stat_t) (*StatT, error) { func FromStatT(s *syscall.Stat_t) (*StatT, error) {
return fromStatT(s) return fromStatT(s)
} }
// Stat takes a path to a file and returns
// a system.StatT type pertaining to that file.
//
// Throws an error if the file does not exist
func Stat(path string) (*StatT, error) {
s := &syscall.Stat_t{}
if err := syscall.Stat(path, s); err != nil {
return nil, err
}
return fromStatT(s)
}

View File

@ -1,10 +1,8 @@
package system package system
import ( import "syscall"
"syscall"
)
// fromStatT creates a system.StatT type from a syscall.Stat_t type // fromStatT converts a syscall.Stat_t type to a system.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) { func fromStatT(s *syscall.Stat_t) (*StatT, error) {
return &StatT{size: s.Size, return &StatT{size: s.Size,
mode: uint32(s.Mode), mode: uint32(s.Mode),

View File

@ -1,12 +1,8 @@
// +build solaris
package system package system
import ( import "syscall"
"syscall"
)
// fromStatT creates a system.StatT type from a syscall.Stat_t type // fromStatT converts a syscall.Stat_t type to a system.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) { func fromStatT(s *syscall.Stat_t) (*StatT, error) {
return &StatT{size: s.Size, return &StatT{size: s.Size,
mode: uint32(s.Mode), mode: uint32(s.Mode),
@ -15,20 +11,3 @@ func fromStatT(s *syscall.Stat_t) (*StatT, error) {
rdev: uint64(s.Rdev), rdev: uint64(s.Rdev),
mtim: s.Mtim}, nil mtim: s.Mtim}, nil
} }
// FromStatT loads a system.StatT from a syscal.Stat_t.
func FromStatT(s *syscall.Stat_t) (*StatT, error) {
return fromStatT(s)
}
// Stat takes a path to a file and returns
// a system.StatT type pertaining to that file.
//
// Throws an error if the file does not exist
func Stat(path string) (*StatT, error) {
s := &syscall.Stat_t{}
if err := syscall.Stat(path, s); err != nil {
return nil, err
}
return fromStatT(s)
}

View File

@ -47,7 +47,14 @@ func (s StatT) Mtim() syscall.Timespec {
return s.mtim return s.mtim
} }
// GetLastModification returns file's last modification time. // Stat takes a path to a file and returns
func (s StatT) GetLastModification() syscall.Timespec { // a system.StatT type pertaining to that file.
return s.Mtim() //
// Throws an error if the file does not exist
func Stat(path string) (*StatT, error) {
s := &syscall.Stat_t{}
if err := syscall.Stat(path, s); err != nil {
return nil, err
}
return fromStatT(s)
} }

View File

@ -1,17 +0,0 @@
// +build !linux,!windows,!freebsd,!solaris,!openbsd,!darwin
package system
import (
"syscall"
)
// fromStatT creates a system.StatT type from a syscall.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) {
return &StatT{size: s.Size,
mode: uint32(s.Mode),
uid: s.Uid,
gid: s.Gid,
rdev: uint64(s.Rdev),
mtim: s.Mtimespec}, nil
}

View File

@ -1,5 +1,3 @@
// +build windows
package system package system
import ( import (
@ -8,18 +6,11 @@ import (
) )
// StatT type contains status of a file. It contains metadata // StatT type contains status of a file. It contains metadata
// like name, permission, size, etc about a file. // like permission, size, etc about a file.
type StatT struct { type StatT struct {
name string mode os.FileMode
size int64 size int64
mode os.FileMode mtim time.Time
modTime time.Time
isDir bool
}
// Name returns file's name.
func (s StatT) Name() string {
return s.name
} }
// Size returns file's size. // Size returns file's size.
@ -29,15 +20,30 @@ func (s StatT) Size() int64 {
// Mode returns file's permission mode. // Mode returns file's permission mode.
func (s StatT) Mode() os.FileMode { func (s StatT) Mode() os.FileMode {
return s.mode return os.FileMode(s.mode)
} }
// ModTime returns file's last modification time. // Mtim returns file's last modification time.
func (s StatT) ModTime() time.Time { func (s StatT) Mtim() time.Time {
return s.modTime return time.Time(s.mtim)
} }
// IsDir returns whether file is actually a directory. // Stat takes a path to a file and returns
func (s StatT) IsDir() bool { // a system.StatT type pertaining to that file.
return s.isDir //
// Throws an error if the file does not exist
func Stat(path string) (*StatT, error) {
fi, err := os.Stat(path)
if err != nil {
return nil, err
}
return fromStatT(&fi)
}
// fromStatT converts a os.FileInfo type to a system.StatT type
func fromStatT(fi *os.FileInfo) (*StatT, error) {
return &StatT{
size: (*fi).Size(),
mode: (*fi).Mode(),
mtim: (*fi).ModTime()}, nil
} }

View File

@ -2,12 +2,12 @@
package system package system
import "syscall" import "golang.org/x/sys/unix"
// Unmount is a platform-specific helper function to call // Unmount is a platform-specific helper function to call
// the unmount syscall. // the unmount syscall.
func Unmount(dest string) error { func Unmount(dest string) error {
return syscall.Unmount(dest, 0) return unix.Unmount(dest, 0)
} }
// CommandLineToArgv should not be used on Unix. // CommandLineToArgv should not be used on Unix.

View File

@ -1,15 +1,16 @@
package system package system
import ( import (
"syscall"
"unsafe" "unsafe"
"github.com/Sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
) )
var ( var (
ntuserApiset = syscall.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0") ntuserApiset = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
procGetVersionExW = modkernel32.NewProc("GetVersionExW") procGetVersionExW = modkernel32.NewProc("GetVersionExW")
procGetProductInfo = modkernel32.NewProc("GetProductInfo")
) )
// OSVersion is a wrapper for Windows version information // OSVersion is a wrapper for Windows version information
@ -41,7 +42,7 @@ type osVersionInfoEx struct {
func GetOSVersion() OSVersion { func GetOSVersion() OSVersion {
var err error var err error
osv := OSVersion{} osv := OSVersion{}
osv.Version, err = syscall.GetVersion() osv.Version, err = windows.GetVersion()
if err != nil { if err != nil {
// GetVersion never fails. // GetVersion never fails.
panic(err) panic(err)
@ -66,6 +67,22 @@ func IsWindowsClient() bool {
return osviex.ProductType == verNTWorkstation return osviex.ProductType == verNTWorkstation
} }
// IsIoTCore returns true if the currently running image is based off of
// Windows 10 IoT Core.
// @engine maintainers - this function should not be removed or modified as it
// is used to enforce licensing restrictions on Windows.
func IsIoTCore() bool {
var returnedProductType uint32
r1, _, err := procGetProductInfo.Call(6, 1, 0, 0, uintptr(unsafe.Pointer(&returnedProductType)))
if r1 == 0 {
logrus.Warnf("GetProductInfo failed - assuming this is not IoT: %v", err)
return false
}
const productIoTUAP = 0x0000007B
const productIoTUAPCommercial = 0x00000083
return returnedProductType == productIoTUAP || returnedProductType == productIoTUAPCommercial
}
// Unmount is a platform-specific helper function to call // Unmount is a platform-specific helper function to call
// the unmount syscall. Not supported on Windows // the unmount syscall. Not supported on Windows
func Unmount(dest string) error { func Unmount(dest string) error {
@ -76,20 +93,20 @@ func Unmount(dest string) error {
func CommandLineToArgv(commandLine string) ([]string, error) { func CommandLineToArgv(commandLine string) ([]string, error) {
var argc int32 var argc int32
argsPtr, err := syscall.UTF16PtrFromString(commandLine) argsPtr, err := windows.UTF16PtrFromString(commandLine)
if err != nil { if err != nil {
return nil, err return nil, err
} }
argv, err := syscall.CommandLineToArgv(argsPtr, &argc) argv, err := windows.CommandLineToArgv(argsPtr, &argc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv)))) defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(argv))))
newArgs := make([]string, argc) newArgs := make([]string, argc)
for i, v := range (*argv)[:argc] { for i, v := range (*argv)[:argc] {
newArgs[i] = string(syscall.UTF16ToString((*v)[:])) newArgs[i] = string(windows.UTF16ToString((*v)[:]))
} }
return newArgs, nil return newArgs, nil

View File

@ -3,11 +3,11 @@
package system package system
import ( import (
"syscall" "golang.org/x/sys/unix"
) )
// Umask sets current process's file mode creation mask to newmask // Umask sets current process's file mode creation mask to newmask
// and returns oldmask. // and returns oldmask.
func Umask(newmask int) (oldmask int, err error) { func Umask(newmask int) (oldmask int, err error) {
return syscall.Umask(newmask), nil return unix.Umask(newmask), nil
} }

View File

@ -3,18 +3,20 @@ package system
import ( import (
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/sys/unix"
) )
// LUtimesNano is used to change access and modification time of the specified path. // LUtimesNano is used to change access and modification time of the specified path.
// It's used for symbol link file because syscall.UtimesNano doesn't support a NOFOLLOW flag atm. // It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm.
func LUtimesNano(path string, ts []syscall.Timespec) error { func LUtimesNano(path string, ts []syscall.Timespec) error {
var _path *byte var _path *byte
_path, err := syscall.BytePtrFromString(path) _path, err := unix.BytePtrFromString(path)
if err != nil { if err != nil {
return err return err
} }
if _, _, err := syscall.Syscall(syscall.SYS_LUTIMES, uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), 0); err != 0 && err != syscall.ENOSYS { if _, _, err := unix.Syscall(unix.SYS_LUTIMES, uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), 0); err != 0 && err != unix.ENOSYS {
return err return err
} }

View File

@ -3,22 +3,21 @@ package system
import ( import (
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/sys/unix"
) )
// LUtimesNano is used to change access and modification time of the specified path. // LUtimesNano is used to change access and modification time of the specified path.
// It's used for symbol link file because syscall.UtimesNano doesn't support a NOFOLLOW flag atm. // It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm.
func LUtimesNano(path string, ts []syscall.Timespec) error { func LUtimesNano(path string, ts []syscall.Timespec) error {
// These are not currently available in syscall atFdCwd := unix.AT_FDCWD
atFdCwd := -100
atSymLinkNoFollow := 0x100
var _path *byte var _path *byte
_path, err := syscall.BytePtrFromString(path) _path, err := unix.BytePtrFromString(path)
if err != nil { if err != nil {
return err return err
} }
if _, _, err := unix.Syscall6(unix.SYS_UTIMENSAT, uintptr(atFdCwd), uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), unix.AT_SYMLINK_NOFOLLOW, 0, 0); err != 0 && err != unix.ENOSYS {
if _, _, err := syscall.Syscall6(syscall.SYS_UTIMENSAT, uintptr(atFdCwd), uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), uintptr(atSymLinkNoFollow), 0, 0); err != 0 && err != syscall.ENOSYS {
return err return err
} }

View File

@ -1,63 +1,29 @@
package system package system
import ( import "golang.org/x/sys/unix"
"syscall"
"unsafe"
)
// Lgetxattr retrieves the value of the extended attribute identified by attr // Lgetxattr retrieves the value of the extended attribute identified by attr
// and associated with the given path in the file system. // and associated with the given path in the file system.
// It will returns a nil slice and nil error if the xattr is not set. // It will returns a nil slice and nil error if the xattr is not set.
func Lgetxattr(path string, attr string) ([]byte, error) { func Lgetxattr(path string, attr string) ([]byte, error) {
pathBytes, err := syscall.BytePtrFromString(path)
if err != nil {
return nil, err
}
attrBytes, err := syscall.BytePtrFromString(attr)
if err != nil {
return nil, err
}
dest := make([]byte, 128) dest := make([]byte, 128)
destBytes := unsafe.Pointer(&dest[0]) sz, errno := unix.Lgetxattr(path, attr, dest)
sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) if errno == unix.ENODATA {
if errno == syscall.ENODATA {
return nil, nil return nil, nil
} }
if errno == syscall.ERANGE { if errno == unix.ERANGE {
dest = make([]byte, sz) dest = make([]byte, sz)
destBytes := unsafe.Pointer(&dest[0]) sz, errno = unix.Lgetxattr(path, attr, dest)
sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
} }
if errno != 0 { if errno != nil {
return nil, errno return nil, errno
} }
return dest[:sz], nil return dest[:sz], nil
} }
var _zero uintptr
// Lsetxattr sets the value of the extended attribute identified by attr // Lsetxattr sets the value of the extended attribute identified by attr
// and associated with the given path in the file system. // and associated with the given path in the file system.
func Lsetxattr(path string, attr string, data []byte, flags int) error { func Lsetxattr(path string, attr string, data []byte, flags int) error {
pathBytes, err := syscall.BytePtrFromString(path) return unix.Lsetxattr(path, attr, data, flags)
if err != nil {
return err
}
attrBytes, err := syscall.BytePtrFromString(attr)
if err != nil {
return err
}
var dataBytes unsafe.Pointer
if len(data) > 0 {
dataBytes = unsafe.Pointer(&data[0])
} else {
dataBytes = unsafe.Pointer(&_zero)
}
_, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
if errno != 0 {
return errno
}
return nil
} }

View File

@ -1 +0,0 @@
../CONTRIBUTING.md

View File

@ -1,18 +0,0 @@
The Prometheus project was started by Matt T. Proud (emeritus) and
Julius Volz in 2012.
Maintainers of this repository:
* Björn Rabenstein <beorn@soundcloud.com>
The following individuals have contributed code to this repository
(listed in alphabetical order):
* Bernerd Schaefer <bj.schaefer@gmail.com>
* Björn Rabenstein <beorn@soundcloud.com>
* Daniel Bornkessel <daniel@soundcloud.com>
* Jeff Younker <jeff@drinktomi.com>
* Julius Volz <julius@soundcloud.com>
* Matt T. Proud <matt.proud@gmail.com>
* Tobias Schmidt <ts@soundcloud.com>

View File

@ -1,13 +0,0 @@
The Prometheus project was started by Matt T. Proud (emeritus) and
Julius Volz in 2012.
Maintainers of this repository:
* Björn Rabenstein <beorn@soundcloud.com>
The following individuals have contributed code to this repository
(listed in alphabetical order):
* Björn Rabenstein <beorn@soundcloud.com>
* Matt T. Proud <matt.proud@gmail.com>
* Tobias Schmidt <ts@soundcloud.com>