diff --git a/stat_test.go b/stat_test.go index 05eb0af..214866c 100644 --- a/stat_test.go +++ b/stat_test.go @@ -3,6 +3,8 @@ package fsutil import ( "os" "path/filepath" + "runtime" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -54,3 +56,16 @@ func TestStat(t *testing.T) { st.ModTime = 0 assert.Equal(t, &types.Stat{Path: "sock", Mode: 0755 /* ModeSocket not set */}, st) } + +func TestStat_SkipAppleXattrs(t *testing.T) { + if runtime.GOOS != "darwin" { + t.Skip("skipping test that requires darwin") + } + + st, err := Stat("Dockerfile") + assert.NoError(t, err) + + for key := range st.Xattrs { + assert.False(t, strings.HasPrefix(key, "com.apple.")) + } +} diff --git a/stat_unix.go b/stat_unix.go index def901e..94e5da0 100644 --- a/stat_unix.go +++ b/stat_unix.go @@ -5,6 +5,7 @@ package fsutil import ( "os" + "strings" "syscall" "github.com/containerd/continuity/sysx" @@ -12,6 +13,8 @@ import ( "github.com/tonistiigi/fsutil/types" ) +const xattrApplePrefix = "com.apple." + func loadXattr(origpath string, stat *types.Stat) error { xattrs, err := sysx.LListxattr(origpath) if err != nil { @@ -23,16 +26,29 @@ func loadXattr(origpath string, stat *types.Stat) error { if len(xattrs) > 0 { m := make(map[string][]byte) for _, key := range xattrs { - v, err := sysx.LGetxattr(origpath, key) - if err == nil { + if skipXattr(key) { + continue + } + + if v, err := sysx.LGetxattr(origpath, key); err == nil { m[key] = v } } - stat.Xattrs = m + + if len(m) > 0 { + stat.Xattrs = m + } } return nil } +func skipXattr(key string) bool { + if strings.HasPrefix(key, xattrApplePrefix) { + return true + } + return false +} + func setUnixOpt(fi os.FileInfo, stat *types.Stat, path string, seenFiles map[uint64]string) { s := fi.Sys().(*syscall.Stat_t)