mirror of https://github.com/docker/docs.git
pkg/archive: adjust chmod bits on windows
This change modifies the chmod bits of build context archives built on windows to preserve the execute bit and remove the r/w bits from grp/others. Also adjusted integ-cli tests to verify permissions based on the platform the tests are running. Fixes #11047. Signed-off-by: Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
This commit is contained in:
parent
5929f401fc
commit
1a22418f9f
|
@ -690,15 +690,15 @@ func TestBuildSixtySteps(t *testing.T) {
|
||||||
func TestBuildAddSingleFileToRoot(t *testing.T) {
|
func TestBuildAddSingleFileToRoot(t *testing.T) {
|
||||||
name := "testaddimg"
|
name := "testaddimg"
|
||||||
defer deleteImages(name)
|
defer deleteImages(name)
|
||||||
ctx, err := fakeContext(`FROM busybox
|
ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
|
||||||
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
||||||
RUN echo 'dockerio:x:1001:' >> /etc/group
|
RUN echo 'dockerio:x:1001:' >> /etc/group
|
||||||
RUN touch /exists
|
RUN touch /exists
|
||||||
RUN chown dockerio.dockerio /exists
|
RUN chown dockerio.dockerio /exists
|
||||||
ADD test_file /
|
ADD test_file /
|
||||||
RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
|
RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
|
||||||
RUN [ $(ls -l /test_file | awk '{print $1}') = '-rw-r--r--' ]
|
RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
|
||||||
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
|
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"test_file": "test1",
|
"test_file": "test1",
|
||||||
})
|
})
|
||||||
|
@ -1263,7 +1263,7 @@ RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
|
||||||
func TestBuildAddWholeDirToRoot(t *testing.T) {
|
func TestBuildAddWholeDirToRoot(t *testing.T) {
|
||||||
name := "testaddwholedirtoroot"
|
name := "testaddwholedirtoroot"
|
||||||
defer deleteImages(name)
|
defer deleteImages(name)
|
||||||
ctx, err := fakeContext(`FROM busybox
|
ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
|
||||||
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
||||||
RUN echo 'dockerio:x:1001:' >> /etc/group
|
RUN echo 'dockerio:x:1001:' >> /etc/group
|
||||||
RUN touch /exists
|
RUN touch /exists
|
||||||
|
@ -1272,8 +1272,8 @@ ADD test_dir /test_dir
|
||||||
RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
|
RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
|
||||||
RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
|
RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
|
||||||
RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
|
RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
|
||||||
RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '-rw-r--r--' ]
|
RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
|
||||||
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
|
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"test_dir/test_file": "test1",
|
"test_dir/test_file": "test1",
|
||||||
})
|
})
|
||||||
|
@ -1336,15 +1336,15 @@ RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`,
|
||||||
func TestBuildCopySingleFileToRoot(t *testing.T) {
|
func TestBuildCopySingleFileToRoot(t *testing.T) {
|
||||||
name := "testcopysinglefiletoroot"
|
name := "testcopysinglefiletoroot"
|
||||||
defer deleteImages(name)
|
defer deleteImages(name)
|
||||||
ctx, err := fakeContext(`FROM busybox
|
ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
|
||||||
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
||||||
RUN echo 'dockerio:x:1001:' >> /etc/group
|
RUN echo 'dockerio:x:1001:' >> /etc/group
|
||||||
RUN touch /exists
|
RUN touch /exists
|
||||||
RUN chown dockerio.dockerio /exists
|
RUN chown dockerio.dockerio /exists
|
||||||
COPY test_file /
|
COPY test_file /
|
||||||
RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
|
RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
|
||||||
RUN [ $(ls -l /test_file | awk '{print $1}') = '-rw-r--r--' ]
|
RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
|
||||||
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
|
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"test_file": "test1",
|
"test_file": "test1",
|
||||||
})
|
})
|
||||||
|
@ -1496,7 +1496,7 @@ RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
|
||||||
func TestBuildCopyWholeDirToRoot(t *testing.T) {
|
func TestBuildCopyWholeDirToRoot(t *testing.T) {
|
||||||
name := "testcopywholedirtoroot"
|
name := "testcopywholedirtoroot"
|
||||||
defer deleteImages(name)
|
defer deleteImages(name)
|
||||||
ctx, err := fakeContext(`FROM busybox
|
ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
|
||||||
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
||||||
RUN echo 'dockerio:x:1001:' >> /etc/group
|
RUN echo 'dockerio:x:1001:' >> /etc/group
|
||||||
RUN touch /exists
|
RUN touch /exists
|
||||||
|
@ -1505,8 +1505,8 @@ COPY test_dir /test_dir
|
||||||
RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
|
RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
|
||||||
RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
|
RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
|
||||||
RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
|
RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
|
||||||
RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '-rw-r--r--' ]
|
RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
|
||||||
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
|
RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"test_dir/test_file": "test1",
|
"test_dir/test_file": "test1",
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,4 +5,6 @@ package main
|
||||||
const (
|
const (
|
||||||
// identifies if test suite is running on a unix platform
|
// identifies if test suite is running on a unix platform
|
||||||
isUnixCli = true
|
isUnixCli = true
|
||||||
|
|
||||||
|
expectedFileChmod = "-rw-r--r--"
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,4 +5,7 @@ package main
|
||||||
const (
|
const (
|
||||||
// identifies if test suite is running on a unix platform
|
// identifies if test suite is running on a unix platform
|
||||||
isUnixCli = false
|
isUnixCli = false
|
||||||
|
|
||||||
|
// this is the expected file permission set on windows: gh#11047
|
||||||
|
expectedFileChmod = "-rwx------"
|
||||||
)
|
)
|
||||||
|
|
|
@ -204,6 +204,7 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
|
||||||
|
|
||||||
name, err = canonicalTarName(name, fi.IsDir())
|
name, err = canonicalTarName(name, fi.IsDir())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -696,6 +697,8 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hdr.Name = filepath.Base(dst)
|
hdr.Name = filepath.Base(dst)
|
||||||
|
hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
|
||||||
|
|
||||||
tw := tar.NewWriter(w)
|
tw := tar.NewWriter(w)
|
||||||
defer tw.Close()
|
defer tw.Close()
|
||||||
if err := tw.WriteHeader(hdr); err != nil {
|
if err := tw.WriteHeader(hdr); err != nil {
|
||||||
|
|
|
@ -4,6 +4,7 @@ package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"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"
|
||||||
|
@ -16,6 +17,13 @@ func CanonicalTarNameForPath(p string) (string, error) {
|
||||||
return p, nil // already unix-style
|
return p, nil // already unix-style
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chmodTarEntry is used to adjust the file permissions used in tar header based
|
||||||
|
// on the platform the archival is done.
|
||||||
|
|
||||||
|
func chmodTarEntry(perm os.FileMode) os.FileMode {
|
||||||
|
return perm // noop for unix as golang APIs provide perm bits correctly
|
||||||
|
}
|
||||||
|
|
||||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
|
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
|
||||||
s, ok := stat.(*syscall.Stat_t)
|
s, ok := stat.(*syscall.Stat_t)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package archive
|
package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,3 +41,20 @@ func TestCanonicalTarName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestChmodTarEntry(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
in, expected os.FileMode
|
||||||
|
}{
|
||||||
|
{0000, 0000},
|
||||||
|
{0777, 0777},
|
||||||
|
{0644, 0644},
|
||||||
|
{0755, 0755},
|
||||||
|
{0444, 0444},
|
||||||
|
}
|
||||||
|
for _, v := range cases {
|
||||||
|
if out := chmodTarEntry(v.in); out != v.expected {
|
||||||
|
t.Fatalf("wrong chmod. expected:%v got:%v", v.expected, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"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"
|
||||||
|
@ -23,6 +24,17 @@ func CanonicalTarNameForPath(p string) (string, error) {
|
||||||
return strings.Replace(p, "\\", "/", -1), nil
|
return strings.Replace(p, "\\", "/", -1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chmodTarEntry is used to adjust the file permissions used in tar header based
|
||||||
|
// on the platform the archival is done.
|
||||||
|
func chmodTarEntry(perm os.FileMode) os.FileMode {
|
||||||
|
// Clear r/w on grp/others: no precise equivalen of group/others on NTFS.
|
||||||
|
perm &= 0711
|
||||||
|
// Add the x bit: make everything +x from windows
|
||||||
|
perm |= 0100
|
||||||
|
|
||||||
|
return perm
|
||||||
|
}
|
||||||
|
|
||||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
|
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
|
// do nothing. no notion of Rdev, Inode, Nlink in stat on Windows
|
||||||
return
|
return
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package archive
|
package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,3 +47,20 @@ func TestCanonicalTarName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestChmodTarEntry(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
in, expected os.FileMode
|
||||||
|
}{
|
||||||
|
{0000, 0100},
|
||||||
|
{0777, 0711},
|
||||||
|
{0644, 0700},
|
||||||
|
{0755, 0711},
|
||||||
|
{0444, 0500},
|
||||||
|
}
|
||||||
|
for _, v := range cases {
|
||||||
|
if out := chmodTarEntry(v.in); out != v.expected {
|
||||||
|
t.Fatalf("wrong chmod. expected:%v got:%v", v.expected, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue