mirror of https://github.com/golang/go.git
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 <thebrokentoaster@gmail.com> Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
5158aab7d6
commit
e4bde05104
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -71,6 +71,16 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
|
|||
}
|
||||
tw.hdr = *hdr // Shallow copy of Header
|
||||
|
||||
// Avoid usage of the legacy TypeRegA flag, and automatically promote
|
||||
// it to use TypeReg or TypeDir.
|
||||
if tw.hdr.Typeflag == TypeRegA {
|
||||
if strings.HasSuffix(tw.hdr.Name, "/") {
|
||||
tw.hdr.Typeflag = TypeDir
|
||||
} else {
|
||||
tw.hdr.Typeflag = TypeReg
|
||||
}
|
||||
}
|
||||
|
||||
// Round ModTime and ignore AccessTime and ChangeTime unless
|
||||
// the format is explicitly chosen.
|
||||
// This ensures nominal usage of WriteHeader (without specifying the format)
|
||||
|
|
|
|||
|
|
@ -461,6 +461,15 @@ func TestWriter(t *testing.T) {
|
|||
testHeader{Header{Name: strings.Repeat("123456789/", 30)}, nil},
|
||||
testClose{nil},
|
||||
},
|
||||
}, {
|
||||
// Automatically promote zero value of Typeflag depending on the name.
|
||||
file: "testdata/file-and-dir.tar",
|
||||
tests: []testFnc{
|
||||
testHeader{Header{Name: "small.txt", Size: 5}, nil},
|
||||
testWrite{"Kilts", 5, nil},
|
||||
testHeader{Header{Name: "dir/"}, nil},
|
||||
testClose{nil},
|
||||
},
|
||||
}}
|
||||
|
||||
equalError := func(x, y error) bool {
|
||||
|
|
@ -809,8 +818,8 @@ func TestValidTypeflagWithPAXHeader(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("Failed to read header: %s", err)
|
||||
}
|
||||
if header.Typeflag != 0 {
|
||||
t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag)
|
||||
if header.Typeflag != TypeReg {
|
||||
t.Fatalf("Typeflag should've been %d, found %d", TypeReg, header.Typeflag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue