Commit d75abb7c authored by David Symonds's avatar David Symonds

archive/tar: catch short writes.

Also make error messages consistent throughout.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5777064
parent ac0789c6
...@@ -18,7 +18,7 @@ import ( ...@@ -18,7 +18,7 @@ import (
) )
var ( 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. // A Reader provides sequential access to the contents of a tar archive.
......
...@@ -5,18 +5,19 @@ ...@@ -5,18 +5,19 @@
package tar package tar
// TODO(dsymonds): // TODO(dsymonds):
// - catch more errors (no first header, write after close, etc.) // - catch more errors (no first header, etc.)
import ( import (
"errors" "errors"
"fmt"
"io" "io"
"strconv" "strconv"
) )
var ( var (
ErrWriteTooLong = errors.New("write too long") ErrWriteTooLong = errors.New("archive/tar: write too long")
ErrFieldTooLong = errors.New("header field too long") ErrFieldTooLong = errors.New("archive/tar: header field too long")
ErrWriteAfterClose = errors.New("write after close") ErrWriteAfterClose = errors.New("archive/tar: write after close")
) )
// A Writer provides sequential writing of a tar archive in POSIX.1 format. // 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} } ...@@ -48,6 +49,11 @@ func NewWriter(w io.Writer) *Writer { return &Writer{w: w} }
// Flush finishes writing the current file (optional). // Flush finishes writing the current file (optional).
func (tw *Writer) Flush() error { 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 n := tw.nb + tw.pad
for n > 0 && tw.err == nil { for n > 0 && tw.err == nil {
nr := n nr := n
...@@ -193,6 +199,9 @@ func (tw *Writer) Close() error { ...@@ -193,6 +199,9 @@ func (tw *Writer) Close() error {
} }
tw.Flush() tw.Flush()
tw.closed = true tw.closed = true
if tw.err != nil {
return tw.err
}
// trailer: two zero blocks // trailer: two zero blocks
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"strings"
"testing" "testing"
"testing/iotest" "testing/iotest"
"time" "time"
...@@ -95,7 +96,8 @@ var writerTests = []*writerTest{ ...@@ -95,7 +96,8 @@ var writerTests = []*writerTest{
Uname: "dsymonds", Uname: "dsymonds",
Gname: "eng", Gname: "eng",
}, },
// no contents // fake contents
contents: strings.Repeat("\x00", 4<<10),
}, },
}, },
}, },
...@@ -150,7 +152,9 @@ testLoop: ...@@ -150,7 +152,9 @@ testLoop:
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
big := false
for j, entry := range test.entries { for j, entry := range test.entries {
big = big || entry.header.Size > 1<<10
if err := tw.WriteHeader(entry.header); err != nil { if err := tw.WriteHeader(entry.header); err != nil {
t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err) t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err)
continue testLoop continue testLoop
...@@ -160,7 +164,8 @@ testLoop: ...@@ -160,7 +164,8 @@ testLoop:
continue 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) t.Errorf("test %d: Failed closing archive: %v", i, err)
continue testLoop continue testLoop
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment