diff --git a/pkg/tarsum/versioning.go b/pkg/tarsum/versioning.go index c475dd9fe0..890b70d455 100644 --- a/pkg/tarsum/versioning.go +++ b/pkg/tarsum/versioning.go @@ -119,9 +119,20 @@ func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) { var xattrs [][2]string for k, v := range h.PAXRecords { if xattr, ok := strings.CutPrefix(k, paxSchilyXattr); ok { + // h.Xattrs keys take precedence over h.PAXRecords keys, like + // archive/tar does when writing. + if vv, ok := h.Xattrs[xattr]; ok { //nolint:staticcheck // field deprecated in stdlib + v = vv + } xattrs = append(xattrs, [2]string{xattr, v}) } } + // Get extended attributes which are not in PAXRecords. + for k, v := range h.Xattrs { //nolint:staticcheck // field deprecated in stdlib + if _, ok := h.PAXRecords[paxSchilyXattr+k]; !ok { + xattrs = append(xattrs, [2]string{k, v}) + } + } sort.Slice(xattrs, func(i, j int) bool { return xattrs[i][0] < xattrs[j][0] }) // Make the slice with enough capacity to hold the 11 basic headers diff --git a/pkg/tarsum/versioning_test.go b/pkg/tarsum/versioning_test.go index 79b9cc9107..f9d174c4cc 100644 --- a/pkg/tarsum/versioning_test.go +++ b/pkg/tarsum/versioning_test.go @@ -1,7 +1,13 @@ package tarsum // import "github.com/docker/docker/pkg/tarsum" import ( + "archive/tar" + "fmt" + "strings" "testing" + + "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" ) func TestVersionLabelForChecksum(t *testing.T) { @@ -96,3 +102,29 @@ func containsVersion(versions []Version, version Version) bool { } return false } + +func TestSelectXattrsV1(t *testing.T) { + hdr := &tar.Header{ + Xattrs: map[string]string{ //nolint:staticcheck + "user.xattronly": "x", + "user.foo": "xattr", + }, + PAXRecords: map[string]string{ + "SCHILY.xattr.user.paxonly": "p", + "SCHILY.xattr.user.foo": "paxrecord", + }, + } + selected := v1TarHeaderSelect(hdr) + + var s strings.Builder + for _, elem := range selected { + fmt.Fprintf(&s, "%s=%s\n", elem[0], elem[1]) + } + t.Logf("Selected headers:\n%s", s.String()) + + assert.Check(t, is.DeepEqual(selected[len(selected)-3:], [][2]string{ + {"user.foo", "xattr"}, + {"user.paxonly", "p"}, + {"user.xattronly", "x"}, + })) +}