mirror of
https://github.com/golang/go
synced 2024-11-20 08:34:41 -07:00
archive/tar: avoid writing ModTime that is out of range.
Update #4358 Still to do: support binary numeric format in Reader. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6818101
This commit is contained in:
parent
7c0cbbfa18
commit
0ac317817b
@ -5,7 +5,10 @@
|
||||
package tar
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@ -54,3 +57,43 @@ func (symlink) Mode() os.FileMode { return os.ModeSymlink }
|
||||
func (symlink) ModTime() time.Time { return time.Time{} }
|
||||
func (symlink) IsDir() bool { return false }
|
||||
func (symlink) Sys() interface{} { return nil }
|
||||
|
||||
func TestRoundTrip(t *testing.T) {
|
||||
data := []byte("some file contents")
|
||||
|
||||
var b bytes.Buffer
|
||||
tw := NewWriter(&b)
|
||||
hdr := &Header{
|
||||
Name: "file.txt",
|
||||
Size: int64(len(data)),
|
||||
ModTime: time.Now(),
|
||||
}
|
||||
// tar only supports second precision.
|
||||
hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond)
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
t.Fatalf("tw.WriteHeader: %v", err)
|
||||
}
|
||||
if _, err := tw.Write(data); err != nil {
|
||||
t.Fatalf("tw.Write: %v", err)
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
t.Fatalf("tw.Close: %v", err)
|
||||
}
|
||||
|
||||
// Read it back.
|
||||
tr := NewReader(&b)
|
||||
rHdr, err := tr.Next()
|
||||
if err != nil {
|
||||
t.Fatalf("tr.Next: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(rHdr, hdr) {
|
||||
t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
|
||||
}
|
||||
rData, err := ioutil.ReadAll(tr)
|
||||
if err != nil {
|
||||
t.Fatalf("Read: %v", err)
|
||||
}
|
||||
if !bytes.Equal(rData, data) {
|
||||
t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data)
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -110,6 +111,12 @@ func (tw *Writer) numeric(b []byte, x int64) {
|
||||
b[0] |= 0x80 // highest bit indicates binary format
|
||||
}
|
||||
|
||||
var (
|
||||
minTime = time.Unix(0, 0)
|
||||
// There is room for 11 octal digits (33 bits) of mtime.
|
||||
maxTime = minTime.Add((1<<33 - 1) * time.Second)
|
||||
)
|
||||
|
||||
// WriteHeader writes hdr and prepares to accept the file's contents.
|
||||
// WriteHeader calls Flush if it is not the first header.
|
||||
// Calling after a Close will return ErrWriteAfterClose.
|
||||
@ -133,19 +140,25 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
|
||||
// TODO(dsymonds): handle names longer than 100 chars
|
||||
copy(s.next(100), []byte(hdr.Name))
|
||||
|
||||
tw.octal(s.next(8), hdr.Mode) // 100:108
|
||||
tw.numeric(s.next(8), int64(hdr.Uid)) // 108:116
|
||||
tw.numeric(s.next(8), int64(hdr.Gid)) // 116:124
|
||||
tw.numeric(s.next(12), hdr.Size) // 124:136
|
||||
tw.numeric(s.next(12), hdr.ModTime.Unix()) // 136:148
|
||||
s.next(8) // chksum (148:156)
|
||||
s.next(1)[0] = hdr.Typeflag // 156:157
|
||||
tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
|
||||
copy(s.next(8), []byte("ustar\x0000")) // 257:265
|
||||
tw.cString(s.next(32), hdr.Uname) // 265:297
|
||||
tw.cString(s.next(32), hdr.Gname) // 297:329
|
||||
tw.numeric(s.next(8), hdr.Devmajor) // 329:337
|
||||
tw.numeric(s.next(8), hdr.Devminor) // 337:345
|
||||
// Handle out of range ModTime carefully.
|
||||
var modTime int64
|
||||
if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
|
||||
modTime = hdr.ModTime.Unix()
|
||||
}
|
||||
|
||||
tw.octal(s.next(8), hdr.Mode) // 100:108
|
||||
tw.numeric(s.next(8), int64(hdr.Uid)) // 108:116
|
||||
tw.numeric(s.next(8), int64(hdr.Gid)) // 116:124
|
||||
tw.numeric(s.next(12), hdr.Size) // 124:136
|
||||
tw.numeric(s.next(12), modTime) // 136:148
|
||||
s.next(8) // chksum (148:156)
|
||||
s.next(1)[0] = hdr.Typeflag // 156:157
|
||||
tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
|
||||
copy(s.next(8), []byte("ustar\x0000")) // 257:265
|
||||
tw.cString(s.next(32), hdr.Uname) // 265:297
|
||||
tw.cString(s.next(32), hdr.Gname) // 297:329
|
||||
tw.numeric(s.next(8), hdr.Devmajor) // 329:337
|
||||
tw.numeric(s.next(8), hdr.Devminor) // 337:345
|
||||
|
||||
// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
|
||||
if tw.usedBinary {
|
||||
|
Loading…
Reference in New Issue
Block a user