From e4bde0510465eecd4c8a8293418b1cbed1e0e623 Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Mon, 1 Jan 2018 16:16:43 -0800 Subject: [PATCH] archive/tar: automatically promote TypeRegA Change Reader to promote TypeRegA to TypeReg in headers, unless their name have a trailing slash which is already promoted to TypeDir. This will allow client code to handle just TypeReg instead both TypeReg and TypeRegA. Change Writer to promote TypeRegA to TypeReg or TypeDir in the headers depending on whether the name has a trailing slash. This normalization is motivated by the specification (in pax(1)): 0 represents a regular file. For backwards-compatibility, a typeflag value of binary zero ( '\0' ) should be recognized as meaning a regular file when extracting files from the archive. Archives written with this version of the archive file format create regular files with a typeflag value of the ISO/IEC 646:1991 standard IRV '0'. Fixes #22768. Change-Id: I149ec55824580d446cdde5a0d7a0457ad7b03466 Reviewed-on: https://go-review.googlesource.com/85656 Reviewed-by: Joe Tsai Run-TryBot: Joe Tsai TryBot-Result: Gobot Gobot --- src/archive/tar/common.go | 7 +++++-- src/archive/tar/reader.go | 8 ++++++-- src/archive/tar/reader_test.go | 11 ++++++----- src/archive/tar/tar_test.go | 1 + src/archive/tar/testdata/file-and-dir.tar | Bin 0 -> 2560 bytes src/archive/tar/testdata/trailing-slash.tar | Bin 2560 -> 2560 bytes src/archive/tar/writer.go | 10 ++++++++++ src/archive/tar/writer_test.go | 13 +++++++++++-- 8 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 src/archive/tar/testdata/file-and-dir.tar diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go index 4a2c173bf3..89d1f38732 100644 --- a/src/archive/tar/common.go +++ b/src/archive/tar/common.go @@ -56,7 +56,7 @@ func (he headerError) Error() string { const ( // Type '0' indicates a regular file. TypeReg = '0' - TypeRegA = '\x00' // For legacy support; use TypeReg instead + TypeRegA = '\x00' // Deprecated: Use TypeReg instead. // Type '1' to '6' are header-only flags and may not have a data body. TypeLink = '1' // Hard link @@ -138,7 +138,10 @@ var basicKeys = map[string]bool{ // should do so by creating a new Header and copying the fields // that they are interested in preserving. type Header struct { - Typeflag byte // Type of header entry (should be TypeReg for most files) + // Typeflag is the type of header entry. + // The zero value is automatically promoted to either TypeReg or TypeDir + // depending on the presence of a trailing slash in Name. + Typeflag byte Name string // Name of file entry Linkname string // Target name of link (valid for TypeLink or TypeSymlink) diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go index f4eeb557be..6025e82b1b 100644 --- a/src/archive/tar/reader.go +++ b/src/archive/tar/reader.go @@ -131,8 +131,12 @@ loop: if gnuLongLink != "" { hdr.Linkname = gnuLongLink } - if hdr.Typeflag == TypeRegA && strings.HasSuffix(hdr.Name, "/") { - hdr.Typeflag = TypeDir // Legacy archives use trailing slash for directories + if hdr.Typeflag == TypeRegA { + if strings.HasSuffix(hdr.Name, "/") { + hdr.Typeflag = TypeDir // Legacy archives use trailing slash for directories + } else { + hdr.Typeflag = TypeReg + } } // The extended headers may have updated the size. diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go index a6832d33b1..0fc29eaab6 100644 --- a/src/archive/tar/reader_test.go +++ b/src/archive/tar/reader_test.go @@ -189,7 +189,7 @@ func TestReader(t *testing.T) { Gid: 5000, Size: 5, ModTime: time.Unix(1244593104, 0), - Typeflag: '\x00', + Typeflag: '0', }, { Name: "small2.txt", Mode: 0444, @@ -197,7 +197,7 @@ func TestReader(t *testing.T) { Gid: 5000, Size: 11, ModTime: time.Unix(1244593104, 0), - Typeflag: '\x00', + Typeflag: '0', }}, }, { file: "testdata/pax.tar", @@ -534,9 +534,10 @@ func TestReader(t *testing.T) { // a buggy pre-Go1.8 tar.Writer. file: "testdata/invalid-go17.tar", headers: []*Header{{ - Name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/foo", - Uid: 010000000, - ModTime: time.Unix(0, 0), + Name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/foo", + Uid: 010000000, + ModTime: time.Unix(0, 0), + Typeflag: '0', }}, }, { // USTAR archive with a regular entry with non-zero device numbers. diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go index af80d6e0c1..2676853122 100644 --- a/src/archive/tar/tar_test.go +++ b/src/archive/tar/tar_test.go @@ -306,6 +306,7 @@ func TestRoundTrip(t *testing.T) { ModTime: time.Now().Round(time.Second), PAXRecords: map[string]string{"uid": "2097152"}, Format: FormatPAX, + Typeflag: TypeReg, } if err := tw.WriteHeader(hdr); err != nil { t.Fatalf("tw.WriteHeader: %v", err) diff --git a/src/archive/tar/testdata/file-and-dir.tar b/src/archive/tar/testdata/file-and-dir.tar new file mode 100644 index 0000000000000000000000000000000000000000..c18d4283e38097edf81165094a4635a473693e94 GIT binary patch literal 2560 zcmXTUP0Y#BE2$`9pdB!P00ta1P}meE2U5adU}$JyY|NlwKszTPOfD@hNh|_dj}Re` zh3+}>Org6j@64Q%V!GQpYT;lBft1W5eOkK(J!_!xL0r`QZ(we2V#J_eN^6IK%pc+T SpB_OxYR6~@jE2DA3;_VVvLvAZ literal 0 HcmV?d00001 diff --git a/src/archive/tar/testdata/trailing-slash.tar b/src/archive/tar/testdata/trailing-slash.tar index bf1b2ec426b4999b111c7f0914fb1f2d52b91728..93718b3034879fba292186c38fae7a9e7be69801 100644 GIT binary patch delta 22 dcmZn=X%N{kgN4=HltICCvLIv1W=7WkEC5CX1^@s6 delta 21 ccmZn=X%N{kgN4P=fI(rhAY