mirror of
https://github.com/vbatts/tar-split.git
synced 2024-12-18 19:46:29 +00:00
tar/asm: initial assmebly of tar stream
This commit is contained in:
parent
34a67dfed5
commit
7ccbb9d40c
2 changed files with 71 additions and 0 deletions
18
tar/asm/README.md
Normal file
18
tar/asm/README.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
asm
|
||||
===
|
||||
|
||||
This library for assembly and disassembly of tar archives, facilitated by
|
||||
`github.com/vbatts/tar-split/tar/storage`.
|
||||
|
||||
|
||||
|
||||
Thoughts
|
||||
--------
|
||||
|
||||
While the initial implementation is based on a relative path, I'm thinking the
|
||||
next step is to have something like a FileGetter interface, of which a path
|
||||
based getter is just one type.
|
||||
|
||||
Then you could pass a path based Getter and an Unpacker, and receive a
|
||||
io.Reader that is your tar stream.
|
||||
|
53
tar/asm/assemble.go
Normal file
53
tar/asm/assemble.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package asm
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/vbatts/tar-split/tar/storage"
|
||||
)
|
||||
|
||||
func NewTarStream(relpath string, up storage.Unpacker) io.ReadCloser {
|
||||
pr, pw := io.Pipe()
|
||||
go func() {
|
||||
for {
|
||||
entry, err := up.Next()
|
||||
if err != nil {
|
||||
pw.CloseWithError(err)
|
||||
break
|
||||
}
|
||||
switch entry.Type {
|
||||
case storage.SegmentType:
|
||||
if _, err := pw.Write(entry.Payload); err != nil {
|
||||
pw.CloseWithError(err)
|
||||
break
|
||||
}
|
||||
case storage.FileType:
|
||||
if err := writeEntryFromRelPath(pw, relpath, entry); err != nil {
|
||||
pw.CloseWithError(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
return pr
|
||||
}
|
||||
|
||||
func writeEntryFromRelPath(w io.Writer, root string, entry *storage.Entry) error {
|
||||
if entry.Size == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME might should have a check for '../../../../etc/passwd' attempts?
|
||||
fh, err := os.Open(path.Join(root, entry.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fh.Close()
|
||||
if _, err := io.Copy(w, fh); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue