From 2d5b6cb925d3a30187b1feac9ea825cc275e0e8a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 30 Oct 2018 14:15:54 +0900 Subject: [PATCH] allow xattr error This commit allows ignoring errors during copying xattr like security.selinux, which is not always supported. Reported in several issues including * openfaas/openfaas-cloud#312 * moby/buildkit#704 * genuinetools/img#45 * https://bugzilla.redhat.com/show_bug.cgi?id=1596918 Signed-off-by: Akihiro Suda --- cmd/copy/main.go | 11 ++++-- vendor.conf | 2 +- .../github.com/tonistiigi/fsutil/copy/copy.go | 38 +++++++++++++++---- .../tonistiigi/fsutil/copy/copy_linux.go | 19 ---------- .../tonistiigi/fsutil/copy/copy_nowindows.go | 28 ++++++++++++++ .../tonistiigi/fsutil/copy/copy_unix.go | 19 ---------- 6 files changed, 67 insertions(+), 50 deletions(-) create mode 100644 vendor/github.com/tonistiigi/fsutil/copy/copy_nowindows.go diff --git a/cmd/copy/main.go b/cmd/copy/main.go index fbd9cb4..d2ebc66 100644 --- a/cmd/copy/main.go +++ b/cmd/copy/main.go @@ -134,10 +134,15 @@ func runCopy(ctx context.Context, args []string, opt opts) error { } func runCp(ctx context.Context, srcs []string, dest string, opt opts) error { + xattrErrorHandler := func(dst, src, key string, err error) error { + log.Println(err) + return nil + } for _, src := range srcs { - if err := copy.Copy(ctx, src, dest, copy.AllowWildcards, func(ci *copy.CopyInfo) { - ci.Chown = opt.chown - }); err != nil { + if err := copy.Copy(ctx, src, dest, copy.AllowWildcards, copy.WithXAttrErrorHandler(xattrErrorHandler), + func(ci *copy.CopyInfo) { + ci.Chown = opt.chown + }); err != nil { return errors.Wrapf(err, "failed to copy %s to %s", src, dest) } } diff --git a/vendor.conf b/vendor.conf index 8814960..457af82 100644 --- a/vendor.conf +++ b/vendor.conf @@ -1,5 +1,5 @@ github.com/moby/buildkit 277037a77f32b689df342c2ac7ea1c093be4b52e -github.com/tonistiigi/fsutil ecf259bc9d815143037535521910285f47f321ef +github.com/tonistiigi/fsutil 11b4bc7505e4558833cf30344d84e225766b21c1 github.com/containerd/continuity c6cef34830231743494fe2969284df7b82cc0ad0 github.com/pkg/errors e881fd58d78e04cf6d0de1217f8707c8cc2249bc github.com/containerd/containerd 1a560540b9a1ab7dcdf657502b2f4db0ae067b30 diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy.go b/vendor/github.com/tonistiigi/fsutil/copy/copy.go index ec2a07a..c4e0b96 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy.go @@ -37,7 +37,7 @@ func Copy(ctx context.Context, src, dst string, opts ...Opt) error { } dst = filepath.Clean(dst) - c := newCopier(ci.Chown) + c := newCopier(ci.Chown, ci.XAttrErrorHandler) srcs := []string{src} destRequiresDir := false @@ -97,9 +97,12 @@ type ChownOpt struct { Uid, Gid int } +type XAttrErrorHandler func(dst, src, xattrKey string, err error) error + type CopyInfo struct { - Chown *ChownOpt - AllowWildcards bool + Chown *ChownOpt + AllowWildcards bool + XAttrErrorHandler XAttrErrorHandler } type Opt func(*CopyInfo) @@ -114,13 +117,32 @@ func AllowWildcards(ci *CopyInfo) { ci.AllowWildcards = true } +func WithXAttrErrorHandler(h XAttrErrorHandler) Opt { + return func(ci *CopyInfo) { + ci.XAttrErrorHandler = h + } +} + +func AllowXAttrErrors(ci *CopyInfo) { + h := func(string, string, string, error) error { + return nil + } + WithXAttrErrorHandler(h)(ci) +} + type copier struct { - chown *ChownOpt - inodes map[uint64]string + chown *ChownOpt + inodes map[uint64]string + xattrErrorHandler XAttrErrorHandler } -func newCopier(chown *ChownOpt) *copier { - return &copier{inodes: map[uint64]string{}, chown: chown} +func newCopier(chown *ChownOpt, xeh XAttrErrorHandler) *copier { + if xeh == nil { + xeh = func(dst, src, key string, err error) error { + return err + } + } + return &copier{inodes: map[uint64]string{}, chown: chown, xattrErrorHandler: xeh} } // dest is always clean @@ -184,7 +206,7 @@ func (c *copier) copy(ctx context.Context, src, target string, overwriteTargetMe return errors.Wrap(err, "failed to copy file info") } - if err := copyXAttrs(target, src); err != nil { + if err := copyXAttrs(target, src, c.xattrErrorHandler); err != nil { return errors.Wrap(err, "failed to copy xattrs") } } diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go index b049de8..90cfe04 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go @@ -7,7 +7,6 @@ import ( "syscall" "github.com/containerd/containerd/sys" - "github.com/containerd/continuity/sysx" "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -77,24 +76,6 @@ func copyFileContent(dst, src *os.File) error { return nil } -func copyXAttrs(dst, src string) error { - xattrKeys, err := sysx.LListxattr(src) - if err != nil { - return errors.Wrapf(err, "failed to list xattrs on %s", src) - } - for _, xattr := range xattrKeys { - data, err := sysx.LGetxattr(src, xattr) - if err != nil { - return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) - } - if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil { - return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) - } - } - - return nil -} - func copyDevice(dst string, fi os.FileInfo) error { st, ok := fi.Sys().(*syscall.Stat_t) if !ok { diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_nowindows.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_nowindows.go new file mode 100644 index 0000000..cbd784e --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_nowindows.go @@ -0,0 +1,28 @@ +// +build !windows + +package fs + +import ( + "github.com/pkg/errors" + + "github.com/containerd/continuity/sysx" +) + +// copyXAttrs requires xeh to be non-nil +func copyXAttrs(dst, src string, xeh XAttrErrorHandler) error { + xattrKeys, err := sysx.LListxattr(src) + if err != nil { + return xeh(dst, src, "", errors.Wrapf(err, "failed to list xattrs on %s", src)) + } + for _, xattr := range xattrKeys { + data, err := sysx.LGetxattr(src, xattr) + if err != nil { + return xeh(dst, src, xattr, errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src)) + } + if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil { + return xeh(dst, src, xattr, errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst)) + } + } + + return nil +} diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go index 3a3e1cf..d9a6b40 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go @@ -8,7 +8,6 @@ import ( "syscall" "github.com/containerd/containerd/sys" - "github.com/containerd/continuity/sysx" "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -45,24 +44,6 @@ func copyFileContent(dst, src *os.File) error { return err } -func copyXAttrs(dst, src string) error { - xattrKeys, err := sysx.LListxattr(src) - if err != nil { - return errors.Wrapf(err, "failed to list xattrs on %s", src) - } - for _, xattr := range xattrKeys { - data, err := sysx.LGetxattr(src, xattr) - if err != nil { - return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) - } - if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil { - return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) - } - } - - return nil -} - func copyDevice(dst string, fi os.FileInfo) error { st, ok := fi.Sys().(*syscall.Stat_t) if !ok {