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:
Ahmet Alp Balkan 2015-03-03 18:40:16 -08:00
parent 2a627ca2f7
commit 276ed4fec4
5 changed files with 59 additions and 0 deletions

View file

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

View file

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

View file

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

View file

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

View file

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