Commit 0a3f35a3 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Create NewTarTree() and accept .tar.gz and .tar.bz2.

parent 0ec6d90d
...@@ -23,9 +23,9 @@ func main() { ...@@ -23,9 +23,9 @@ func main() {
} }
var fs fuse.FileSystem var fs fuse.FileSystem
fs, err := zipfs.NewZipArchiveFileSystem(flag.Arg(1)) fs, err := zipfs.NewArchiveFileSystem(flag.Arg(1))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "NewZipArchiveFileSystem failed: %v\n", err) fmt.Fprintf(os.Stderr, "NewArchiveFileSystem failed: %v\n", err)
os.Exit(1) os.Exit(1)
} }
debugFs := fuse.NewFileSystemDebug() debugFs := fuse.NewFileSystemDebug()
......
...@@ -6,6 +6,7 @@ DEPS=../fuse ...@@ -6,6 +6,7 @@ DEPS=../fuse
GOFILES=zipfs.go \ GOFILES=zipfs.go \
multizip.go \ multizip.go \
tarfs.go \
memtree.go memtree.go
include $(GOROOT)/src/Make.pkg include $(GOROOT)/src/Make.pkg
......
...@@ -43,10 +43,10 @@ func (me *zipCreateFile) Write(input *fuse.WriteIn, nameBytes []byte) (uint32, f ...@@ -43,10 +43,10 @@ func (me *zipCreateFile) Write(input *fuse.WriteIn, nameBytes []byte) (uint32, f
zipFile := string(nameBytes) zipFile := string(nameBytes)
zipFile = strings.Trim(zipFile, "\n ") zipFile = strings.Trim(zipFile, "\n ")
fs, err := NewZipArchiveFileSystem(zipFile) fs, err := NewArchiveFileSystem(zipFile)
if err != nil { if err != nil {
// TODO // TODO
log.Println("NewZipArchiveFileSystem failed:", err) log.Println("NewZipArchiveFileSystem failed.")
me.zfs.pendingZips[me.Basename] = false, false me.zfs.pendingZips[me.Basename] = false, false
return 0, fuse.ENOSYS return 0, fuse.ENOSYS
} }
......
package zipfs
import (
"archive/tar"
"bytes"
"compress/bzip2"
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"syscall"
)
var _ = fmt.Println
// TODO - handle symlinks.
func HeaderToFileInfo(h *tar.Header) *os.FileInfo {
return &os.FileInfo{
Name: h.Name,
Mode: uint32(h.Mode),
Uid: h.Uid,
Gid: h.Gid,
Size: h.Size,
Mtime_ns: h.Mtime,
//Linkname: h.Linkname ,
Atime_ns: h.Atime,
Ctime_ns: h.Ctime,
}
}
type TarFile struct {
data []byte
tar.Header
}
func (me *TarFile) Stat() *os.FileInfo {
fi := HeaderToFileInfo(&me.Header)
fi.Mode |= syscall.S_IFREG
return fi
}
func (me *TarFile) Data() []byte {
return me.data
}
func NewTarTree(r io.Reader) *MemTree {
tree := NewMemTree()
tr := tar.NewReader(r)
var longName *string
for {
hdr, err := tr.Next()
if err == os.EOF {
// end of tar archive
break
}
if err != nil {
// handle error
}
if hdr.Typeflag == 'L' {
buf := bytes.NewBuffer(make([]byte, 0, hdr.Size))
io.Copy(buf, tr)
s := buf.String()
longName = &s
continue
}
if longName != nil {
hdr.Name = *longName
longName = nil
}
comps := strings.Split(filepath.Clean(hdr.Name), "/", -1)
base := ""
if !strings.HasSuffix(hdr.Name, "/") {
base = comps[len(comps)-1]
comps = comps[:len(comps)-1]
}
parent := tree
for _, c := range comps {
parent = parent.FindDir(c)
}
buf := bytes.NewBuffer(make([]byte, 0, hdr.Size))
io.Copy(buf, tr)
if base != "" {
b := buf.Bytes()
parent.files[base] = &TarFile{
Header: *hdr,
data: b,
}
}
}
return tree
}
func NewTarCompressedTree(name string, format string) (*MemTree, os.Error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
var stream io.Reader
switch format {
case "gz":
unzip, err := gzip.NewReader(f)
if err != nil {
return nil, err
}
defer unzip.Close()
stream = unzip
case "bz2":
unzip := bzip2.NewReader(f)
stream = unzip
}
return NewTarTree(stream), nil
}
...@@ -72,11 +72,32 @@ func zipFilesToTree(files []*zip.File) *MemTree { ...@@ -72,11 +72,32 @@ func zipFilesToTree(files []*zip.File) *MemTree {
// NewZipArchiveFileSystem creates a new file-system for the // NewZipArchiveFileSystem creates a new file-system for the
// zip file named name. // zip file named name.
func NewZipArchiveFileSystem(name string) (*MemTreeFileSystem, os.Error) { func NewZipTree(name string) (*MemTree, os.Error) {
r, err := zip.OpenReader(name) r, err := zip.OpenReader(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
z := NewMemTreeFileSystem(zipFilesToTree(r.File)) return zipFilesToTree(r.File), nil
return z, nil }
func NewArchiveFileSystem(name string) (fs *MemTreeFileSystem, err os.Error) {
var tree *MemTree
if strings.HasSuffix(name, ".zip") {
tree, err = NewZipTree(name)
}
if strings.HasSuffix(name, ".tar.gz") {
tree, err = NewTarCompressedTree(name, "gz")
}
if strings.HasSuffix(name, ".tar.bz2") {
tree, err = NewTarCompressedTree(name, "bz2")
}
if err != nil {
return nil, err
}
if tree == nil {
return nil, os.NewError(fmt.Sprintf("Unknown type for %v", name))
}
return NewMemTreeFileSystem(tree), nil
} }
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
func TestZipFs(t *testing.T) { func TestZipFs(t *testing.T) {
wd, err := os.Getwd() wd, err := os.Getwd()
CheckSuccess(err) CheckSuccess(err)
zfs, err := NewZipArchiveFileSystem(wd + "/test.zip") zfs, err := NewArchiveFileSystem(wd + "/test.zip")
if err != nil { if err != nil {
t.Error("NewZipArchiveFileSystem failed:", err) t.Error("NewZipArchiveFileSystem failed:", err)
} }
......
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