Commit 1abae81d authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

tarfs: handle empty directories, handle more file types

parent 0f68fcc4
...@@ -52,7 +52,6 @@ func (r *tarRoot) OnAdd(ctx context.Context) { ...@@ -52,7 +52,6 @@ func (r *tarRoot) OnAdd(ctx context.Context) {
// XXX handle error // XXX handle error
break break
} }
if hdr.Typeflag == 'L' { if hdr.Typeflag == 'L' {
buf := bytes.NewBuffer(make([]byte, 0, hdr.Size)) buf := bytes.NewBuffer(make([]byte, 0, hdr.Size))
io.Copy(buf, tr) io.Copy(buf, tr)
...@@ -66,10 +65,6 @@ func (r *tarRoot) OnAdd(ctx context.Context) { ...@@ -66,10 +65,6 @@ func (r *tarRoot) OnAdd(ctx context.Context) {
longName = nil longName = nil
} }
if strings.HasSuffix(hdr.Name, "/") {
continue
}
buf := bytes.NewBuffer(make([]byte, 0, hdr.Size)) buf := bytes.NewBuffer(make([]byte, 0, hdr.Size))
io.Copy(buf, tr) io.Copy(buf, tr)
dir, base := filepath.Split(filepath.Clean(hdr.Name)) dir, base := filepath.Split(filepath.Clean(hdr.Name))
...@@ -89,16 +84,43 @@ func (r *tarRoot) OnAdd(ctx context.Context) { ...@@ -89,16 +84,43 @@ func (r *tarRoot) OnAdd(ctx context.Context) {
p = ch p = ch
} }
if hdr.Typeflag == tar.TypeSymlink { var attr fuse.Attr
p.AddChild(base, r.NewPersistentInode(ctx, &nodefs.MemSymlink{ HeaderToFileInfo(&attr, hdr)
switch hdr.Typeflag {
case tar.TypeSymlink:
l := &nodefs.MemSymlink{
Data: []byte(hdr.Linkname), Data: []byte(hdr.Linkname),
}, nodefs.NodeAttr{Mode: syscall.S_IFLNK}), false) }
} else { l.Attr = attr
p.AddChild(base, r.NewPersistentInode(ctx, l, nodefs.NodeAttr{Mode: syscall.S_IFLNK}), false)
case tar.TypeLink:
log.Println("don't know how to handle Typelink")
case tar.TypeChar:
rf := &nodefs.MemRegularFile{}
rf.Attr = attr
p.AddChild(base, r.NewPersistentInode(ctx, rf, nodefs.NodeAttr{Mode: syscall.S_IFCHR}), false)
case tar.TypeBlock:
rf := &nodefs.MemRegularFile{}
rf.Attr = attr
p.AddChild(base, r.NewPersistentInode(ctx, rf, nodefs.NodeAttr{Mode: syscall.S_IFBLK}), false)
case tar.TypeDir:
rf := &nodefs.MemRegularFile{}
rf.Attr = attr
p.AddChild(base, r.NewPersistentInode(ctx, rf, nodefs.NodeAttr{Mode: syscall.S_IFDIR}), false)
case tar.TypeFifo:
rf := &nodefs.MemRegularFile{}
rf.Attr = attr
p.AddChild(base, r.NewPersistentInode(ctx, rf, nodefs.NodeAttr{Mode: syscall.S_IFIFO}), false)
case tar.TypeReg, tar.TypeRegA:
df := &nodefs.MemRegularFile{ df := &nodefs.MemRegularFile{
Data: buf.Bytes(), Data: buf.Bytes(),
} }
HeaderToFileInfo(&df.Attr, hdr) df.Attr = attr
p.AddChild(base, r.NewPersistentInode(ctx, df, nodefs.NodeAttr{}), false) p.AddChild(base, r.NewPersistentInode(ctx, df, nodefs.NodeAttr{}), false)
default:
log.Printf("entry %q: unsupported type '%c'", hdr.Name, hdr.Typeflag)
} }
} }
} }
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"syscall" "syscall"
"testing" "testing"
"time" "time"
...@@ -20,6 +21,7 @@ import ( ...@@ -20,6 +21,7 @@ import (
) )
var tarContents = map[string]string{ var tarContents = map[string]string{
"emptydir/": "",
"file.txt": "content", "file.txt": "content",
"dir/subfile.txt": "other content", "dir/subfile.txt": "other content",
} }
...@@ -48,14 +50,16 @@ func TestTar(t *testing.T) { ...@@ -48,14 +50,16 @@ func TestTar(t *testing.T) {
} }
isLink := filepath.Base(k) == "link" isLink := filepath.Base(k) == "link"
isDir := strings.HasSuffix(k, "/")
if isLink { if isLink {
h.Typeflag = tar.TypeSymlink h.Typeflag = tar.TypeSymlink
h.Linkname = v h.Linkname = v
} else if isDir {
h.Typeflag = tar.TypeDir
} }
w.WriteHeader(h) w.WriteHeader(h)
if !isLink { if !isLink && !isDir {
w.Write([]byte(v)) w.Write([]byte(v))
} }
} }
...@@ -89,9 +93,15 @@ func TestTar(t *testing.T) { ...@@ -89,9 +93,15 @@ func TestTar(t *testing.T) {
if got != want { if got != want {
t.Errorf("Readlink: got %q want %q", got, want) t.Errorf("Readlink: got %q want %q", got, want)
} }
} else if strings.HasSuffix(k, "/") {
if got, want := st.Mode, uint32(syscall.S_IFDIR|0464); got != want {
t.Errorf("dir %q: got mode %o, want %o", k, got, want)
}
} else { } else {
if got, want := st.Mode, uint32(syscall.S_IFREG|0464); got != want { if got, want := st.Mode, uint32(syscall.S_IFREG|0464); got != want {
t.Errorf("got mode %o, want %o", got, want) t.Errorf("entry %q, got mode %o, want %o", k, got, want)
} }
c, err := ioutil.ReadFile(p) c, err := ioutil.ReadFile(p)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment