]> Cypherpunks repositories - gostls13.git/commitdiff
archive/tar: catch short writes.
authorDavid Symonds <dsymonds@golang.org>
Mon, 12 Mar 2012 06:33:35 +0000 (17:33 +1100)
committerDavid Symonds <dsymonds@golang.org>
Mon, 12 Mar 2012 06:33:35 +0000 (17:33 +1100)
Also make error messages consistent throughout.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5777064

src/pkg/archive/tar/reader.go
src/pkg/archive/tar/writer.go
src/pkg/archive/tar/writer_test.go

index 755a730c8b4f98ddca28cc18c3a9c3c4199d62ca..1b40af812ae627a267b9331bda7e7a00970ae21c 100644 (file)
@@ -18,7 +18,7 @@ import (
 )
 
 var (
-       ErrHeader = errors.New("invalid tar header")
+       ErrHeader = errors.New("archive/tar: invalid tar header")
 )
 
 // A Reader provides sequential access to the contents of a tar archive.
index d35726bf9d83ba93d2ffb8f8ffa91b02d31e2d76..b2b7a58a10a7e22250af5074308d7dd3d98b1b36 100644 (file)
@@ -5,18 +5,19 @@
 package tar
 
 // TODO(dsymonds):
-// - catch more errors (no first header, write after close, etc.)
+// - catch more errors (no first header, etc.)
 
 import (
        "errors"
+       "fmt"
        "io"
        "strconv"
 )
 
 var (
-       ErrWriteTooLong    = errors.New("write too long")
-       ErrFieldTooLong    = errors.New("header field too long")
-       ErrWriteAfterClose = errors.New("write after close")
+       ErrWriteTooLong    = errors.New("archive/tar: write too long")
+       ErrFieldTooLong    = errors.New("archive/tar: header field too long")
+       ErrWriteAfterClose = errors.New("archive/tar: write after close")
 )
 
 // A Writer provides sequential writing of a tar archive in POSIX.1 format.
@@ -48,6 +49,11 @@ func NewWriter(w io.Writer) *Writer { return &Writer{w: w} }
 
 // Flush finishes writing the current file (optional).
 func (tw *Writer) Flush() error {
+       if tw.nb > 0 {
+               tw.err = fmt.Errorf("archive/tar: missed writing %d bytes", tw.nb)
+               return tw.err
+       }
+
        n := tw.nb + tw.pad
        for n > 0 && tw.err == nil {
                nr := n
@@ -193,6 +199,9 @@ func (tw *Writer) Close() error {
        }
        tw.Flush()
        tw.closed = true
+       if tw.err != nil {
+               return tw.err
+       }
 
        // trailer: two zero blocks
        for i := 0; i < 2; i++ {
index 0b413722dd34da1166a59567f33bfe63436cbbff..a214e57b9fc46dc48870822c0d096b883690c072 100644 (file)
@@ -9,6 +9,7 @@ import (
        "fmt"
        "io"
        "io/ioutil"
+       "strings"
        "testing"
        "testing/iotest"
        "time"
@@ -95,7 +96,8 @@ var writerTests = []*writerTest{
                                        Uname:    "dsymonds",
                                        Gname:    "eng",
                                },
-                               // no contents
+                               // fake contents
+                               contents: strings.Repeat("\x00", 4<<10),
                        },
                },
        },
@@ -150,7 +152,9 @@ testLoop:
 
                buf := new(bytes.Buffer)
                tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
+               big := false
                for j, entry := range test.entries {
+                       big = big || entry.header.Size > 1<<10
                        if err := tw.WriteHeader(entry.header); err != nil {
                                t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err)
                                continue testLoop
@@ -160,7 +164,8 @@ testLoop:
                                continue testLoop
                        }
                }
-               if err := tw.Close(); err != nil {
+               // Only interested in Close failures for the small tests.
+               if err := tw.Close(); err != nil && !big {
                        t.Errorf("test %d: Failed closing archive: %v", i, err)
                        continue testLoop
                }