diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2014-06-06 22:37:27 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2014-06-06 22:37:27 +0000 |
commit | 6736ef96eab222e58e6294f42be981a5afb59811 (patch) | |
tree | 2bc668fae9bf96f9a3988e0b0a16685bde8c4f0b /libgo/go/archive | |
parent | 38a138411da4206c53f9a153ee9c3624fce58a52 (diff) | |
download | gcc-6736ef96eab222e58e6294f42be981a5afb59811.zip gcc-6736ef96eab222e58e6294f42be981a5afb59811.tar.gz gcc-6736ef96eab222e58e6294f42be981a5afb59811.tar.bz2 |
libgo: Merge to master revision 19184.
The next revision, 19185, renames several runtime files, and
will be handled in a separate change.
From-SVN: r211328
Diffstat (limited to 'libgo/go/archive')
-rw-r--r-- | libgo/go/archive/tar/common.go | 2 | ||||
-rw-r--r-- | libgo/go/archive/tar/reader.go | 8 | ||||
-rw-r--r-- | libgo/go/archive/tar/reader_test.go | 48 | ||||
-rw-r--r-- | libgo/go/archive/tar/stat_atim.go | 2 | ||||
-rw-r--r-- | libgo/go/archive/tar/stat_unix.go | 2 | ||||
-rw-r--r-- | libgo/go/archive/tar/testdata/xattrs.tar | bin | 0 -> 5120 bytes | |||
-rw-r--r-- | libgo/go/archive/tar/writer.go | 6 | ||||
-rw-r--r-- | libgo/go/archive/tar/writer_test.go | 40 | ||||
-rw-r--r-- | libgo/go/archive/zip/reader_test.go | 28 | ||||
-rw-r--r-- | libgo/go/archive/zip/register.go | 41 | ||||
-rw-r--r-- | libgo/go/archive/zip/testdata/zip64-2.zip | bin | 0 -> 266 bytes | |||
-rw-r--r-- | libgo/go/archive/zip/writer_test.go | 18 |
12 files changed, 180 insertions, 15 deletions
diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go index 1b961e3..e8b973c 100644 --- a/libgo/go/archive/tar/common.go +++ b/libgo/go/archive/tar/common.go @@ -57,6 +57,7 @@ type Header struct { Devminor int64 // minor number of character or block device AccessTime time.Time // access time ChangeTime time.Time // status change time + Xattrs map[string]string } // File name constants from the tar spec. @@ -189,6 +190,7 @@ const ( paxSize = "size" paxUid = "uid" paxUname = "uname" + paxXattr = "SCHILY.xattr." paxNone = "" ) diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go index b2d62f3..7cb6e64 100644 --- a/libgo/go/archive/tar/reader.go +++ b/libgo/go/archive/tar/reader.go @@ -139,8 +139,14 @@ func mergePAX(hdr *Header, headers map[string]string) error { return err } hdr.Size = int64(size) + default: + if strings.HasPrefix(k, paxXattr) { + if hdr.Xattrs == nil { + hdr.Xattrs = make(map[string]string) + } + hdr.Xattrs[k[len(paxXattr):]] = v + } } - } return nil } diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go index 1285616..f84dbeb 100644 --- a/libgo/go/archive/tar/reader_test.go +++ b/libgo/go/archive/tar/reader_test.go @@ -161,6 +161,46 @@ var untarTests = []*untarTest{ }, }, }, + { + file: "testdata/xattrs.tar", + headers: []*Header{ + { + Name: "small.txt", + Mode: 0644, + Uid: 1000, + Gid: 10, + Size: 5, + ModTime: time.Unix(1386065770, 448252320), + Typeflag: '0', + Uname: "alex", + Gname: "wheel", + AccessTime: time.Unix(1389782991, 419875220), + ChangeTime: time.Unix(1389782956, 794414986), + Xattrs: map[string]string{ + "user.key": "value", + "user.key2": "value2", + // Interestingly, selinux encodes the terminating null inside the xattr + "security.selinux": "unconfined_u:object_r:default_t:s0\x00", + }, + }, + { + Name: "small2.txt", + Mode: 0644, + Uid: 1000, + Gid: 10, + Size: 11, + ModTime: time.Unix(1386065770, 449252304), + Typeflag: '0', + Uname: "alex", + Gname: "wheel", + AccessTime: time.Unix(1389782991, 419875220), + ChangeTime: time.Unix(1386065770, 449252304), + Xattrs: map[string]string{ + "security.selinux": "unconfined_u:object_r:default_t:s0\x00", + }, + }, + }, + }, } func TestReader(t *testing.T) { @@ -180,7 +220,7 @@ testLoop: f.Close() continue testLoop } - if *hdr != *header { + if !reflect.DeepEqual(*hdr, *header) { t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v", i, j, *hdr, *header) } @@ -253,7 +293,7 @@ func TestIncrementalRead(t *testing.T) { } // check the header - if *hdr != *headers[nread] { + if !reflect.DeepEqual(*hdr, *headers[nread]) { t.Errorf("Incorrect header:\nhave %+v\nwant %+v", *hdr, headers[nread]) } @@ -321,7 +361,7 @@ func TestParsePAXHeader(t *testing.T) { {"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}} for _, test := range paxTests { key, expected, raw := test[0], test[1], test[2] - reader := bytes.NewBuffer([]byte(raw)) + reader := bytes.NewReader([]byte(raw)) headers, err := parsePAX(reader) if err != nil { t.Errorf("Couldn't parse correctly formatted headers: %v", err) @@ -337,7 +377,7 @@ func TestParsePAXHeader(t *testing.T) { t.Error("Buffer wasn't consumed") } } - badHeader := bytes.NewBuffer([]byte("3 somelongkey=")) + badHeader := bytes.NewReader([]byte("3 somelongkey=")) if _, err := parsePAX(badHeader); err != ErrHeader { t.Fatal("Unexpected success when parsing bad header") } diff --git a/libgo/go/archive/tar/stat_atim.go b/libgo/go/archive/tar/stat_atim.go index 6029b08..cf9cc79 100644 --- a/libgo/go/archive/tar/stat_atim.go +++ b/libgo/go/archive/tar/stat_atim.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux openbsd +// +build linux dragonfly openbsd solaris package tar diff --git a/libgo/go/archive/tar/stat_unix.go b/libgo/go/archive/tar/stat_unix.go index 92bc924..cb843db 100644 --- a/libgo/go/archive/tar/stat_unix.go +++ b/libgo/go/archive/tar/stat_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux darwin freebsd openbsd netbsd +// +build linux darwin dragonfly freebsd openbsd netbsd solaris package tar diff --git a/libgo/go/archive/tar/testdata/xattrs.tar b/libgo/go/archive/tar/testdata/xattrs.tar Binary files differnew file mode 100644 index 0000000..9701950 --- /dev/null +++ b/libgo/go/archive/tar/testdata/xattrs.tar diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go index 549f146..9ee9499 100644 --- a/libgo/go/archive/tar/writer.go +++ b/libgo/go/archive/tar/writer.go @@ -236,6 +236,12 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error { return tw.err } + if allowPax { + for k, v := range hdr.Xattrs { + paxHeaders[paxXattr+k] = v + } + } + if len(paxHeaders) > 0 { if !allowPax { return errInvalidHeader diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go index 30ebf97..2b9ea65 100644 --- a/libgo/go/archive/tar/writer_test.go +++ b/libgo/go/archive/tar/writer_test.go @@ -10,6 +10,7 @@ import ( "io" "io/ioutil" "os" + "reflect" "strings" "testing" "testing/iotest" @@ -338,6 +339,45 @@ func TestPaxNonAscii(t *testing.T) { } } +func TestPaxXattrs(t *testing.T) { + xattrs := map[string]string{ + "user.key": "value", + } + + // Create an archive with an xattr + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + hdr, err := FileInfoHeader(fileinfo, "") + if err != nil { + t.Fatalf("os.Stat: %v", err) + } + contents := "Kilts" + hdr.Xattrs = xattrs + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if _, err = writer.Write([]byte(contents)); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Test that we can get the xattrs back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(hdr.Xattrs, xattrs) { + t.Fatalf("xattrs did not survive round trip: got %+v, want %+v", + hdr.Xattrs, xattrs) + } +} + func TestPAXHeader(t *testing.T) { medName := strings.Repeat("CD", 50) longName := strings.Repeat("AB", 100) diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go index 78875ec..5652f3a 100644 --- a/libgo/go/archive/zip/reader_test.go +++ b/libgo/go/archive/zip/reader_test.go @@ -235,6 +235,18 @@ var tests = []ZipTest{ }, }, }, + // Another zip64 file with different Extras fields. (golang.org/issue/7069) + { + Name: "zip64-2.zip", + File: []ZipTestFile{ + { + Name: "README", + Content: []byte("This small file is in ZIP64 format.\n"), + Mtime: "08-10-12 14:33:32", + Mode: 0644, + }, + }, + }, } var crossPlatform = []ZipTestFile{ @@ -343,19 +355,13 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { testFileMode(t, zt.Name, f, ft.Mode) - size0 := f.UncompressedSize - var b bytes.Buffer r, err := f.Open() if err != nil { - t.Error(err) + t.Errorf("%s: %v", zt.Name, err) return } - if size1 := f.UncompressedSize; size0 != size1 { - t.Errorf("file %q changed f.UncompressedSize from %d to %d", f.Name, size0, size1) - } - _, err = io.Copy(&b, r) if err != ft.ContentErr { t.Errorf("%s: copying contents: %v (want %v)", zt.Name, err, ft.ContentErr) @@ -365,6 +371,14 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { } r.Close() + size := uint64(f.UncompressedSize) + if size == uint32max { + size = f.UncompressedSize64 + } + if g := uint64(b.Len()); g != size { + t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size) + } + var c []byte if ft.Content != nil { c = ft.Content diff --git a/libgo/go/archive/zip/register.go b/libgo/go/archive/zip/register.go index c046f08..4211ec7 100644 --- a/libgo/go/archive/zip/register.go +++ b/libgo/go/archive/zip/register.go @@ -6,6 +6,7 @@ package zip import ( "compress/flate" + "errors" "io" "io/ioutil" "sync" @@ -21,12 +22,50 @@ type Compressor func(io.Writer) (io.WriteCloser, error) // when they're finished reading. type Decompressor func(io.Reader) io.ReadCloser +var flateWriterPool sync.Pool + +func newFlateWriter(w io.Writer) io.WriteCloser { + fw, ok := flateWriterPool.Get().(*flate.Writer) + if ok { + fw.Reset(w) + } else { + fw, _ = flate.NewWriter(w, 5) + } + return &pooledFlateWriter{fw: fw} +} + +type pooledFlateWriter struct { + mu sync.Mutex // guards Close and Write + fw *flate.Writer +} + +func (w *pooledFlateWriter) Write(p []byte) (n int, err error) { + w.mu.Lock() + defer w.mu.Unlock() + if w.fw == nil { + return 0, errors.New("Write after Close") + } + return w.fw.Write(p) +} + +func (w *pooledFlateWriter) Close() error { + w.mu.Lock() + defer w.mu.Unlock() + var err error + if w.fw != nil { + err = w.fw.Close() + flateWriterPool.Put(w.fw) + w.fw = nil + } + return err +} + var ( mu sync.RWMutex // guards compressor and decompressor maps compressors = map[uint16]Compressor{ Store: func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }, - Deflate: func(w io.Writer) (io.WriteCloser, error) { return flate.NewWriter(w, 5) }, + Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }, } decompressors = map[uint16]Decompressor{ diff --git a/libgo/go/archive/zip/testdata/zip64-2.zip b/libgo/go/archive/zip/testdata/zip64-2.zip Binary files differnew file mode 100644 index 0000000..f844e35 --- /dev/null +++ b/libgo/go/archive/zip/testdata/zip64-2.zip diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go index 8b1c4df..4bfa870 100644 --- a/libgo/go/archive/zip/writer_test.go +++ b/libgo/go/archive/zip/writer_test.go @@ -125,3 +125,21 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) { t.Errorf("File contents %q, want %q", b, wt.Data) } } + +func BenchmarkCompressedZipGarbage(b *testing.B) { + b.ReportAllocs() + var buf bytes.Buffer + bigBuf := bytes.Repeat([]byte("a"), 1<<20) + for i := 0; i < b.N; i++ { + buf.Reset() + zw := NewWriter(&buf) + for j := 0; j < 3; j++ { + w, _ := zw.CreateHeader(&FileHeader{ + Name: "foo", + Method: Deflate, + }) + w.Write(bigBuf) + } + zw.Close() + } +} |