Browse Source

Merge pull request #9113 from Azure/windows-client

Windows port of Docker Client
Tibor Vass 10 years ago
parent
commit
08201d021e

+ 1 - 0
.gitignore

@@ -4,6 +4,7 @@
 .vagrant*
 .vagrant*
 bin
 bin
 docker/docker
 docker/docker
+*.exe
 .*.swp
 .*.swp
 a.out
 a.out
 *.orig
 *.orig

+ 2 - 1
Dockerfile

@@ -68,7 +68,8 @@ RUN	cd /usr/local/go/src && ./make.bash --no-clean 2>&1
 ENV	DOCKER_CROSSPLATFORMS	\
 ENV	DOCKER_CROSSPLATFORMS	\
 	linux/386 linux/arm \
 	linux/386 linux/arm \
 	darwin/amd64 darwin/386 \
 	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)
 # (set an explicit GOARM of 5 for maximum compatibility)
 ENV	GOARM	5
 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'
 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'

+ 4 - 5
api/client/commands.go

@@ -18,7 +18,6 @@ import (
 	"runtime"
 	"runtime"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
-	"syscall"
 	"text/tabwriter"
 	"text/tabwriter"
 	"text/template"
 	"text/template"
 	"time"
 	"time"
@@ -608,7 +607,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
 	signal.CatchAll(sigc)
 	signal.CatchAll(sigc)
 	go func() {
 	go func() {
 		for s := range sigc {
 		for s := range sigc {
-			if s == syscall.SIGCHLD {
+			if s == signal.SIGCHLD {
 				continue
 				continue
 			}
 			}
 			var sig string
 			var sig string
@@ -619,7 +618,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
 				}
 				}
 			}
 			}
 			if sig == "" {
 			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 {
 			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)
 				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")
 		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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -2220,7 +2219,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
 		ErrConflictDetachAutoRemove           = fmt.Errorf("Conflicting options: --rm and -d")
 		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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 2 - 2
api/client/utils.go

@@ -14,12 +14,12 @@ import (
 	gosignal "os/signal"
 	gosignal "os/signal"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
-	"syscall"
 
 
 	log "github.com/Sirupsen/logrus"
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
+	"github.com/docker/docker/pkg/signal"
 	"github.com/docker/docker/pkg/stdcopy"
 	"github.com/docker/docker/pkg/stdcopy"
 	"github.com/docker/docker/pkg/term"
 	"github.com/docker/docker/pkg/term"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/registry"
@@ -238,7 +238,7 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
 	cli.resizeTty(id, isExec)
 	cli.resizeTty(id, isExec)
 
 
 	sigchan := make(chan os.Signal, 1)
 	sigchan := make(chan os.Signal, 1)
-	gosignal.Notify(sigchan, syscall.SIGWINCH)
+	gosignal.Notify(sigchan, signal.SIGWINCH)
 	go func() {
 	go func() {
 		for _ = range sigchan {
 		for _ = range sigchan {
 			cli.resizeTty(id, isExec)
 			cli.resizeTty(id, isExec)

+ 1 - 1
builder/dispatchers.go

@@ -183,7 +183,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
 	runCmd.SetOutput(ioutil.Discard)
 	runCmd.SetOutput(ioutil.Discard)
 	runCmd.Usage = nil
 	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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 2 - 0
daemon/graphdriver/fsdiff.go

@@ -1,3 +1,5 @@
+// +build daemon
+
 package graphdriver
 package graphdriver
 
 
 import (
 import (

+ 9 - 1
docker/flags.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
+	"runtime"
 
 
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
@@ -16,10 +17,17 @@ var (
 
 
 func init() {
 func init() {
 	if dockerCertPath == "" {
 	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 (
 var (
 	flVersion     = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
 	flVersion     = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
 	flDaemon      = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
 	flDaemon      = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")

+ 7 - 7
integration/runtime_test.go

@@ -661,7 +661,7 @@ func TestDefaultContainerName(t *testing.T) {
 	daemon := mkDaemonFromEngine(eng, t)
 	daemon := mkDaemonFromEngine(eng, t)
 	defer nuke(daemon)
 	defer nuke(daemon)
 
 
-	config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
+	config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -685,7 +685,7 @@ func TestRandomContainerName(t *testing.T) {
 	daemon := mkDaemonFromEngine(eng, t)
 	daemon := mkDaemonFromEngine(eng, t)
 	defer nuke(daemon)
 	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 {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -716,7 +716,7 @@ func TestContainerNameValidation(t *testing.T) {
 		{"abc-123_AAA.1", true},
 		{"abc-123_AAA.1", true},
 		{"\000asdf", false},
 		{"\000asdf", false},
 	} {
 	} {
-		config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
+		config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
 		if err != nil {
 		if err != nil {
 			if !test.Valid {
 			if !test.Valid {
 				continue
 				continue
@@ -757,7 +757,7 @@ func TestLinkChildContainer(t *testing.T) {
 	daemon := mkDaemonFromEngine(eng, t)
 	daemon := mkDaemonFromEngine(eng, t)
 	defer nuke(daemon)
 	defer nuke(daemon)
 
 
-	config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
+	config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		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)
 		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 {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -799,7 +799,7 @@ func TestGetAllChildren(t *testing.T) {
 	daemon := mkDaemonFromEngine(eng, t)
 	daemon := mkDaemonFromEngine(eng, t)
 	defer nuke(daemon)
 	defer nuke(daemon)
 
 
-	config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
+	config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		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)
 		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 {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 5 - 5
integration/server_test.go

@@ -12,7 +12,7 @@ func TestCreateNumberHostname(t *testing.T) {
 	eng := NewTestEngine(t)
 	eng := NewTestEngine(t)
 	defer mkDaemonFromEngine(eng, t).Nuke()
 	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 {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -24,7 +24,7 @@ func TestCommit(t *testing.T) {
 	eng := NewTestEngine(t)
 	eng := NewTestEngine(t)
 	defer mkDaemonFromEngine(eng, t).Nuke()
 	defer mkDaemonFromEngine(eng, t).Nuke()
 
 
-	config, _, _, err := parseRun([]string{unitTestImageID, "/bin/cat"}, nil)
+	config, _, _, err := parseRun([]string{unitTestImageID, "/bin/cat"})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		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)
 	container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t)
 	defer runtime.Destroy(container1)
 	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 {
 	if err != nil {
 		t.Error(err)
 		t.Error(err)
 	}
 	}
@@ -102,7 +102,7 @@ func TestRestartKillWait(t *testing.T) {
 	runtime := mkDaemonFromEngine(eng, t)
 	runtime := mkDaemonFromEngine(eng, t)
 	defer runtime.Nuke()
 	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 {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -163,7 +163,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
 	eng := NewTestEngine(t)
 	eng := NewTestEngine(t)
 	defer mkDaemonFromEngine(eng, t).Nuke()
 	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 {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 3 - 4
integration/utils_test.go

@@ -19,7 +19,6 @@ import (
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
-	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/utils"
 	"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.
 // The caller is responsible for destroying the container.
 // Call t.Fatal() at the first error.
 // Call t.Fatal() at the first error.
 func mkContainer(r *daemon.Daemon, args []string, t *testing.T) (*daemon.Container, *runconfig.HostConfig, 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() {
 	defer func() {
 		if err != nil && t != nil {
 		if err != nil && t != nil {
 			t.Fatal(err)
 			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 := flag.NewFlagSet("run", flag.ContinueOnError)
 	cmd.SetOutput(ioutil.Discard)
 	cmd.SetOutput(ioutil.Discard)
 	cmd.Usage = nil
 	cmd.Usage = nil
-	return runconfig.Parse(cmd, args, sysInfo)
+	return runconfig.Parse(cmd, args)
 }
 }

+ 4 - 4
opts/opts.go

@@ -5,7 +5,7 @@ import (
 	"net"
 	"net"
 	"net/url"
 	"net/url"
 	"os"
 	"os"
-	"path/filepath"
+	"path"
 	"regexp"
 	"regexp"
 	"strings"
 	"strings"
 
 
@@ -151,13 +151,13 @@ func ValidatePath(val string) (string, error) {
 	splited := strings.SplitN(val, ":", 2)
 	splited := strings.SplitN(val, ":", 2)
 	if len(splited) == 1 {
 	if len(splited) == 1 {
 		containerPath = splited[0]
 		containerPath = splited[0]
-		val = filepath.Clean(splited[0])
+		val = path.Clean(splited[0])
 	} else {
 	} else {
 		containerPath = splited[1]
 		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, fmt.Errorf("%s is not an absolute path", containerPath)
 	}
 	}
 	return val, nil
 	return val, nil

+ 5 - 14
pkg/archive/archive.go

@@ -192,20 +192,11 @@ func (ta *tarAppender) addTarFile(path, name string) error {
 
 
 	hdr.Name = name
 	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,
 	// if it's a regular file and has more than 1 link,
 	// it's hardlinked, so set the type flag accordingly
 	// it's hardlinked, so set the type flag accordingly
 	if fi.Mode().IsRegular() && nlink > 1 {
 	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
 			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
 			return err
 		}
 		}
 
 

+ 39 - 0
pkg/archive/archive_unix.go

@@ -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 - 0
pkg/archive/archive_windows.go

@@ -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
+}

+ 13 - 19
pkg/archive/changes.go

@@ -135,7 +135,7 @@ func Changes(layers []string, rw string) ([]Change, error) {
 type FileInfo struct {
 type FileInfo struct {
 	parent     *FileInfo
 	parent     *FileInfo
 	name       string
 	name       string
-	stat       syscall.Stat_t
+	stat       *system.Stat
 	children   map[string]*FileInfo
 	children   map[string]*FileInfo
 	capability []byte
 	capability []byte
 	added      bool
 	added      bool
@@ -168,7 +168,7 @@ func (info *FileInfo) path() string {
 }
 }
 
 
 func (info *FileInfo) isDir() bool {
 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) {
 func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
@@ -199,21 +199,21 @@ func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
 		oldChild, _ := oldChildren[name]
 		oldChild, _ := oldChildren[name]
 		if oldChild != nil {
 		if oldChild != nil {
 			// change?
 			// 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
 			// 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
 			// 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
 			// because any content change will change mtime, and any status change should
 			// be visible when actually comparing the stat fields. The only time this
 			// be visible when actually comparing the stat fields. The only time this
 			// breaks down is if some code intentionally hides a change by setting
 			// breaks down is if some code intentionally hides a change by setting
 			// back mtime
 			// 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
 				// 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 {
 				bytes.Compare(oldChild.capability, newChild.capability) != 0 {
 				change := Change{
 				change := Change{
 					Path: newChild.path(),
 					Path: newChild.path(),
@@ -299,9 +299,11 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) {
 			parent:   parent,
 			parent:   parent,
 		}
 		}
 
 
-		if err := syscall.Lstat(path, &info.stat); err != nil {
+		s, err := system.Lstat(path)
+		if err != nil {
 			return err
 			return err
 		}
 		}
+		info.stat = s
 
 
 		info.capability, _ = system.Lgetxattr(path, "security.capability")
 		info.capability, _ = system.Lgetxattr(path, "security.capability")
 
 
@@ -359,14 +361,6 @@ func ChangesSize(newDir string, changes []Change) int64 {
 	return size
 	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.
 // ExportChanges produces an Archive from the provided changes, relative to dir.
 func ExportChanges(dir string, changes []Change) (Archive, error) {
 func ExportChanges(dir string, changes []Change) (Archive, error) {
 	reader, writer := io.Pipe()
 	reader, writer := io.Pipe()

+ 8 - 10
pkg/archive/diff.go

@@ -12,23 +12,21 @@ import (
 	"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
 	"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/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
 // ApplyLayer parses a diff in the standard layer format from `layer`, and
 // applies it to the directory `dest`.
 // applies it to the directory `dest`.
 func ApplyLayer(dest string, layer ArchiveReader) error {
 func ApplyLayer(dest string, layer ArchiveReader) error {
 	// We need to be able to set any perms
 	// 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
+	}
+
+	defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform
 
 
-	layer, err := DecompressStream(layer)
+	layer, err = DecompressStream(layer)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 12 - 0
pkg/signal/signal_unix.go

@@ -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 - 0
pkg/signal/signal_windows.go

@@ -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 - 0
pkg/system/lstat.go

@@ -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 - 0
pkg/system/lstat_test.go

@@ -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 - 0
pkg/system/lstat_windows.go

@@ -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 - 0
pkg/system/mknod.go

@@ -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 - 0
pkg/system/mknod_windows.go

@@ -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 - 0
pkg/system/stat.go

@@ -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()
+}

+ 7 - 6
pkg/system/stat_linux.go

@@ -4,10 +4,11 @@ import (
 	"syscall"
 	"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 - 0
pkg/system/stat_test.go

@@ -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")
+	}
+}

+ 11 - 8
pkg/system/stat_unsupported.go

@@ -1,13 +1,16 @@
-// +build !linux
+// +build !linux,!windows
 
 
 package system
 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 - 0
pkg/system/stat_windows.go

@@ -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 - 0
pkg/system/umask.go

@@ -0,0 +1,11 @@
+// +build !windows
+
+package system
+
+import (
+	"syscall"
+)
+
+func Umask(newmask int) (oldmask int, err error) {
+	return syscall.Umask(newmask), nil
+}

+ 8 - 0
pkg/system/umask_windows.go

@@ -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 - 0
pkg/term/console_windows.go

@@ -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
+}

+ 2 - 0
pkg/term/term.go

@@ -1,3 +1,5 @@
+// +build !windows
+
 package term
 package term
 
 
 import (
 import (

+ 89 - 0
pkg/term/term_windows.go

@@ -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
+}

+ 8 - 4
project/make/binary

@@ -2,16 +2,20 @@
 set -e
 set -e
 
 
 DEST=$1
 DEST=$1
+BINARY_NAME="docker-$VERSION"
+if [ "$(go env GOOS)" = 'windows' ]; then
+	BINARY_NAME+='.exe'
+fi
 
 
 go build \
 go build \
-	-o "$DEST/docker-$VERSION" \
+	-o "$DEST/$BINARY_NAME" \
 	"${BUILDFLAGS[@]}" \
 	"${BUILDFLAGS[@]}" \
 	-ldflags "
 	-ldflags "
 		$LDFLAGS
 		$LDFLAGS
 		$LDFLAGS_STATIC_DOCKER
 		$LDFLAGS_STATIC_DOCKER
 	" \
 	" \
 	./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"

+ 1 - 1
runconfig/config_test.go

@@ -9,7 +9,7 @@ import (
 )
 )
 
 
 func parse(t *testing.T, args string) (*Config, *HostConfig, error) {
 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
 	return config, hostConfig, err
 }
 }
 
 

+ 1 - 12
runconfig/parse.go

@@ -10,7 +10,6 @@ import (
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers"
-	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/units"
 	"github.com/docker/docker/pkg/units"
 	"github.com/docker/docker/utils"
 	"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.")
 	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 (
 	var (
 		// FIXME: use utils.ListOpts for attach and volumes?
 		// FIXME: use utils.ListOpts for attach and volumes?
 		flAttach  = opts.NewListOpts(opts.ValidateAttach)
 		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
 		return nil, nil, cmd, err
 	}
 	}
 
 
-	// Check if the kernel supports memory limit cgroup.
-	if sysInfo != nil && *flMemoryString != "" && !sysInfo.MemoryLimit {
-		*flMemoryString = ""
-	}
-
 	// Validate input params
 	// Validate input params
 	if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) {
 	if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) {
 		return nil, nil, cmd, ErrInvalidWorkingDirectory
 		return nil, nil, cmd, ErrInvalidWorkingDirectory
@@ -302,11 +296,6 @@ func Parse(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config,
 		RestartPolicy:   restartPolicy,
 		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
 	// When allocating stdin in attached mode, close stdin at client disconnect
 	if config.OpenStdin && config.AttachStdin {
 	if config.OpenStdin && config.AttachStdin {
 		config.StdinOnce = true
 		config.StdinOnce = true

+ 8 - 9
runconfig/parse_test.go

@@ -6,14 +6,13 @@ import (
 
 
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/parsers"
 	"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 := flag.NewFlagSet("run", flag.ContinueOnError)
 	cmd.SetOutput(ioutil.Discard)
 	cmd.SetOutput(ioutil.Discard)
 	cmd.Usage = nil
 	cmd.Usage = nil
-	return Parse(cmd, args, sysInfo)
+	return Parse(cmd, args)
 }
 }
 
 
 func TestParseLxcConfOpt(t *testing.T) {
 func TestParseLxcConfOpt(t *testing.T) {
@@ -34,27 +33,27 @@ func TestParseLxcConfOpt(t *testing.T) {
 }
 }
 
 
 func TestNetHostname(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)
 		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)
 		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)
 		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)
 		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)
 		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)
 		t.Fatalf("Expected error ErrConflictNetworkHostname, got: %s", err)
 	}
 	}
 }
 }

+ 8 - 4
utils/tmpdir.go

@@ -1,12 +1,16 @@
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
-
 package utils
 package utils
 
 
 import (
 import (
 	"os"
 	"os"
+	"path/filepath"
 )
 )
 
 
 // TempDir returns the default directory to use for temporary files.
 // 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
 }
 }

+ 0 - 18
utils/tmpdir_unix.go

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

+ 0 - 31
utils/utils.go

@@ -18,7 +18,6 @@ import (
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
-	"syscall"
 
 
 	log "github.com/Sirupsen/logrus"
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/dockerversion"
@@ -453,36 +452,6 @@ func ReadSymlinkedDirectory(path string) (string, error) {
 	return realPath, nil
 	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
 // ValidateContextDirectory checks if all the contents of the directory
 // can be read and returns an error if some files can't be read
 // 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
 // symlinks which point to non-existing files don't trigger an error

+ 39 - 0
utils/utils_daemon.go

@@ -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
+}