Merge pull request #9113 from Azure/windows-client
Windows port of Docker Client
This commit is contained in:
commit
08201d021e
41 changed files with 588 additions and 166 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,6 +4,7 @@
|
|||
.vagrant*
|
||||
bin
|
||||
docker/docker
|
||||
*.exe
|
||||
.*.swp
|
||||
a.out
|
||||
*.orig
|
||||
|
|
|
@ -68,7 +68,8 @@ RUN cd /usr/local/go/src && ./make.bash --no-clean 2>&1
|
|||
ENV DOCKER_CROSSPLATFORMS \
|
||||
linux/386 linux/arm \
|
||||
darwin/amd64 darwin/386 \
|
||||
freebsd/amd64 freebsd/386 freebsd/arm
|
||||
freebsd/amd64 freebsd/386 freebsd/arm \
|
||||
windows/amd64 windows/386
|
||||
# (set an explicit GOARM of 5 for maximum compatibility)
|
||||
ENV GOARM 5
|
||||
RUN cd /usr/local/go/src && bash -xc 'for platform in $DOCKER_CROSSPLATFORMS; do GOOS=${platform%/*} GOARCH=${platform##*/} ./make.bash --no-clean 2>&1; done'
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
"time"
|
||||
|
@ -608,7 +607,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
|
|||
signal.CatchAll(sigc)
|
||||
go func() {
|
||||
for s := range sigc {
|
||||
if s == syscall.SIGCHLD {
|
||||
if s == signal.SIGCHLD {
|
||||
continue
|
||||
}
|
||||
var sig string
|
||||
|
@ -619,7 +618,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
|
|||
}
|
||||
}
|
||||
if sig == "" {
|
||||
log.Errorf("Unsupported signal: %d. Discarding.", s)
|
||||
log.Errorf("Unsupported signal: %v. Discarding.", s)
|
||||
}
|
||||
if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, false)); err != nil {
|
||||
log.Debugf("Error sending signal: %s", err)
|
||||
|
@ -2184,7 +2183,7 @@ func (cli *DockerCli) CmdCreate(args ...string) error {
|
|||
flName = cmd.String([]string{"-name"}, "", "Assign a name to the container")
|
||||
)
|
||||
|
||||
config, hostConfig, cmd, err := runconfig.Parse(cmd, args, nil)
|
||||
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2220,7 +2219,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||
ErrConflictDetachAutoRemove = fmt.Errorf("Conflicting options: --rm and -d")
|
||||
)
|
||||
|
||||
config, hostConfig, cmd, err := runconfig.Parse(cmd, args, nil)
|
||||
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@ import (
|
|||
gosignal "os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/docker/docker/registry"
|
||||
|
@ -238,7 +238,7 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
|
|||
cli.resizeTty(id, isExec)
|
||||
|
||||
sigchan := make(chan os.Signal, 1)
|
||||
gosignal.Notify(sigchan, syscall.SIGWINCH)
|
||||
gosignal.Notify(sigchan, signal.SIGWINCH)
|
||||
go func() {
|
||||
for _ = range sigchan {
|
||||
cli.resizeTty(id, isExec)
|
||||
|
|
|
@ -183,7 +183,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
|
|||
runCmd.SetOutput(ioutil.Discard)
|
||||
runCmd.Usage = nil
|
||||
|
||||
config, _, _, err := runconfig.Parse(runCmd, append([]string{b.image}, args...), nil)
|
||||
config, _, _, err := runconfig.Parse(runCmd, append([]string{b.image}, args...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build daemon
|
||||
|
||||
package graphdriver
|
||||
|
||||
import (
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
|
@ -16,10 +17,17 @@ var (
|
|||
|
||||
func init() {
|
||||
if dockerCertPath == "" {
|
||||
dockerCertPath = filepath.Join(os.Getenv("HOME"), ".docker")
|
||||
dockerCertPath = filepath.Join(getHomeDir(), ".docker")
|
||||
}
|
||||
}
|
||||
|
||||
func getHomeDir() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return os.Getenv("USERPROFILE")
|
||||
}
|
||||
return os.Getenv("HOME")
|
||||
}
|
||||
|
||||
var (
|
||||
flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
|
||||
flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
|
||||
|
|
|
@ -661,7 +661,7 @@ func TestDefaultContainerName(t *testing.T) {
|
|||
daemon := mkDaemonFromEngine(eng, t)
|
||||
defer nuke(daemon)
|
||||
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -685,7 +685,7 @@ func TestRandomContainerName(t *testing.T) {
|
|||
daemon := mkDaemonFromEngine(eng, t)
|
||||
defer nuke(daemon)
|
||||
|
||||
config, _, _, err := parseRun([]string{GetTestImage(daemon).ID, "echo test"}, nil)
|
||||
config, _, _, err := parseRun([]string{GetTestImage(daemon).ID, "echo test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -716,7 +716,7 @@ func TestContainerNameValidation(t *testing.T) {
|
|||
{"abc-123_AAA.1", true},
|
||||
{"\000asdf", false},
|
||||
} {
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
|
||||
if err != nil {
|
||||
if !test.Valid {
|
||||
continue
|
||||
|
@ -757,7 +757,7 @@ func TestLinkChildContainer(t *testing.T) {
|
|||
daemon := mkDaemonFromEngine(eng, t)
|
||||
defer nuke(daemon)
|
||||
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -773,7 +773,7 @@ func TestLinkChildContainer(t *testing.T) {
|
|||
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
|
||||
}
|
||||
|
||||
config, _, _, err = parseRun([]string{GetTestImage(daemon).ID, "echo test"}, nil)
|
||||
config, _, _, err = parseRun([]string{GetTestImage(daemon).ID, "echo test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -799,7 +799,7 @@ func TestGetAllChildren(t *testing.T) {
|
|||
daemon := mkDaemonFromEngine(eng, t)
|
||||
defer nuke(daemon)
|
||||
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -815,7 +815,7 @@ func TestGetAllChildren(t *testing.T) {
|
|||
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
|
||||
}
|
||||
|
||||
config, _, _, err = parseRun([]string{unitTestImageID, "echo test"}, nil)
|
||||
config, _, _, err = parseRun([]string{unitTestImageID, "echo test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ func TestCreateNumberHostname(t *testing.T) {
|
|||
eng := NewTestEngine(t)
|
||||
defer mkDaemonFromEngine(eng, t).Nuke()
|
||||
|
||||
config, _, _, err := parseRun([]string{"-h", "web.0", unitTestImageID, "echo test"}, nil)
|
||||
config, _, _, err := parseRun([]string{"-h", "web.0", unitTestImageID, "echo test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func TestCommit(t *testing.T) {
|
|||
eng := NewTestEngine(t)
|
||||
defer mkDaemonFromEngine(eng, t).Nuke()
|
||||
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "/bin/cat"}, nil)
|
||||
config, _, _, err := parseRun([]string{unitTestImageID, "/bin/cat"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ func TestMergeConfigOnCommit(t *testing.T) {
|
|||
container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t)
|
||||
defer runtime.Destroy(container1)
|
||||
|
||||
config, _, _, err := parseRun([]string{container1.ID, "cat /tmp/foo"}, nil)
|
||||
config, _, _, err := parseRun([]string{container1.ID, "cat /tmp/foo"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ func TestRestartKillWait(t *testing.T) {
|
|||
runtime := mkDaemonFromEngine(eng, t)
|
||||
defer runtime.Nuke()
|
||||
|
||||
config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
|
||||
config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
|
|||
eng := NewTestEngine(t)
|
||||
defer mkDaemonFromEngine(eng, t).Nuke()
|
||||
|
||||
config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
|
||||
config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/engine"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/utils"
|
||||
)
|
||||
|
@ -250,7 +249,7 @@ func readFile(src string, t *testing.T) (content string) {
|
|||
// The caller is responsible for destroying the container.
|
||||
// Call t.Fatal() at the first error.
|
||||
func mkContainer(r *daemon.Daemon, args []string, t *testing.T) (*daemon.Container, *runconfig.HostConfig, error) {
|
||||
config, hc, _, err := parseRun(args, nil)
|
||||
config, hc, _, err := parseRun(args)
|
||||
defer func() {
|
||||
if err != nil && t != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -351,9 +350,9 @@ func getImages(eng *engine.Engine, t *testing.T, all bool, filter string) *engin
|
|||
|
||||
}
|
||||
|
||||
func parseRun(args []string, sysInfo *sysinfo.SysInfo) (*runconfig.Config, *runconfig.HostConfig, *flag.FlagSet, error) {
|
||||
func parseRun(args []string) (*runconfig.Config, *runconfig.HostConfig, *flag.FlagSet, error) {
|
||||
cmd := flag.NewFlagSet("run", flag.ContinueOnError)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
cmd.Usage = nil
|
||||
return runconfig.Parse(cmd, args, sysInfo)
|
||||
return runconfig.Parse(cmd, args)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
|
@ -151,13 +151,13 @@ func ValidatePath(val string) (string, error) {
|
|||
splited := strings.SplitN(val, ":", 2)
|
||||
if len(splited) == 1 {
|
||||
containerPath = splited[0]
|
||||
val = filepath.Clean(splited[0])
|
||||
val = path.Clean(splited[0])
|
||||
} else {
|
||||
containerPath = splited[1]
|
||||
val = fmt.Sprintf("%s:%s", splited[0], filepath.Clean(splited[1]))
|
||||
val = fmt.Sprintf("%s:%s", splited[0], path.Clean(splited[1]))
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(containerPath) {
|
||||
if !path.IsAbs(containerPath) {
|
||||
return val, fmt.Errorf("%s is not an absolute path", containerPath)
|
||||
}
|
||||
return val, nil
|
||||
|
|
|
@ -192,20 +192,11 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
|||
|
||||
hdr.Name = name
|
||||
|
||||
var (
|
||||
nlink uint32
|
||||
inode uint64
|
||||
)
|
||||
if stat, ok := fi.Sys().(*syscall.Stat_t); ok {
|
||||
nlink = uint32(stat.Nlink)
|
||||
inode = uint64(stat.Ino)
|
||||
// Currently go does not fill in the major/minors
|
||||
if stat.Mode&syscall.S_IFBLK == syscall.S_IFBLK ||
|
||||
stat.Mode&syscall.S_IFCHR == syscall.S_IFCHR {
|
||||
hdr.Devmajor = int64(major(uint64(stat.Rdev)))
|
||||
hdr.Devminor = int64(minor(uint64(stat.Rdev)))
|
||||
}
|
||||
nlink, inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if it's a regular file and has more than 1 link,
|
||||
// it's hardlinked, so set the type flag accordingly
|
||||
if fi.Mode().IsRegular() && nlink > 1 {
|
||||
|
@ -291,7 +282,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
|
|||
mode |= syscall.S_IFIFO
|
||||
}
|
||||
|
||||
if err := syscall.Mknod(path, mode, int(mkdev(hdr.Devmajor, hdr.Devminor))); err != nil {
|
||||
if err := system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
39
pkg/archive/archive_unix.go
Normal file
39
pkg/archive/archive_unix.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
// +build !windows
|
||||
|
||||
package archive
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
|
||||
)
|
||||
|
||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
|
||||
s, ok := stat.(*syscall.Stat_t)
|
||||
|
||||
if !ok {
|
||||
err = errors.New("cannot convert stat value to syscall.Stat_t")
|
||||
return
|
||||
}
|
||||
|
||||
nlink = uint32(s.Nlink)
|
||||
inode = uint64(s.Ino)
|
||||
|
||||
// Currently go does not fil in the major/minors
|
||||
if s.Mode&syscall.S_IFBLK == syscall.S_IFBLK ||
|
||||
s.Mode&syscall.S_IFCHR == syscall.S_IFCHR {
|
||||
hdr.Devmajor = int64(major(uint64(s.Rdev)))
|
||||
hdr.Devminor = int64(minor(uint64(s.Rdev)))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func major(device uint64) uint64 {
|
||||
return (device >> 8) & 0xfff
|
||||
}
|
||||
|
||||
func minor(device uint64) uint64 {
|
||||
return (device & 0xff) | ((device >> 12) & 0xfff00)
|
||||
}
|
12
pkg/archive/archive_windows.go
Normal file
12
pkg/archive/archive_windows.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build windows
|
||||
|
||||
package archive
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
|
||||
)
|
||||
|
||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
|
||||
// do nothing. no notion of Rdev, Inode, Nlink in stat on Windows
|
||||
return
|
||||
}
|
|
@ -135,7 +135,7 @@ func Changes(layers []string, rw string) ([]Change, error) {
|
|||
type FileInfo struct {
|
||||
parent *FileInfo
|
||||
name string
|
||||
stat syscall.Stat_t
|
||||
stat *system.Stat
|
||||
children map[string]*FileInfo
|
||||
capability []byte
|
||||
added bool
|
||||
|
@ -168,7 +168,7 @@ func (info *FileInfo) path() string {
|
|||
}
|
||||
|
||||
func (info *FileInfo) isDir() bool {
|
||||
return info.parent == nil || info.stat.Mode&syscall.S_IFDIR == syscall.S_IFDIR
|
||||
return info.parent == nil || info.stat.Mode()&syscall.S_IFDIR == syscall.S_IFDIR
|
||||
}
|
||||
|
||||
func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
|
||||
|
@ -199,21 +199,21 @@ func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
|
|||
oldChild, _ := oldChildren[name]
|
||||
if oldChild != nil {
|
||||
// change?
|
||||
oldStat := &oldChild.stat
|
||||
newStat := &newChild.stat
|
||||
oldStat := oldChild.stat
|
||||
newStat := newChild.stat
|
||||
// Note: We can't compare inode or ctime or blocksize here, because these change
|
||||
// when copying a file into a container. However, that is not generally a problem
|
||||
// because any content change will change mtime, and any status change should
|
||||
// be visible when actually comparing the stat fields. The only time this
|
||||
// breaks down is if some code intentionally hides a change by setting
|
||||
// back mtime
|
||||
if oldStat.Mode != newStat.Mode ||
|
||||
oldStat.Uid != newStat.Uid ||
|
||||
oldStat.Gid != newStat.Gid ||
|
||||
oldStat.Rdev != newStat.Rdev ||
|
||||
if oldStat.Mode() != newStat.Mode() ||
|
||||
oldStat.Uid() != newStat.Uid() ||
|
||||
oldStat.Gid() != newStat.Gid() ||
|
||||
oldStat.Rdev() != newStat.Rdev() ||
|
||||
// Don't look at size for dirs, its not a good measure of change
|
||||
(oldStat.Size != newStat.Size && oldStat.Mode&syscall.S_IFDIR != syscall.S_IFDIR) ||
|
||||
!sameFsTimeSpec(system.GetLastModification(oldStat), system.GetLastModification(newStat)) ||
|
||||
(oldStat.Size() != newStat.Size() && oldStat.Mode()&syscall.S_IFDIR != syscall.S_IFDIR) ||
|
||||
!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) ||
|
||||
bytes.Compare(oldChild.capability, newChild.capability) != 0 {
|
||||
change := Change{
|
||||
Path: newChild.path(),
|
||||
|
@ -299,9 +299,11 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) {
|
|||
parent: parent,
|
||||
}
|
||||
|
||||
if err := syscall.Lstat(path, &info.stat); err != nil {
|
||||
s, err := system.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info.stat = s
|
||||
|
||||
info.capability, _ = system.Lgetxattr(path, "security.capability")
|
||||
|
||||
|
@ -359,14 +361,6 @@ func ChangesSize(newDir string, changes []Change) int64 {
|
|||
return size
|
||||
}
|
||||
|
||||
func major(device uint64) uint64 {
|
||||
return (device >> 8) & 0xfff
|
||||
}
|
||||
|
||||
func minor(device uint64) uint64 {
|
||||
return (device & 0xff) | ((device >> 12) & 0xfff00)
|
||||
}
|
||||
|
||||
// ExportChanges produces an Archive from the provided changes, relative to dir.
|
||||
func ExportChanges(dir string, changes []Change) (Archive, error) {
|
||||
reader, writer := io.Pipe()
|
||||
|
|
|
@ -12,23 +12,21 @@ import (
|
|||
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
|
||||
|
||||
"github.com/docker/docker/pkg/pools"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
)
|
||||
|
||||
// Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes.
|
||||
// They are, from low to high: the lower 8 bits of the minor, then 12 bits of the major,
|
||||
// then the top 12 bits of the minor
|
||||
func mkdev(major int64, minor int64) uint32 {
|
||||
return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff))
|
||||
}
|
||||
|
||||
// ApplyLayer parses a diff in the standard layer format from `layer`, and
|
||||
// applies it to the directory `dest`.
|
||||
func ApplyLayer(dest string, layer ArchiveReader) error {
|
||||
// We need to be able to set any perms
|
||||
oldmask := syscall.Umask(0)
|
||||
defer syscall.Umask(oldmask)
|
||||
oldmask, err := system.Umask(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
layer, err := DecompressStream(layer)
|
||||
defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform
|
||||
|
||||
layer, err = DecompressStream(layer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
12
pkg/signal/signal_unix.go
Normal file
12
pkg/signal/signal_unix.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build !windows
|
||||
|
||||
package signal
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Signals used in api/client (no windows equivalent, use
|
||||
// invalid signals so they don't get handled)
|
||||
const SIGCHLD = syscall.SIGCHLD
|
||||
const SIGWINCH = syscall.SIGWINCH
|
12
pkg/signal/signal_windows.go
Normal file
12
pkg/signal/signal_windows.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build windows
|
||||
|
||||
package signal
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Signals used in api/client (no windows equivalent, use
|
||||
// invalid signals so they don't get handled)
|
||||
const SIGCHLD = syscall.Signal(0xff)
|
||||
const SIGWINCH = syscall.Signal(0xff)
|
16
pkg/system/lstat.go
Normal file
16
pkg/system/lstat.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
// +build !windows
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Lstat(path string) (*Stat, error) {
|
||||
s := &syscall.Stat_t{}
|
||||
err := syscall.Lstat(path, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fromStatT(s)
|
||||
}
|
25
pkg/system/lstat_test.go
Normal file
25
pkg/system/lstat_test.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLstat(t *testing.T) {
|
||||
file, invalid, _ := prepareFiles(t)
|
||||
|
||||
statFile, err := Lstat(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if statFile == nil {
|
||||
t.Fatal("returned empty stat for existing file")
|
||||
}
|
||||
|
||||
statInvalid, err := Lstat(invalid)
|
||||
if err == nil {
|
||||
t.Fatal("did not return error for non-existing file")
|
||||
}
|
||||
if statInvalid != nil {
|
||||
t.Fatal("returned non-nil stat for non-existing file")
|
||||
}
|
||||
}
|
8
pkg/system/lstat_windows.go
Normal file
8
pkg/system/lstat_windows.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
// +build windows
|
||||
|
||||
package system
|
||||
|
||||
func Lstat(path string) (*Stat, error) {
|
||||
// should not be called on cli code path
|
||||
return nil, ErrNotSupportedPlatform
|
||||
}
|
18
pkg/system/mknod.go
Normal file
18
pkg/system/mknod.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
// +build !windows
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Mknod(path string, mode uint32, dev int) error {
|
||||
return syscall.Mknod(path, mode, dev)
|
||||
}
|
||||
|
||||
// Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes.
|
||||
// They are, from low to high: the lower 8 bits of the minor, then 12 bits of the major,
|
||||
// then the top 12 bits of the minor
|
||||
func Mkdev(major int64, minor int64) uint32 {
|
||||
return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff))
|
||||
}
|
12
pkg/system/mknod_windows.go
Normal file
12
pkg/system/mknod_windows.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build windows
|
||||
|
||||
package system
|
||||
|
||||
func Mknod(path string, mode uint32, dev int) error {
|
||||
// should not be called on cli code path
|
||||
return ErrNotSupportedPlatform
|
||||
}
|
||||
|
||||
func Mkdev(major int64, minor int64) uint32 {
|
||||
panic("Mkdev not implemented on windows, should not be called on cli code")
|
||||
}
|
42
pkg/system/stat.go
Normal file
42
pkg/system/stat.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Stat struct {
|
||||
mode uint32
|
||||
uid uint32
|
||||
gid uint32
|
||||
rdev uint64
|
||||
size int64
|
||||
mtim syscall.Timespec
|
||||
}
|
||||
|
||||
func (s Stat) Mode() uint32 {
|
||||
return s.mode
|
||||
}
|
||||
|
||||
func (s Stat) Uid() uint32 {
|
||||
return s.uid
|
||||
}
|
||||
|
||||
func (s Stat) Gid() uint32 {
|
||||
return s.gid
|
||||
}
|
||||
|
||||
func (s Stat) Rdev() uint64 {
|
||||
return s.rdev
|
||||
}
|
||||
|
||||
func (s Stat) Size() int64 {
|
||||
return s.size
|
||||
}
|
||||
|
||||
func (s Stat) Mtim() syscall.Timespec {
|
||||
return s.mtim
|
||||
}
|
||||
|
||||
func (s Stat) GetLastModification() syscall.Timespec {
|
||||
return s.Mtim()
|
||||
}
|
|
@ -4,10 +4,11 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func GetLastAccess(stat *syscall.Stat_t) syscall.Timespec {
|
||||
return stat.Atim
|
||||
}
|
||||
|
||||
func GetLastModification(stat *syscall.Stat_t) syscall.Timespec {
|
||||
return stat.Mtim
|
||||
func fromStatT(s *syscall.Stat_t) (*Stat, error) {
|
||||
return &Stat{size: s.Size,
|
||||
mode: s.Mode,
|
||||
uid: s.Uid,
|
||||
gid: s.Gid,
|
||||
rdev: s.Rdev,
|
||||
mtim: s.Mtim}, nil
|
||||
}
|
||||
|
|
34
pkg/system/stat_test.go
Normal file
34
pkg/system/stat_test.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFromStatT(t *testing.T) {
|
||||
file, _, _ := prepareFiles(t)
|
||||
|
||||
stat := &syscall.Stat_t{}
|
||||
err := syscall.Lstat(file, stat)
|
||||
|
||||
s, err := fromStatT(stat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if stat.Mode != s.Mode() {
|
||||
t.Fatal("got invalid mode")
|
||||
}
|
||||
if stat.Uid != s.Uid() {
|
||||
t.Fatal("got invalid uid")
|
||||
}
|
||||
if stat.Gid != s.Gid() {
|
||||
t.Fatal("got invalid gid")
|
||||
}
|
||||
if stat.Rdev != s.Rdev() {
|
||||
t.Fatal("got invalid rdev")
|
||||
}
|
||||
if stat.Mtim != s.Mtim() {
|
||||
t.Fatal("got invalid mtim")
|
||||
}
|
||||
}
|
|
@ -1,13 +1,16 @@
|
|||
// +build !linux
|
||||
// +build !linux,!windows
|
||||
|
||||
package system
|
||||
|
||||
import "syscall"
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func GetLastAccess(stat *syscall.Stat_t) syscall.Timespec {
|
||||
return stat.Atimespec
|
||||
}
|
||||
|
||||
func GetLastModification(stat *syscall.Stat_t) syscall.Timespec {
|
||||
return stat.Mtimespec
|
||||
func fromStatT(s *syscall.Stat_t) (*Stat, error) {
|
||||
return &Stat{size: s.Size,
|
||||
mode: uint32(s.Mode),
|
||||
uid: s.Uid,
|
||||
gid: s.Gid,
|
||||
rdev: uint64(s.Rdev),
|
||||
mtim: s.Mtimespec}, nil
|
||||
}
|
||||
|
|
12
pkg/system/stat_windows.go
Normal file
12
pkg/system/stat_windows.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build windows
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func fromStatT(s *syscall.Win32FileAttributeData) (*Stat, error) {
|
||||
return nil, errors.New("fromStatT should not be called on windows path")
|
||||
}
|
11
pkg/system/umask.go
Normal file
11
pkg/system/umask.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
// +build !windows
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Umask(newmask int) (oldmask int, err error) {
|
||||
return syscall.Umask(newmask), nil
|
||||
}
|
8
pkg/system/umask_windows.go
Normal file
8
pkg/system/umask_windows.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
// +build windows
|
||||
|
||||
package system
|
||||
|
||||
func Umask(newmask int) (oldmask int, err error) {
|
||||
// should not be called on cli code path
|
||||
return 0, ErrNotSupportedPlatform
|
||||
}
|
87
pkg/term/console_windows.go
Normal file
87
pkg/term/console_windows.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
// +build windows
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Consts for Get/SetConsoleMode function
|
||||
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx
|
||||
ENABLE_ECHO_INPUT = 0x0004
|
||||
ENABLE_INSERT_MODE = 0x0020
|
||||
ENABLE_LINE_INPUT = 0x0002
|
||||
ENABLE_MOUSE_INPUT = 0x0010
|
||||
ENABLE_PROCESSED_INPUT = 0x0001
|
||||
ENABLE_QUICK_EDIT_MODE = 0x0040
|
||||
ENABLE_WINDOW_INPUT = 0x0008
|
||||
// If parameter is a screen buffer handle, additional values
|
||||
ENABLE_PROCESSED_OUTPUT = 0x0001
|
||||
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
|
||||
)
|
||||
|
||||
var kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
var (
|
||||
setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode")
|
||||
getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
|
||||
)
|
||||
|
||||
func GetConsoleMode(fileDesc uintptr) (uint32, error) {
|
||||
var mode uint32
|
||||
err := syscall.GetConsoleMode(syscall.Handle(fileDesc), &mode)
|
||||
return mode, err
|
||||
}
|
||||
|
||||
func SetConsoleMode(fileDesc uintptr, mode uint32) error {
|
||||
r, _, err := setConsoleModeProc.Call(fileDesc, uintptr(mode), 0)
|
||||
if r == 0 {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return syscall.EINVAL
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// types for calling GetConsoleScreenBufferInfo
|
||||
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
|
||||
type (
|
||||
SHORT int16
|
||||
|
||||
SMALL_RECT struct {
|
||||
Left SHORT
|
||||
Top SHORT
|
||||
Right SHORT
|
||||
Bottom SHORT
|
||||
}
|
||||
|
||||
COORD struct {
|
||||
X SHORT
|
||||
Y SHORT
|
||||
}
|
||||
|
||||
WORD uint16
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO struct {
|
||||
dwSize COORD
|
||||
dwCursorPosition COORD
|
||||
wAttributes WORD
|
||||
srWindow SMALL_RECT
|
||||
dwMaximumWindowSize COORD
|
||||
}
|
||||
)
|
||||
|
||||
func GetConsoleScreenBufferInfo(fileDesc uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
|
||||
var info CONSOLE_SCREEN_BUFFER_INFO
|
||||
r, _, err := getConsoleScreenBufferInfoProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&info)), 0)
|
||||
if r == 0 {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
return &info, nil
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
// +build !windows
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
|
|
89
pkg/term/term_windows.go
Normal file
89
pkg/term/term_windows.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
// +build windows
|
||||
|
||||
package term
|
||||
|
||||
type State struct {
|
||||
mode uint32
|
||||
}
|
||||
|
||||
type Winsize struct {
|
||||
Height uint16
|
||||
Width uint16
|
||||
x uint16
|
||||
y uint16
|
||||
}
|
||||
|
||||
func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||
ws := &Winsize{}
|
||||
var info *CONSOLE_SCREEN_BUFFER_INFO
|
||||
info, err := GetConsoleScreenBufferInfo(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ws.Height = uint16(info.srWindow.Right - info.srWindow.Left + 1)
|
||||
ws.Width = uint16(info.srWindow.Bottom - info.srWindow.Top + 1)
|
||||
|
||||
ws.x = 0 // todo azlinux -- this is the pixel size of the Window, and not currently used by any caller
|
||||
ws.y = 0
|
||||
|
||||
return ws, nil
|
||||
}
|
||||
|
||||
func SetWinsize(fd uintptr, ws *Winsize) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
_, e := GetConsoleMode(fd)
|
||||
return e == nil
|
||||
}
|
||||
|
||||
// Restore restores the terminal connected to the given file descriptor to a
|
||||
// previous state.
|
||||
func RestoreTerminal(fd uintptr, state *State) error {
|
||||
return SetConsoleMode(fd, state.mode)
|
||||
}
|
||||
|
||||
func SaveState(fd uintptr) (*State, error) {
|
||||
mode, e := GetConsoleMode(fd)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return &State{mode}, nil
|
||||
}
|
||||
|
||||
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings
|
||||
func DisableEcho(fd uintptr, state *State) error {
|
||||
state.mode &^= (ENABLE_ECHO_INPUT)
|
||||
state.mode |= (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)
|
||||
return SetConsoleMode(fd, state.mode)
|
||||
}
|
||||
|
||||
func SetRawTerminal(fd uintptr) (*State, error) {
|
||||
oldState, err := MakeRaw(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO (azlinux): implement handling interrupt and restore state of terminal
|
||||
return oldState, err
|
||||
}
|
||||
|
||||
// MakeRaw puts 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 state *State
|
||||
state, err := SaveState(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings
|
||||
state.mode &^= (ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)
|
||||
err = SetConsoleMode(fd, state.mode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return state, nil
|
||||
}
|
|
@ -2,16 +2,20 @@
|
|||
set -e
|
||||
|
||||
DEST=$1
|
||||
BINARY_NAME="docker-$VERSION"
|
||||
if [ "$(go env GOOS)" = 'windows' ]; then
|
||||
BINARY_NAME+='.exe'
|
||||
fi
|
||||
|
||||
go build \
|
||||
-o "$DEST/docker-$VERSION" \
|
||||
-o "$DEST/$BINARY_NAME" \
|
||||
"${BUILDFLAGS[@]}" \
|
||||
-ldflags "
|
||||
$LDFLAGS
|
||||
$LDFLAGS_STATIC_DOCKER
|
||||
" \
|
||||
./docker
|
||||
echo "Created binary: $DEST/docker-$VERSION"
|
||||
ln -sf "docker-$VERSION" "$DEST/docker"
|
||||
echo "Created binary: $DEST/$BINARY_NAME"
|
||||
ln -sf "$BINARY_NAME" "$DEST/docker"
|
||||
|
||||
hash_files "$DEST/docker-$VERSION"
|
||||
hash_files "$DEST/$BINARY_NAME"
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
func parse(t *testing.T, args string) (*Config, *HostConfig, error) {
|
||||
config, hostConfig, _, err := parseRun(strings.Split(args+" ubuntu bash", " "), nil)
|
||||
config, hostConfig, _, err := parseRun(strings.Split(args+" ubuntu bash", " "))
|
||||
return config, hostConfig, err
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"github.com/docker/docker/pkg/units"
|
||||
"github.com/docker/docker/utils"
|
||||
)
|
||||
|
@ -24,7 +23,7 @@ var (
|
|||
ErrConflictHostNetworkAndLinks = fmt.Errorf("Conflicting options: --net=host can't be used with links. This would result in undefined behavior.")
|
||||
)
|
||||
|
||||
func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||
func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||
var (
|
||||
// FIXME: use utils.ListOpts for attach and volumes?
|
||||
flAttach = opts.NewListOpts(opts.ValidateAttach)
|
||||
|
@ -88,11 +87,6 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config,
|
|||
return nil, nil, cmd, err
|
||||
}
|
||||
|
||||
// Check if the kernel supports memory limit cgroup.
|
||||
if sysInfo != nil && *flMemoryString != "" && !sysInfo.MemoryLimit {
|
||||
*flMemoryString = ""
|
||||
}
|
||||
|
||||
// Validate input params
|
||||
if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) {
|
||||
return nil, nil, cmd, ErrInvalidWorkingDirectory
|
||||
|
@ -302,11 +296,6 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config,
|
|||
RestartPolicy: restartPolicy,
|
||||
}
|
||||
|
||||
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
||||
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
||||
config.MemorySwap = -1
|
||||
}
|
||||
|
||||
// When allocating stdin in attached mode, close stdin at client disconnect
|
||||
if config.OpenStdin && config.AttachStdin {
|
||||
config.StdinOnce = true
|
||||
|
|
|
@ -6,14 +6,13 @@ import (
|
|||
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
)
|
||||
|
||||
func parseRun(args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||
func parseRun(args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||
cmd := flag.NewFlagSet("run", flag.ContinueOnError)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
cmd.Usage = nil
|
||||
return Parse(cmd, args, sysInfo)
|
||||
return Parse(cmd, args)
|
||||
}
|
||||
|
||||
func TestParseLxcConfOpt(t *testing.T) {
|
||||
|
@ -34,27 +33,27 @@ func TestParseLxcConfOpt(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNetHostname(t *testing.T) {
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "img", "cmd"}, nil); err != nil {
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "img", "cmd"}); err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if _, _, _, err := parseRun([]string{"--net=host", "img", "cmd"}, nil); err != nil {
|
||||
if _, _, _, err := parseRun([]string{"--net=host", "img", "cmd"}); err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=bridge", "img", "cmd"}, nil); err != nil {
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=bridge", "img", "cmd"}); err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=none", "img", "cmd"}, nil); err != nil {
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=none", "img", "cmd"}); err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=host", "img", "cmd"}, nil); err != ErrConflictNetworkHostname {
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=host", "img", "cmd"}); err != ErrConflictNetworkHostname {
|
||||
t.Fatalf("Expected error ErrConflictNetworkHostname, got: %s", err)
|
||||
}
|
||||
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=container:other", "img", "cmd"}, nil); err != ErrConflictNetworkHostname {
|
||||
if _, _, _, err := parseRun([]string{"-h=name", "--net=container:other", "img", "cmd"}); err != ErrConflictNetworkHostname {
|
||||
t.Fatalf("Expected error ErrConflictNetworkHostname, got: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// TempDir returns the default directory to use for temporary files.
|
||||
func TempDir(rootdir string) (string error) {
|
||||
return os.TempDir(), nil
|
||||
func TempDir(rootDir string) (string, error) {
|
||||
var tmpDir string
|
||||
if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
|
||||
tmpDir = filepath.Join(rootDir, "tmp")
|
||||
}
|
||||
err := os.MkdirAll(tmpDir, 0700)
|
||||
return tmpDir, err
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// TempDir returns the default directory to use for temporary files.
|
||||
func TempDir(rootDir string) (string, error) {
|
||||
var tmpDir string
|
||||
if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
|
||||
tmpDir = filepath.Join(rootDir, "tmp")
|
||||
}
|
||||
err := os.MkdirAll(tmpDir, 0700)
|
||||
return tmpDir, err
|
||||
}
|
|
@ -18,7 +18,6 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
|
@ -453,36 +452,6 @@ func ReadSymlinkedDirectory(path string) (string, error) {
|
|||
return realPath, nil
|
||||
}
|
||||
|
||||
// TreeSize walks a directory tree and returns its total size in bytes.
|
||||
func TreeSize(dir string) (size int64, err error) {
|
||||
data := make(map[uint64]struct{})
|
||||
err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, e error) error {
|
||||
// Ignore directory sizes
|
||||
if fileInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
s := fileInfo.Size()
|
||||
if fileInfo.IsDir() || s == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check inode to handle hard links correctly
|
||||
inode := fileInfo.Sys().(*syscall.Stat_t).Ino
|
||||
// inode is not a uint64 on all platforms. Cast it to avoid issues.
|
||||
if _, exists := data[uint64(inode)]; exists {
|
||||
return nil
|
||||
}
|
||||
// inode is not a uint64 on all platforms. Cast it to avoid issues.
|
||||
data[uint64(inode)] = struct{}{}
|
||||
|
||||
size += s
|
||||
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// ValidateContextDirectory checks if all the contents of the directory
|
||||
// can be read and returns an error if some files can't be read
|
||||
// symlinks which point to non-existing files don't trigger an error
|
||||
|
|
39
utils/utils_daemon.go
Normal file
39
utils/utils_daemon.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
// +build daemon
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// TreeSize walks a directory tree and returns its total size in bytes.
|
||||
func TreeSize(dir string) (size int64, err error) {
|
||||
data := make(map[uint64]struct{})
|
||||
err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, e error) error {
|
||||
// Ignore directory sizes
|
||||
if fileInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
s := fileInfo.Size()
|
||||
if fileInfo.IsDir() || s == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check inode to handle hard links correctly
|
||||
inode := fileInfo.Sys().(*syscall.Stat_t).Ino
|
||||
// inode is not a uint64 on all platforms. Cast it to avoid issues.
|
||||
if _, exists := data[uint64(inode)]; exists {
|
||||
return nil
|
||||
}
|
||||
// inode is not a uint64 on all platforms. Cast it to avoid issues.
|
||||
data[uint64(inode)] = struct{}{}
|
||||
|
||||
size += s
|
||||
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
Loading…
Add table
Reference in a new issue