mirror of https://github.com/docker/docs.git
Merge pull request #9113 from Azure/windows-client
Windows port of Docker Client
This commit is contained in:
commit
08201d021e
|
@ -4,6 +4,7 @@
|
||||||
.vagrant*
|
.vagrant*
|
||||||
bin
|
bin
|
||||||
docker/docker
|
docker/docker
|
||||||
|
*.exe
|
||||||
.*.swp
|
.*.swp
|
||||||
a.out
|
a.out
|
||||||
*.orig
|
*.orig
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build daemon
|
||||||
|
|
||||||
package graphdriver
|
package graphdriver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -192,20 +192,11 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
||||||
|
|
||||||
hdr.Name = name
|
hdr.Name = name
|
||||||
|
|
||||||
var (
|
nlink, inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
|
||||||
nlink uint32
|
if err != nil {
|
||||||
inode uint64
|
return err
|
||||||
)
|
|
||||||
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)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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 {
|
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
|
oldStat := oldChild.stat
|
||||||
newStat := &newChild.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 ||
|
if oldStat.Mode() != newStat.Mode() ||
|
||||||
oldStat.Uid != newStat.Uid ||
|
oldStat.Uid() != newStat.Uid() ||
|
||||||
oldStat.Gid != newStat.Gid ||
|
oldStat.Gid() != newStat.Gid() ||
|
||||||
oldStat.Rdev != newStat.Rdev ||
|
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) ||
|
(oldStat.Size() != newStat.Size() && oldStat.Mode()&syscall.S_IFDIR != syscall.S_IFDIR) ||
|
||||||
!sameFsTimeSpec(system.GetLastModification(oldStat), system.GetLastModification(newStat)) ||
|
!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()
|
||||||
|
|
|
@ -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)
|
oldmask, err := system.Umask(0)
|
||||||
defer syscall.Umask(oldmask)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
layer, err := DecompressStream(layer)
|
defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform
|
||||||
|
|
||||||
|
layer, err = DecompressStream(layer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
||||||
|
}
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
|
@ -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")
|
||||||
|
}
|
|
@ -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"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetLastAccess(stat *syscall.Stat_t) syscall.Timespec {
|
func fromStatT(s *syscall.Stat_t) (*Stat, error) {
|
||||||
return stat.Atim
|
return &Stat{size: s.Size,
|
||||||
}
|
mode: s.Mode,
|
||||||
|
uid: s.Uid,
|
||||||
func GetLastModification(stat *syscall.Stat_t) syscall.Timespec {
|
gid: s.Gid,
|
||||||
return stat.Mtim
|
rdev: s.Rdev,
|
||||||
|
mtim: s.Mtim}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
package system
|
||||||
|
|
||||||
import "syscall"
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
func GetLastAccess(stat *syscall.Stat_t) syscall.Timespec {
|
func fromStatT(s *syscall.Stat_t) (*Stat, error) {
|
||||||
return stat.Atimespec
|
return &Stat{size: s.Size,
|
||||||
}
|
mode: uint32(s.Mode),
|
||||||
|
uid: s.Uid,
|
||||||
func GetLastModification(stat *syscall.Stat_t) syscall.Timespec {
|
gid: s.Gid,
|
||||||
return stat.Mtimespec
|
rdev: uint64(s.Rdev),
|
||||||
|
mtim: s.Mtimespec}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Umask(newmask int) (oldmask int, err error) {
|
||||||
|
return syscall.Umask(newmask), nil
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
package term
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -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
|
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"
|
echo "Created binary: $DEST/$BINARY_NAME"
|
||||||
ln -sf "docker-$VERSION" "$DEST/docker"
|
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) {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
func TempDir(rootDir string) (string, error) {
|
||||||
return os.TempDir(), nil
|
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"
|
"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
|
||||||
|
|
|
@ -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…
Reference in New Issue