github.com/eun/go@v0.0.0-20170811110501-92cfd07a6cfd/src/archive/tar/writer_test.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tar
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/hex"
    10  	"io"
    11  	"io/ioutil"
    12  	"os"
    13  	"path"
    14  	"reflect"
    15  	"sort"
    16  	"strings"
    17  	"testing"
    18  	"testing/iotest"
    19  	"time"
    20  )
    21  
    22  // Render a pseudo-diff between two blocks of bytes.
    23  func bytediff(a []byte, b []byte) (s string) {
    24  	var ax = strings.Split(hex.Dump(a), "\n")
    25  	var bx = strings.Split(hex.Dump(b), "\n")
    26  	for i := 0; i < len(ax) || i < len(bx); i++ {
    27  		var sa, sb = "", ""
    28  		if i < len(ax) {
    29  			sa = ax[i]
    30  		}
    31  		if i < len(bx) {
    32  			sb = bx[i]
    33  		}
    34  		if sa != sb {
    35  			if len(sa) > 0 {
    36  				s += "+" + sa + "\n"
    37  			}
    38  			if len(sb) > 0 {
    39  				s += "-" + sb + "\n"
    40  			}
    41  		}
    42  	}
    43  	return s
    44  }
    45  
    46  func TestWriter(t *testing.T) {
    47  	type entry struct {
    48  		header   *Header
    49  		contents string
    50  	}
    51  
    52  	vectors := []struct {
    53  		file    string // filename of expected output
    54  		entries []*entry
    55  		err     error // expected error on WriteHeader
    56  	}{{
    57  		// The writer test file was produced with this command:
    58  		// tar (GNU tar) 1.26
    59  		//   ln -s small.txt link.txt
    60  		//   tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
    61  		file: "testdata/writer.tar",
    62  		entries: []*entry{{
    63  			header: &Header{
    64  				Name:     "small.txt",
    65  				Mode:     0640,
    66  				Uid:      73025,
    67  				Gid:      5000,
    68  				Size:     5,
    69  				ModTime:  time.Unix(1246508266, 0),
    70  				Typeflag: '0',
    71  				Uname:    "dsymonds",
    72  				Gname:    "eng",
    73  			},
    74  			contents: "Kilts",
    75  		}, {
    76  			header: &Header{
    77  				Name:     "small2.txt",
    78  				Mode:     0640,
    79  				Uid:      73025,
    80  				Gid:      5000,
    81  				Size:     11,
    82  				ModTime:  time.Unix(1245217492, 0),
    83  				Typeflag: '0',
    84  				Uname:    "dsymonds",
    85  				Gname:    "eng",
    86  			},
    87  			contents: "Google.com\n",
    88  		}, {
    89  			header: &Header{
    90  				Name:     "link.txt",
    91  				Mode:     0777,
    92  				Uid:      1000,
    93  				Gid:      1000,
    94  				Size:     0,
    95  				ModTime:  time.Unix(1314603082, 0),
    96  				Typeflag: '2',
    97  				Linkname: "small.txt",
    98  				Uname:    "strings",
    99  				Gname:    "strings",
   100  			},
   101  			// no contents
   102  		}},
   103  	}, {
   104  		// The truncated test file was produced using these commands:
   105  		//   dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
   106  		//   tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
   107  		file: "testdata/writer-big.tar",
   108  		entries: []*entry{{
   109  			header: &Header{
   110  				Name:     "tmp/16gig.txt",
   111  				Mode:     0640,
   112  				Uid:      73025,
   113  				Gid:      5000,
   114  				Size:     16 << 30,
   115  				ModTime:  time.Unix(1254699560, 0),
   116  				Typeflag: '0',
   117  				Uname:    "dsymonds",
   118  				Gname:    "eng",
   119  			},
   120  			// fake contents
   121  			contents: strings.Repeat("\x00", 4<<10),
   122  		}},
   123  	}, {
   124  		// This truncated file was produced using this library.
   125  		// It was verified to work with GNU tar 1.27.1 and BSD tar 3.1.2.
   126  		//  dd if=/dev/zero bs=1G count=16 >> writer-big-long.tar
   127  		//  gnutar -xvf writer-big-long.tar
   128  		//  bsdtar -xvf writer-big-long.tar
   129  		//
   130  		// This file is in PAX format.
   131  		file: "testdata/writer-big-long.tar",
   132  		entries: []*entry{{
   133  			header: &Header{
   134  				Name:     strings.Repeat("longname/", 15) + "16gig.txt",
   135  				Mode:     0644,
   136  				Uid:      1000,
   137  				Gid:      1000,
   138  				Size:     16 << 30,
   139  				ModTime:  time.Unix(1399583047, 0),
   140  				Typeflag: '0',
   141  				Uname:    "guillaume",
   142  				Gname:    "guillaume",
   143  			},
   144  			// fake contents
   145  			contents: strings.Repeat("\x00", 4<<10),
   146  		}},
   147  	}, {
   148  		// TODO(dsnet): The Writer output should match the following file.
   149  		// To fix an issue (see https://golang.org/issue/12594), we disabled
   150  		// prefix support, which alters the generated output.
   151  		/*
   152  			// This file was produced using gnu tar 1.17
   153  			// gnutar  -b 4 --format=ustar (longname/)*15 + file.txt
   154  			file: "testdata/ustar.tar"
   155  		*/
   156  		file: "testdata/ustar.issue12594.tar", // This is a valid tar file, but not expected
   157  		entries: []*entry{{
   158  			header: &Header{
   159  				Name:     strings.Repeat("longname/", 15) + "file.txt",
   160  				Mode:     0644,
   161  				Uid:      0765,
   162  				Gid:      024,
   163  				Size:     06,
   164  				ModTime:  time.Unix(1360135598, 0),
   165  				Typeflag: '0',
   166  				Uname:    "shane",
   167  				Gname:    "staff",
   168  			},
   169  			contents: "hello\n",
   170  		}},
   171  	}, {
   172  		// This file was produced using gnu tar 1.26
   173  		// echo "Slartibartfast" > file.txt
   174  		// ln file.txt hard.txt
   175  		// tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
   176  		file: "testdata/hardlink.tar",
   177  		entries: []*entry{{
   178  			header: &Header{
   179  				Name:     "file.txt",
   180  				Mode:     0644,
   181  				Uid:      1000,
   182  				Gid:      100,
   183  				Size:     15,
   184  				ModTime:  time.Unix(1425484303, 0),
   185  				Typeflag: '0',
   186  				Uname:    "vbatts",
   187  				Gname:    "users",
   188  			},
   189  			contents: "Slartibartfast\n",
   190  		}, {
   191  			header: &Header{
   192  				Name:     "hard.txt",
   193  				Mode:     0644,
   194  				Uid:      1000,
   195  				Gid:      100,
   196  				Size:     0,
   197  				ModTime:  time.Unix(1425484303, 0),
   198  				Typeflag: '1',
   199  				Linkname: "file.txt",
   200  				Uname:    "vbatts",
   201  				Gname:    "users",
   202  			},
   203  			// no contents
   204  		}},
   205  	}, {
   206  		entries: []*entry{{
   207  			header: &Header{
   208  				Name:     "bad-null.txt",
   209  				Typeflag: '0',
   210  				Xattrs:   map[string]string{"null\x00null\x00": "fizzbuzz"},
   211  			},
   212  		}},
   213  		err: ErrHeader,
   214  	}, {
   215  		entries: []*entry{{
   216  			header: &Header{
   217  				Name:     "null\x00.txt",
   218  				Typeflag: '0',
   219  			},
   220  		}},
   221  		err: ErrHeader,
   222  	}}
   223  
   224  	for _, v := range vectors {
   225  		t.Run(path.Base(v.file), func(t *testing.T) {
   226  			buf := new(bytes.Buffer)
   227  			tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
   228  			canFail := false
   229  			for i, entry := range v.entries {
   230  				canFail = canFail || entry.header.Size > 1<<10 || v.err != nil
   231  
   232  				err := tw.WriteHeader(entry.header)
   233  				if err != v.err {
   234  					t.Fatalf("entry %d: WriteHeader() = %v, want %v", i, err, v.err)
   235  				}
   236  				if _, err := io.WriteString(tw, entry.contents); err != nil {
   237  					t.Fatalf("entry %d: WriteString() = %v, want nil", i, err)
   238  				}
   239  			}
   240  			// Only interested in Close failures for the small tests.
   241  			if err := tw.Close(); err != nil && !canFail {
   242  				t.Fatalf("Close() = %v, want nil", err)
   243  			}
   244  
   245  			if v.file != "" {
   246  				want, err := ioutil.ReadFile(v.file)
   247  				if err != nil {
   248  					t.Fatalf("ReadFile() = %v, want nil", err)
   249  				}
   250  				got := buf.Bytes()
   251  				if !bytes.Equal(want, got) {
   252  					t.Fatalf("incorrect result: (-=want, +=got)\n%v", bytediff(want, got))
   253  				}
   254  			}
   255  		})
   256  	}
   257  }
   258  
   259  func TestPax(t *testing.T) {
   260  	// Create an archive with a large name
   261  	fileinfo, err := os.Stat("testdata/small.txt")
   262  	if err != nil {
   263  		t.Fatal(err)
   264  	}
   265  	hdr, err := FileInfoHeader(fileinfo, "")
   266  	if err != nil {
   267  		t.Fatalf("os.Stat: %v", err)
   268  	}
   269  	// Force a PAX long name to be written
   270  	longName := strings.Repeat("ab", 100)
   271  	contents := strings.Repeat(" ", int(hdr.Size))
   272  	hdr.Name = longName
   273  	var buf bytes.Buffer
   274  	writer := NewWriter(&buf)
   275  	if err := writer.WriteHeader(hdr); err != nil {
   276  		t.Fatal(err)
   277  	}
   278  	if _, err = writer.Write([]byte(contents)); err != nil {
   279  		t.Fatal(err)
   280  	}
   281  	if err := writer.Close(); err != nil {
   282  		t.Fatal(err)
   283  	}
   284  	// Simple test to make sure PAX extensions are in effect
   285  	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
   286  		t.Fatal("Expected at least one PAX header to be written.")
   287  	}
   288  	// Test that we can get a long name back out of the archive.
   289  	reader := NewReader(&buf)
   290  	hdr, err = reader.Next()
   291  	if err != nil {
   292  		t.Fatal(err)
   293  	}
   294  	if hdr.Name != longName {
   295  		t.Fatal("Couldn't recover long file name")
   296  	}
   297  }
   298  
   299  func TestPaxSymlink(t *testing.T) {
   300  	// Create an archive with a large linkname
   301  	fileinfo, err := os.Stat("testdata/small.txt")
   302  	if err != nil {
   303  		t.Fatal(err)
   304  	}
   305  	hdr, err := FileInfoHeader(fileinfo, "")
   306  	hdr.Typeflag = TypeSymlink
   307  	if err != nil {
   308  		t.Fatalf("os.Stat:1 %v", err)
   309  	}
   310  	// Force a PAX long linkname to be written
   311  	longLinkname := strings.Repeat("1234567890/1234567890", 10)
   312  	hdr.Linkname = longLinkname
   313  
   314  	hdr.Size = 0
   315  	var buf bytes.Buffer
   316  	writer := NewWriter(&buf)
   317  	if err := writer.WriteHeader(hdr); err != nil {
   318  		t.Fatal(err)
   319  	}
   320  	if err := writer.Close(); err != nil {
   321  		t.Fatal(err)
   322  	}
   323  	// Simple test to make sure PAX extensions are in effect
   324  	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
   325  		t.Fatal("Expected at least one PAX header to be written.")
   326  	}
   327  	// Test that we can get a long name back out of the archive.
   328  	reader := NewReader(&buf)
   329  	hdr, err = reader.Next()
   330  	if err != nil {
   331  		t.Fatal(err)
   332  	}
   333  	if hdr.Linkname != longLinkname {
   334  		t.Fatal("Couldn't recover long link name")
   335  	}
   336  }
   337  
   338  func TestPaxNonAscii(t *testing.T) {
   339  	// Create an archive with non ascii. These should trigger a pax header
   340  	// because pax headers have a defined utf-8 encoding.
   341  	fileinfo, err := os.Stat("testdata/small.txt")
   342  	if err != nil {
   343  		t.Fatal(err)
   344  	}
   345  
   346  	hdr, err := FileInfoHeader(fileinfo, "")
   347  	if err != nil {
   348  		t.Fatalf("os.Stat:1 %v", err)
   349  	}
   350  
   351  	// some sample data
   352  	chineseFilename := "文件名"
   353  	chineseGroupname := "組"
   354  	chineseUsername := "用戶名"
   355  
   356  	hdr.Name = chineseFilename
   357  	hdr.Gname = chineseGroupname
   358  	hdr.Uname = chineseUsername
   359  
   360  	contents := strings.Repeat(" ", int(hdr.Size))
   361  
   362  	var buf bytes.Buffer
   363  	writer := NewWriter(&buf)
   364  	if err := writer.WriteHeader(hdr); err != nil {
   365  		t.Fatal(err)
   366  	}
   367  	if _, err = writer.Write([]byte(contents)); err != nil {
   368  		t.Fatal(err)
   369  	}
   370  	if err := writer.Close(); err != nil {
   371  		t.Fatal(err)
   372  	}
   373  	// Simple test to make sure PAX extensions are in effect
   374  	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
   375  		t.Fatal("Expected at least one PAX header to be written.")
   376  	}
   377  	// Test that we can get a long name back out of the archive.
   378  	reader := NewReader(&buf)
   379  	hdr, err = reader.Next()
   380  	if err != nil {
   381  		t.Fatal(err)
   382  	}
   383  	if hdr.Name != chineseFilename {
   384  		t.Fatal("Couldn't recover unicode name")
   385  	}
   386  	if hdr.Gname != chineseGroupname {
   387  		t.Fatal("Couldn't recover unicode group")
   388  	}
   389  	if hdr.Uname != chineseUsername {
   390  		t.Fatal("Couldn't recover unicode user")
   391  	}
   392  }
   393  
   394  func TestPaxXattrs(t *testing.T) {
   395  	xattrs := map[string]string{
   396  		"user.key": "value",
   397  	}
   398  
   399  	// Create an archive with an xattr
   400  	fileinfo, err := os.Stat("testdata/small.txt")
   401  	if err != nil {
   402  		t.Fatal(err)
   403  	}
   404  	hdr, err := FileInfoHeader(fileinfo, "")
   405  	if err != nil {
   406  		t.Fatalf("os.Stat: %v", err)
   407  	}
   408  	contents := "Kilts"
   409  	hdr.Xattrs = xattrs
   410  	var buf bytes.Buffer
   411  	writer := NewWriter(&buf)
   412  	if err := writer.WriteHeader(hdr); err != nil {
   413  		t.Fatal(err)
   414  	}
   415  	if _, err = writer.Write([]byte(contents)); err != nil {
   416  		t.Fatal(err)
   417  	}
   418  	if err := writer.Close(); err != nil {
   419  		t.Fatal(err)
   420  	}
   421  	// Test that we can get the xattrs back out of the archive.
   422  	reader := NewReader(&buf)
   423  	hdr, err = reader.Next()
   424  	if err != nil {
   425  		t.Fatal(err)
   426  	}
   427  	if !reflect.DeepEqual(hdr.Xattrs, xattrs) {
   428  		t.Fatalf("xattrs did not survive round trip: got %+v, want %+v",
   429  			hdr.Xattrs, xattrs)
   430  	}
   431  }
   432  
   433  func TestPaxHeadersSorted(t *testing.T) {
   434  	fileinfo, err := os.Stat("testdata/small.txt")
   435  	if err != nil {
   436  		t.Fatal(err)
   437  	}
   438  	hdr, err := FileInfoHeader(fileinfo, "")
   439  	if err != nil {
   440  		t.Fatalf("os.Stat: %v", err)
   441  	}
   442  	contents := strings.Repeat(" ", int(hdr.Size))
   443  
   444  	hdr.Xattrs = map[string]string{
   445  		"foo": "foo",
   446  		"bar": "bar",
   447  		"baz": "baz",
   448  		"qux": "qux",
   449  	}
   450  
   451  	var buf bytes.Buffer
   452  	writer := NewWriter(&buf)
   453  	if err := writer.WriteHeader(hdr); err != nil {
   454  		t.Fatal(err)
   455  	}
   456  	if _, err = writer.Write([]byte(contents)); err != nil {
   457  		t.Fatal(err)
   458  	}
   459  	if err := writer.Close(); err != nil {
   460  		t.Fatal(err)
   461  	}
   462  	// Simple test to make sure PAX extensions are in effect
   463  	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
   464  		t.Fatal("Expected at least one PAX header to be written.")
   465  	}
   466  
   467  	// xattr bar should always appear before others
   468  	indices := []int{
   469  		bytes.Index(buf.Bytes(), []byte("bar=bar")),
   470  		bytes.Index(buf.Bytes(), []byte("baz=baz")),
   471  		bytes.Index(buf.Bytes(), []byte("foo=foo")),
   472  		bytes.Index(buf.Bytes(), []byte("qux=qux")),
   473  	}
   474  	if !sort.IntsAreSorted(indices) {
   475  		t.Fatal("PAX headers are not sorted")
   476  	}
   477  }
   478  
   479  func TestUSTARLongName(t *testing.T) {
   480  	// Create an archive with a path that failed to split with USTAR extension in previous versions.
   481  	fileinfo, err := os.Stat("testdata/small.txt")
   482  	if err != nil {
   483  		t.Fatal(err)
   484  	}
   485  	hdr, err := FileInfoHeader(fileinfo, "")
   486  	hdr.Typeflag = TypeDir
   487  	if err != nil {
   488  		t.Fatalf("os.Stat:1 %v", err)
   489  	}
   490  	// Force a PAX long name to be written. The name was taken from a practical example
   491  	// that fails and replaced ever char through numbers to anonymize the sample.
   492  	longName := "/0000_0000000/00000-000000000/0000_0000000/00000-0000000000000/0000_0000000/00000-0000000-00000000/0000_0000000/00000000/0000_0000000/000/0000_0000000/00000000v00/0000_0000000/000000/0000_0000000/0000000/0000_0000000/00000y-00/0000/0000/00000000/0x000000/"
   493  	hdr.Name = longName
   494  
   495  	hdr.Size = 0
   496  	var buf bytes.Buffer
   497  	writer := NewWriter(&buf)
   498  	if err := writer.WriteHeader(hdr); err != nil {
   499  		t.Fatal(err)
   500  	}
   501  	if err := writer.Close(); err != nil {
   502  		t.Fatal(err)
   503  	}
   504  	// Test that we can get a long name back out of the archive.
   505  	reader := NewReader(&buf)
   506  	hdr, err = reader.Next()
   507  	if err != nil {
   508  		t.Fatal(err)
   509  	}
   510  	if hdr.Name != longName {
   511  		t.Fatal("Couldn't recover long name")
   512  	}
   513  }
   514  
   515  func TestValidTypeflagWithPAXHeader(t *testing.T) {
   516  	var buffer bytes.Buffer
   517  	tw := NewWriter(&buffer)
   518  
   519  	fileName := strings.Repeat("ab", 100)
   520  
   521  	hdr := &Header{
   522  		Name:     fileName,
   523  		Size:     4,
   524  		Typeflag: 0,
   525  	}
   526  	if err := tw.WriteHeader(hdr); err != nil {
   527  		t.Fatalf("Failed to write header: %s", err)
   528  	}
   529  	if _, err := tw.Write([]byte("fooo")); err != nil {
   530  		t.Fatalf("Failed to write the file's data: %s", err)
   531  	}
   532  	tw.Close()
   533  
   534  	tr := NewReader(&buffer)
   535  
   536  	for {
   537  		header, err := tr.Next()
   538  		if err == io.EOF {
   539  			break
   540  		}
   541  		if err != nil {
   542  			t.Fatalf("Failed to read header: %s", err)
   543  		}
   544  		if header.Typeflag != 0 {
   545  			t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag)
   546  		}
   547  	}
   548  }
   549  
   550  func TestWriteAfterClose(t *testing.T) {
   551  	var buffer bytes.Buffer
   552  	tw := NewWriter(&buffer)
   553  
   554  	hdr := &Header{
   555  		Name: "small.txt",
   556  		Size: 5,
   557  	}
   558  	if err := tw.WriteHeader(hdr); err != nil {
   559  		t.Fatalf("Failed to write header: %s", err)
   560  	}
   561  	tw.Close()
   562  	if _, err := tw.Write([]byte("Kilts")); err != ErrWriteAfterClose {
   563  		t.Fatalf("Write: got %v; want ErrWriteAfterClose", err)
   564  	}
   565  }
   566  
   567  func TestSplitUSTARPath(t *testing.T) {
   568  	sr := strings.Repeat
   569  
   570  	vectors := []struct {
   571  		input  string // Input path
   572  		prefix string // Expected output prefix
   573  		suffix string // Expected output suffix
   574  		ok     bool   // Split success?
   575  	}{
   576  		{"", "", "", false},
   577  		{"abc", "", "", false},
   578  		{"用戶名", "", "", false},
   579  		{sr("a", nameSize), "", "", false},
   580  		{sr("a", nameSize) + "/", "", "", false},
   581  		{sr("a", nameSize) + "/a", sr("a", nameSize), "a", true},
   582  		{sr("a", prefixSize) + "/", "", "", false},
   583  		{sr("a", prefixSize) + "/a", sr("a", prefixSize), "a", true},
   584  		{sr("a", nameSize+1), "", "", false},
   585  		{sr("/", nameSize+1), sr("/", nameSize-1), "/", true},
   586  		{sr("a", prefixSize) + "/" + sr("b", nameSize),
   587  			sr("a", prefixSize), sr("b", nameSize), true},
   588  		{sr("a", prefixSize) + "//" + sr("b", nameSize), "", "", false},
   589  		{sr("a/", nameSize), sr("a/", 77) + "a", sr("a/", 22), true},
   590  	}
   591  
   592  	for _, v := range vectors {
   593  		prefix, suffix, ok := splitUSTARPath(v.input)
   594  		if prefix != v.prefix || suffix != v.suffix || ok != v.ok {
   595  			t.Errorf("splitUSTARPath(%q):\ngot  (%q, %q, %v)\nwant (%q, %q, %v)",
   596  				v.input, prefix, suffix, ok, v.prefix, v.suffix, v.ok)
   597  		}
   598  	}
   599  }
   600  
   601  // TestIssue12594 tests that the Writer does not attempt to populate the prefix
   602  // field when encoding a header in the GNU format. The prefix field is valid
   603  // in USTAR and PAX, but not GNU.
   604  func TestIssue12594(t *testing.T) {
   605  	names := []string{
   606  		"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/file.txt",
   607  		"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/file.txt",
   608  		"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/333/file.txt",
   609  		"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/file.txt",
   610  		"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000/file.txt",
   611  		"/home/support/.openoffice.org/3/user/uno_packages/cache/registry/com.sun.star.comp.deployment.executable.PackageRegistryBackend",
   612  	}
   613  
   614  	for i, name := range names {
   615  		var b bytes.Buffer
   616  
   617  		tw := NewWriter(&b)
   618  		if err := tw.WriteHeader(&Header{
   619  			Name: name,
   620  			Uid:  1 << 25, // Prevent USTAR format
   621  		}); err != nil {
   622  			t.Errorf("test %d, unexpected WriteHeader error: %v", i, err)
   623  		}
   624  		if err := tw.Close(); err != nil {
   625  			t.Errorf("test %d, unexpected Close error: %v", i, err)
   626  		}
   627  
   628  		// The prefix field should never appear in the GNU format.
   629  		var blk block
   630  		copy(blk[:], b.Bytes())
   631  		prefix := string(blk.USTAR().Prefix())
   632  		if i := strings.IndexByte(prefix, 0); i >= 0 {
   633  			prefix = prefix[:i] // Truncate at the NUL terminator
   634  		}
   635  		if blk.GetFormat() == formatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) {
   636  			t.Errorf("test %d, found prefix in GNU format: %s", i, prefix)
   637  		}
   638  
   639  		tr := NewReader(&b)
   640  		hdr, err := tr.Next()
   641  		if err != nil {
   642  			t.Errorf("test %d, unexpected Next error: %v", i, err)
   643  		}
   644  		if hdr.Name != name {
   645  			t.Errorf("test %d, hdr.Name = %s, want %s", i, hdr.Name, name)
   646  		}
   647  	}
   648  }