package main import ( "archive/tar" "fmt" "io" "log" "os" tartar "github.com/vbatts/tar-split/archive/tar" ) const length int64 = 8589934592 // README: first a random test file needs to be created with this command: // $ head -c 8589934592 file // // randomness is important. With a file the same size but containing only zeros, // the issue is not triggered. // func main() { limit := length // KO // limit := length - 1 // OK pr, pw := io.Pipe() go func() { // var b bytes.Buffer tw := tar.NewWriter(pw) if err := tw.WriteHeader(&tar.Header{ Format: tar.FormatPAX, Name: "test", Size: limit, }); err != nil { log.Fatal(err) } src, err := os.Open("file") if err != nil { log.Fatal(err) } if _, err := io.Copy(tw, io.LimitReader(src, limit)); err != nil { log.Fatal(err) } if err := tw.Close(); err != nil { log.Fatal(err) } }() ttr, err := newInputTarStream(pr) if err != nil { log.Fatal(err) } tr := tar.NewReader(ttr) for { hdr, err := tr.Next() if err == io.EOF { break // End of archive } if err != nil { log.Fatalln("Next", err) } fmt.Println("Size of", hdr.Name, hdr.Size) } } func newInputTarStream(r io.Reader) (io.Reader, error) { pR, pW := io.Pipe() outputRdr := io.TeeReader(r, pW) go func() { tr := tartar.NewReader(outputRdr) for { hdr, err := tr.Next() if err != nil { if err != io.EOF { pW.CloseWithError(err) return } break } if hdr == nil { break } } pW.Close() }() return pR, nil }