1
0
Fork 1
mirror of https://github.com/vbatts/tar-split.git synced 2024-12-24 06:16:31 +00:00

tar/asm: add FileGetter and concerns in README

This commit is contained in:
Vincent Batts 2015-02-25 12:56:40 -05:00
parent 7ccbb9d40c
commit e1206b43a6
3 changed files with 52 additions and 22 deletions

View file

@ -5,6 +5,21 @@ This library for assembly and disassembly of tar archives, facilitated by
`github.com/vbatts/tar-split/tar/storage`. `github.com/vbatts/tar-split/tar/storage`.
Concerns
--------
For completely safe assembly/disassembly, there will need to be a CAS
directory, that maps to a checksum in the `storage.Entity` of
`storage.FileType`.
This is due to the fact that tar archives _can_ allow multiple records for the
same path, but the last one effectively wins. Even if the prior records had a
different payload.
In this way, when assembling an archive from relative paths, if the archive has
multiple entries for the same path, then all payloads read in from a relative
path would be identical.
Thoughts Thoughts
-------- --------

View file

@ -2,13 +2,11 @@ package asm
import ( import (
"io" "io"
"os"
"path"
"github.com/vbatts/tar-split/tar/storage" "github.com/vbatts/tar-split/tar/storage"
) )
func NewTarStream(relpath string, up storage.Unpacker) io.ReadCloser { func NewTarStream(fg FileGetter, up storage.Unpacker) io.ReadCloser {
pr, pw := io.Pipe() pr, pw := io.Pipe()
go func() { go func() {
for { for {
@ -24,7 +22,16 @@ func NewTarStream(relpath string, up storage.Unpacker) io.ReadCloser {
break break
} }
case storage.FileType: case storage.FileType:
if err := writeEntryFromRelPath(pw, relpath, entry); err != nil { if entry.Size == 0 {
continue
}
fh, err := fg.Get(entry.Name)
if err != nil {
pw.CloseWithError(err)
break
}
defer fh.Close()
if _, err := io.Copy(pw, fh); err != nil {
pw.CloseWithError(err) pw.CloseWithError(err)
break break
} }
@ -33,21 +40,3 @@ func NewTarStream(relpath string, up storage.Unpacker) io.ReadCloser {
}() }()
return pr 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
}

26
tar/asm/getter.go Normal file
View file

@ -0,0 +1,26 @@
package asm
import (
"io"
"os"
"path"
)
type FileGetter interface {
// Get returns a stream for the provided file path
Get(string) (io.ReadCloser, error)
}
// NewPathFileGetter returns a FileGetter that is for files relative to path relpath.
func NewPathFileGetter(relpath string) FileGetter {
return &pathFileGetter{root: relpath}
}
type pathFileGetter struct {
root string
}
func (pfg pathFileGetter) Get(filename string) (io.ReadCloser, error) {
// FIXME might should have a check for '../../../../etc/passwd' attempts?
return os.Open(path.Join(pfg.root, filename))
}