Skip to content

Instantly share code, notes, and snippets.

@dgageot
Created August 31, 2018 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dgageot/0007b4cbfa08f7cf95e93ba0db3bc12a to your computer and use it in GitHub Desktop.
Save dgageot/0007b4cbfa08f7cf95e93ba0db3bc12a to your computer and use it in GitHub Desktop.
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 </dev/urandom >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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment