2015-02-20 21:57:18 +00:00
|
|
|
// +build ignore
|
|
|
|
|
2015-02-19 21:50:30 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2015-02-20 20:28:48 +00:00
|
|
|
"io/ioutil"
|
2015-02-19 21:50:30 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
|
2015-02-20 21:56:50 +00:00
|
|
|
"github.com/vbatts/tar-split/archive/tar"
|
2015-02-19 21:50:30 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
log.SetOutput(os.Stderr)
|
|
|
|
for _, arg := range flag.Args() {
|
|
|
|
func() {
|
|
|
|
// Open the tar archive
|
|
|
|
fh, err := os.Open(arg)
|
|
|
|
if err != nil {
|
2015-02-20 20:28:48 +00:00
|
|
|
log.Fatal(err, arg)
|
2015-02-19 21:50:30 +00:00
|
|
|
}
|
|
|
|
defer fh.Close()
|
|
|
|
|
2015-02-19 23:07:22 +00:00
|
|
|
output, err := os.Create(fmt.Sprintf("%s.out", arg))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer output.Close()
|
|
|
|
log.Printf("writing %q to %q", fh.Name(), output.Name())
|
|
|
|
|
2015-02-19 21:50:30 +00:00
|
|
|
fi, err := fh.Stat()
|
|
|
|
if err != nil {
|
2015-02-20 20:28:48 +00:00
|
|
|
log.Fatal(err, fh.Name())
|
2015-02-19 21:50:30 +00:00
|
|
|
}
|
|
|
|
size := fi.Size()
|
|
|
|
var sum int64
|
|
|
|
tr := tar.NewReader(fh)
|
|
|
|
tr.RawAccounting = true
|
|
|
|
for {
|
|
|
|
hdr, err := tr.Next()
|
|
|
|
if err != nil {
|
|
|
|
if err != io.EOF {
|
|
|
|
log.Println(err)
|
|
|
|
}
|
2015-02-20 19:53:05 +00:00
|
|
|
// even when an EOF is reached, there is often 1024 null bytes on
|
|
|
|
// the end of an archive. Collect them too.
|
|
|
|
post := tr.RawBytes()
|
|
|
|
output.Write(post)
|
|
|
|
sum += int64(len(post))
|
2015-02-19 21:50:30 +00:00
|
|
|
break
|
|
|
|
}
|
2015-02-20 19:49:36 +00:00
|
|
|
|
2015-02-19 21:50:30 +00:00
|
|
|
pre := tr.RawBytes()
|
2015-02-19 23:07:22 +00:00
|
|
|
output.Write(pre)
|
2015-02-20 19:49:36 +00:00
|
|
|
sum += int64(len(pre))
|
|
|
|
|
2015-02-19 21:50:30 +00:00
|
|
|
var i int64
|
2015-02-19 23:07:22 +00:00
|
|
|
if i, err = io.Copy(output, tr); err != nil {
|
2015-02-19 21:50:30 +00:00
|
|
|
log.Println(err)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
sum += i
|
2015-02-20 19:49:36 +00:00
|
|
|
|
2015-02-24 20:21:05 +00:00
|
|
|
// I've never seen this be populated
|
2015-02-20 19:49:36 +00:00
|
|
|
post := tr.RawBytes()
|
|
|
|
output.Write(post)
|
2015-02-19 21:50:30 +00:00
|
|
|
sum += int64(len(post))
|
2015-02-20 19:49:36 +00:00
|
|
|
|
|
|
|
fmt.Println(hdr.Name, "pre:", len(pre), "read:", i, "post:", len(post))
|
2015-02-19 21:50:30 +00:00
|
|
|
}
|
|
|
|
|
2015-02-20 20:28:48 +00:00
|
|
|
// it is allowable, and not uncommon that there is further padding on the
|
|
|
|
// end of an archive, apart from the expected 1024 null bytes
|
|
|
|
remainder, err := ioutil.ReadAll(fh)
|
|
|
|
if err != nil && err != io.EOF {
|
|
|
|
log.Fatal(err, fh.Name())
|
|
|
|
}
|
|
|
|
output.Write(remainder)
|
|
|
|
sum += int64(len(remainder))
|
2015-02-24 20:21:05 +00:00
|
|
|
fmt.Printf("Remainder: %d\n", len(remainder))
|
2015-02-20 20:28:48 +00:00
|
|
|
|
2015-02-19 21:50:30 +00:00
|
|
|
if size != sum {
|
|
|
|
fmt.Printf("Size: %d; Sum: %d; Diff: %d\n", size, sum, size-sum)
|
2015-02-19 23:07:22 +00:00
|
|
|
fmt.Printf("Compare like `cmp -bl %s %s | less`\n", fh.Name(), output.Name())
|
2015-02-19 21:50:30 +00:00
|
|
|
} else {
|
|
|
|
fmt.Printf("Size: %d; Sum: %d\n", size, sum)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|