summaryrefslogtreecommitdiff
path: root/libgo/go/compress/gzip
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/compress/gzip')
-rw-r--r--libgo/go/compress/gzip/example_test.go130
-rw-r--r--libgo/go/compress/gzip/gunzip.go7
-rw-r--r--libgo/go/compress/gzip/gunzip_test.go20
-rw-r--r--libgo/go/compress/gzip/gzip.go23
-rw-r--r--libgo/go/compress/gzip/gzip_test.go4
-rw-r--r--libgo/go/compress/gzip/issue14937_test.go9
6 files changed, 178 insertions, 15 deletions
diff --git a/libgo/go/compress/gzip/example_test.go b/libgo/go/compress/gzip/example_test.go
new file mode 100644
index 00000000000..4764bcb090a
--- /dev/null
+++ b/libgo/go/compress/gzip/example_test.go
@@ -0,0 +1,130 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package gzip_test
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "time"
+)
+
+func Example_writerReader() {
+ var buf bytes.Buffer
+ zw := gzip.NewWriter(&buf)
+
+ // Setting the Header fields is optional.
+ zw.Name = "a-new-hope.txt"
+ zw.Comment = "an epic space opera by George Lucas"
+ zw.ModTime = time.Date(1977, time.May, 25, 0, 0, 0, 0, time.UTC)
+
+ _, err := zw.Write([]byte("A long time ago in a galaxy far, far away..."))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := zw.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ zr, err := gzip.NewReader(&buf)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Printf("Name: %s\nComment: %s\nModTime: %s\n\n", zr.Name, zr.Comment, zr.ModTime.UTC())
+
+ if _, err := io.Copy(os.Stdout, zr); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // Name: a-new-hope.txt
+ // Comment: an epic space opera by George Lucas
+ // ModTime: 1977-05-25 00:00:00 +0000 UTC
+ //
+ // A long time ago in a galaxy far, far away...
+}
+
+func ExampleReader_Multistream() {
+ var buf bytes.Buffer
+ zw := gzip.NewWriter(&buf)
+
+ var files = []struct {
+ name string
+ comment string
+ modTime time.Time
+ data string
+ }{
+ {"file-1.txt", "file-header-1", time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC), "Hello Gophers - 1"},
+ {"file-2.txt", "file-header-2", time.Date(2007, time.March, 2, 4, 5, 6, 1, time.UTC), "Hello Gophers - 2"},
+ }
+
+ for _, file := range files {
+ zw.Name = file.name
+ zw.Comment = file.comment
+ zw.ModTime = file.modTime
+
+ if _, err := zw.Write([]byte(file.data)); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := zw.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ zw.Reset(&buf)
+ }
+
+ zr, err := gzip.NewReader(&buf)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for {
+ zr.Multistream(false)
+ fmt.Printf("Name: %s\nComment: %s\nModTime: %s\n\n", zr.Name, zr.Comment, zr.ModTime.UTC())
+
+ if _, err := io.Copy(os.Stdout, zr); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Print("\n\n")
+
+ err = zr.Reset(&buf)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // Name: file-1.txt
+ // Comment: file-header-1
+ // ModTime: 2006-02-01 03:04:05 +0000 UTC
+ //
+ // Hello Gophers - 1
+ //
+ // Name: file-2.txt
+ // Comment: file-header-2
+ // ModTime: 2007-03-02 04:05:06 +0000 UTC
+ //
+ // Hello Gophers - 2
+}
diff --git a/libgo/go/compress/gzip/gunzip.go b/libgo/go/compress/gzip/gunzip.go
index 7e640692f3f..8bd750bd8b3 100644
--- a/libgo/go/compress/gzip/gunzip.go
+++ b/libgo/go/compress/gzip/gunzip.go
@@ -186,7 +186,11 @@ func (z *Reader) readHeader() (hdr Header, err error) {
return hdr, ErrHeader
}
flg := z.buf[3]
- hdr.ModTime = time.Unix(int64(le.Uint32(z.buf[4:8])), 0)
+ if t := int64(le.Uint32(z.buf[4:8])); t > 0 {
+ // Section 2.3.1, the zero value for MTIME means that the
+ // modified time is not set.
+ hdr.ModTime = time.Unix(t, 0)
+ }
// z.buf[8] is XFL and is currently ignored.
hdr.OS = z.buf[9]
z.digest = crc32.ChecksumIEEE(z.buf[:10])
@@ -238,6 +242,7 @@ func (z *Reader) readHeader() (hdr Header, err error) {
return hdr, nil
}
+// Read implements io.Reader, reading uncompressed bytes from its underlying Reader.
func (z *Reader) Read(p []byte) (n int, err error) {
if z.err != nil {
return 0, z.err
diff --git a/libgo/go/compress/gzip/gunzip_test.go b/libgo/go/compress/gzip/gunzip_test.go
index fdce91989a6..fdea0c5d5ff 100644
--- a/libgo/go/compress/gzip/gunzip_test.go
+++ b/libgo/go/compress/gzip/gunzip_test.go
@@ -339,6 +339,26 @@ var gunzipTests = []gunzipTest{
},
nil,
},
+ {
+ "",
+ "truncated gzip file amid raw-block",
+ "hello",
+ []byte{
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x0c, 0x00, 0xf3, 0xff, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
+ },
+ io.ErrUnexpectedEOF,
+ },
+ {
+ "",
+ "truncated gzip file amid fixed-block",
+ "He",
+ []byte{
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xf2, 0x48, 0xcd,
+ },
+ io.ErrUnexpectedEOF,
+ },
}
func TestDecompressor(t *testing.T) {
diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go
index c702c493c11..aafb442a667 100644
--- a/libgo/go/compress/gzip/gzip.go
+++ b/libgo/go/compress/gzip/gzip.go
@@ -10,6 +10,7 @@ import (
"fmt"
"hash/crc32"
"io"
+ "time"
)
// These constants are copied from the flate package, so that code that imports
@@ -19,6 +20,7 @@ const (
BestSpeed = flate.BestSpeed
BestCompression = flate.BestCompression
DefaultCompression = flate.DefaultCompression
+ HuffmanOnly = flate.HuffmanOnly
)
// A Writer is an io.WriteCloser.
@@ -52,11 +54,11 @@ func NewWriter(w io.Writer) *Writer {
// NewWriterLevel is like NewWriter but specifies the compression level instead
// of assuming DefaultCompression.
//
-// The compression level can be DefaultCompression, NoCompression, or any
-// integer value between BestSpeed and BestCompression inclusive. The error
-// returned will be nil if the level is valid.
+// The compression level can be DefaultCompression, NoCompression, HuffmanOnly
+// or any integer value between BestSpeed and BestCompression inclusive.
+// The error returned will be nil if the level is valid.
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
- if level < DefaultCompression || level > BestCompression {
+ if level < HuffmanOnly || level > BestCompression {
return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
}
z := new(Writer)
@@ -142,10 +144,7 @@ func (z *Writer) Write(p []byte) (int, error) {
// Write the GZIP header lazily.
if !z.wroteHeader {
z.wroteHeader = true
- z.buf[0] = gzipID1
- z.buf[1] = gzipID2
- z.buf[2] = gzipDeflate
- z.buf[3] = 0
+ z.buf = [10]byte{0: gzipID1, 1: gzipID2, 2: gzipDeflate}
if z.Extra != nil {
z.buf[3] |= 0x04
}
@@ -155,13 +154,15 @@ func (z *Writer) Write(p []byte) (int, error) {
if z.Comment != "" {
z.buf[3] |= 0x10
}
- le.PutUint32(z.buf[4:8], uint32(z.ModTime.Unix()))
+ if z.ModTime.After(time.Unix(0, 0)) {
+ // Section 2.3.1, the zero value for MTIME means that the
+ // modified time is not set.
+ le.PutUint32(z.buf[4:8], uint32(z.ModTime.Unix()))
+ }
if z.level == BestCompression {
z.buf[8] = 2
} else if z.level == BestSpeed {
z.buf[8] = 4
- } else {
- z.buf[8] = 0
}
z.buf[9] = z.OS
n, z.err = z.w.Write(z.buf[:10])
diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go
index 09271b24e92..865c529f55c 100644
--- a/libgo/go/compress/gzip/gzip_test.go
+++ b/libgo/go/compress/gzip/gzip_test.go
@@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"io/ioutil"
+ "reflect"
"testing"
"time"
)
@@ -24,6 +25,9 @@ func TestEmpty(t *testing.T) {
if err != nil {
t.Fatalf("NewReader: %v", err)
}
+ if want := (Header{OS: 255}); !reflect.DeepEqual(r.Header, want) {
+ t.Errorf("Header mismatch:\ngot %#v\nwant %#v", r.Header, want)
+ }
b, err := ioutil.ReadAll(r)
if err != nil {
t.Fatalf("ReadAll: %v", err)
diff --git a/libgo/go/compress/gzip/issue14937_test.go b/libgo/go/compress/gzip/issue14937_test.go
index 432ad16b1c2..e76d47cc4ee 100644
--- a/libgo/go/compress/gzip/issue14937_test.go
+++ b/libgo/go/compress/gzip/issue14937_test.go
@@ -7,7 +7,6 @@ import (
"runtime"
"strings"
"testing"
- "time"
)
// Per golang.org/issue/14937, check that every .gz file
@@ -16,8 +15,12 @@ func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
if testing.Short() && testenv.Builder() == "" {
t.Skip("skipping in short mode")
}
+ goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
+ if err != nil {
+ t.Fatal("error evaluating GOROOT: ", err)
+ }
var files []string
- err := filepath.Walk(runtime.GOROOT(), func(path string, info os.FileInfo, err error) error {
+ err = filepath.Walk(goroot, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
@@ -53,7 +56,7 @@ func checkZeroMTime(t *testing.T, path string) {
return
}
defer gz.Close()
- if !gz.ModTime.Equal(time.Unix(0, 0)) {
+ if !gz.ModTime.IsZero() {
t.Errorf("gzip file %s has non-zero mtime (%s)", path, gz.ModTime)
}
}