hughesjr / rpms / golang

Forked from rpms/golang 5 years ago
Clone

Blame SOURCES/go1.3-tar-fix_writing_of_pax_headers.patch

9b5743
# HG changeset patch
9b5743
# User Cristian Staretu <unclejacksons@gmail.com>
9b5743
# Date 1405555229 -36000
9b5743
#      Thu Jul 17 10:00:29 2014 +1000
9b5743
# Node ID 1b17b3426e3c281a973d2d7bbf235b936d6a0942
9b5743
# Parent  278365dff593f027db6c6b2c0a89262490d6b676
9b5743
archive/tar: fix writing of pax headers
9b5743
9b5743
"archive/tar: reuse temporary buffer in writeHeader" introduced a
9b5743
change which was supposed to help lower the number of allocations from
9b5743
512 bytes for every call to writeHeader. This change broke the writing
9b5743
of PAX headers.
9b5743
9b5743
writeHeader calls writePAXHeader and writePAXHeader calls writeHeader
9b5743
again. writeHeader will end up writing the PAX header twice.
9b5743
9b5743
example broken header:
9b5743
PaxHeaders.4007/NetLock_Arany_=Class_Gold=_Ftanstvny.crt0000000000000000000000000000007112301216634021512 xustar0000000000000000
9b5743
PaxHeaders.4007/NetLock_Arany_=Class_Gold=_Ftanstvny.crt0000000000000000000000000000007112301216634021512 xustar0000000000000000
9b5743
9b5743
example correct header:
9b5743
PaxHeaders.4290/NetLock_Arany_=Class_Gold=_Ftanstvny.crt0000000000000000000000000000007112301216634021516 xustar0000000000000000
9b5743
0100644000000000000000000000270412301216634007250 0ustar0000000000000000
9b5743
9b5743
This commit adds a dedicated buffer for pax headers to the Writer
9b5743
struct. This change increases the size of the struct by 512 bytes, but
9b5743
allows tar/writer to avoid allocating 512 bytes for all written
9b5743
headers and it avoids allocating 512 more bytes for pax headers.
9b5743
9b5743
LGTM=dsymonds
9b5743
R=dsymonds, dave, iant
9b5743
CC=golang-codereviews
9b5743
https://codereview.appspot.com/110480043
9b5743
9b5743
Committer: David Symonds <dsymonds@golang.org>
9b5743
9b5743
diff -r 278365dff593 -r 1b17b3426e3c src/pkg/archive/tar/writer.go
9b5743
--- a/src/pkg/archive/tar/writer.go	Wed Jul 16 16:29:51 2014 -0700
9b5743
+++ b/src/pkg/archive/tar/writer.go	Thu Jul 17 10:00:29 2014 +1000
9b5743
@@ -39,7 +39,8 @@
9b5743
 	closed     bool
9b5743
 	usedBinary bool            // whether the binary numeric field extension was used
9b5743
 	preferPax  bool            // use pax header instead of binary numeric header
9b5743
-	hdrBuff    [blockSize]byte // buffer to use in writeHeader
9b5743
+	hdrBuff    [blockSize]byte // buffer to use in writeHeader when writing a regular header
9b5743
+	paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
9b5743
 }
9b5743
 
9b5743
 // NewWriter creates a new Writer writing to w.
9b5743
@@ -161,7 +162,17 @@
9b5743
 	// subsecond time resolution, but for now let's just capture
9b5743
 	// too long fields or non ascii characters
9b5743
 
9b5743
-	header := tw.hdrBuff[:]
9b5743
+	var header []byte
9b5743
+
9b5743
+	// We need to select which scratch buffer to use carefully,
9b5743
+	// since this method is called recursively to write PAX headers.
9b5743
+	// If allowPax is true, this is the non-recursive call, and we will use hdrBuff.
9b5743
+	// If allowPax is false, we are being called by writePAXHeader, and hdrBuff is
9b5743
+	// already being used by the non-recursive call, so we must use paxHdrBuff.
9b5743
+	header = tw.hdrBuff[:]
9b5743
+	if !allowPax {
9b5743
+		header = tw.paxHdrBuff[:]
9b5743
+	}
9b5743
 	copy(header, zeroBlock)
9b5743
 	s := slicer(header)
9b5743
 
9b5743
diff -r 278365dff593 -r 1b17b3426e3c src/pkg/archive/tar/writer_test.go
9b5743
--- a/src/pkg/archive/tar/writer_test.go	Wed Jul 16 16:29:51 2014 -0700
9b5743
+++ b/src/pkg/archive/tar/writer_test.go	Thu Jul 17 10:00:29 2014 +1000
9b5743
@@ -454,3 +454,38 @@
9b5743
 		t.Fatal("Couldn't recover long name")
9b5743
 	}
9b5743
 }
9b5743
+
9b5743
+func TestValidTypeflagWithPAXHeader(t *testing.T) {
9b5743
+	var buffer bytes.Buffer
9b5743
+	tw := NewWriter(&buffer)
9b5743
+
9b5743
+	fileName := strings.Repeat("ab", 100)
9b5743
+
9b5743
+	hdr := &Header{
9b5743
+		Name:     fileName,
9b5743
+		Size:     4,
9b5743
+		Typeflag: 0,
9b5743
+	}
9b5743
+	if err := tw.WriteHeader(hdr); err != nil {
9b5743
+		t.Fatalf("Failed to write header: %s", err)
9b5743
+	}
9b5743
+	if _, err := tw.Write([]byte("fooo")); err != nil {
9b5743
+		t.Fatalf("Failed to write the file's data: %s", err)
9b5743
+	}
9b5743
+	tw.Close()
9b5743
+
9b5743
+	tr := NewReader(&buffer)
9b5743
+
9b5743
+	for {
9b5743
+		header, err := tr.Next()
9b5743
+		if err == io.EOF {
9b5743
+			break
9b5743
+		}
9b5743
+		if err != nil {
9b5743
+			t.Fatalf("Failed to read header: %s", err)
9b5743
+		}
9b5743
+		if header.Typeflag != 0 {
9b5743
+			t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag)
9b5743
+		}
9b5743
+	}
9b5743
+}