Commit b229cb17 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Move LoopbackFileSystem into core go-fuse library.

parent c0b9bca3
...@@ -2,7 +2,6 @@ package main ...@@ -2,7 +2,6 @@ package main
import ( import (
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/examplelib"
"fmt" "fmt"
"os" "os"
"expvar" "expvar"
...@@ -23,7 +22,7 @@ func main() { ...@@ -23,7 +22,7 @@ func main() {
} }
orig := flag.Arg(0) orig := flag.Arg(0)
fs := examplelib.NewLoopbackFileSystem(orig) fs := fuse.NewLoopbackFileSystem(orig)
conn := fuse.NewPathFileSystemConnector(fs) conn := fuse.NewPathFileSystemConnector(fs)
state := fuse.NewMountState(conn) state := fuse.NewMountState(conn)
state.Debug = *debug state.Debug = *debug
......
...@@ -5,8 +5,7 @@ TARG=github.com/hanwen/go-fuse/examplelib ...@@ -5,8 +5,7 @@ TARG=github.com/hanwen/go-fuse/examplelib
DEPS=../fuse DEPS=../fuse
GOFILES=loopback.go \ GOFILES=stackfs.go \
stackfs.go \
zipfs.go \ zipfs.go \
multizip.go \ multizip.go \
misc.go misc.go
......
...@@ -41,8 +41,8 @@ func (me *stackFsTestCase) Setup(t *testing.T) { ...@@ -41,8 +41,8 @@ func (me *stackFsTestCase) Setup(t *testing.T) {
os.Mkdir(me.origDir2, 0700) os.Mkdir(me.origDir2, 0700)
os.Mkdir(me.mountDir, 0700) os.Mkdir(me.mountDir, 0700)
fs1 := fuse.NewPathFileSystemConnector(NewLoopbackFileSystem(me.origDir1)) fs1 := fuse.NewPathFileSystemConnector(fuse.NewLoopbackFileSystem(me.origDir1))
fs2 := fuse.NewPathFileSystemConnector(NewLoopbackFileSystem(me.origDir2)) fs2 := fuse.NewPathFileSystemConnector(fuse.NewLoopbackFileSystem(me.origDir2))
me.fs = NewSubmountFileSystem() me.fs = NewSubmountFileSystem()
...@@ -154,7 +154,7 @@ func (me *stackFsTestCase) testAddRemove() { ...@@ -154,7 +154,7 @@ func (me *stackFsTestCase) testAddRemove() {
Mode: 0755, Mode: 0755,
} }
conn := fuse.NewPathFileSystemConnector(NewLoopbackFileSystem(me.origDir1)) conn := fuse.NewPathFileSystemConnector(fuse.NewLoopbackFileSystem(me.origDir1))
ok := me.fs.AddFileSystem("sub1", conn, attr) ok := me.fs.AddFileSystem("sub1", conn, attr)
if ok { if ok {
me.tester.Errorf("AddFileSystem should fail") me.tester.Errorf("AddFileSystem should fail")
......
...@@ -12,7 +12,8 @@ GOFILES=misc.go\ ...@@ -12,7 +12,8 @@ GOFILES=misc.go\
pathfilesystem.go \ pathfilesystem.go \
bufferpool.go \ bufferpool.go \
default.go \ default.go \
datafile.go datafile.go \
loopback.go
include $(GOROOT)/src/Make.pkg include $(GOROOT)/src/Make.pkg
...@@ -2,10 +2,9 @@ ...@@ -2,10 +2,9 @@
// system. Its main purpose is to provide test coverage without // system. Its main purpose is to provide test coverage without
// having to build an actual synthetic filesystem. // having to build an actual synthetic filesystem.
package examplelib package fuse
import ( import (
"github.com/hanwen/go-fuse/fuse"
"fmt" "fmt"
"os" "os"
"path" "path"
...@@ -17,7 +16,7 @@ var _ = fmt.Println ...@@ -17,7 +16,7 @@ var _ = fmt.Println
type LoopbackFileSystem struct { type LoopbackFileSystem struct {
root string root string
fuse.DefaultPathFilesystem DefaultPathFilesystem
} }
func NewLoopbackFileSystem(root string) (out *LoopbackFileSystem) { func NewLoopbackFileSystem(root string) (out *LoopbackFileSystem) {
...@@ -31,32 +30,32 @@ func (me *LoopbackFileSystem) GetPath(relPath string) string { ...@@ -31,32 +30,32 @@ func (me *LoopbackFileSystem) GetPath(relPath string) string {
return path.Join(me.root, relPath) return path.Join(me.root, relPath)
} }
func (me *LoopbackFileSystem) GetAttr(name string) (*fuse.Attr, fuse.Status) { func (me *LoopbackFileSystem) GetAttr(name string) (*Attr, Status) {
fullPath := me.GetPath(name) fullPath := me.GetPath(name)
fi, err := os.Lstat(fullPath) fi, err := os.Lstat(fullPath)
if err != nil { if err != nil {
return nil, fuse.ENOENT return nil, ENOENT
} }
out := new(fuse.Attr) out := new(Attr)
fuse.CopyFileInfo(fi, out) CopyFileInfo(fi, out)
return out, fuse.OK return out, OK
} }
func (me *LoopbackFileSystem) OpenDir(name string) (stream chan fuse.DirEntry, status fuse.Status) { func (me *LoopbackFileSystem) OpenDir(name string) (stream chan DirEntry, status Status) {
// What other ways beyond O_RDONLY are there to open // What other ways beyond O_RDONLY are there to open
// directories? // directories?
f, err := os.Open(me.GetPath(name), os.O_RDONLY, 0) f, err := os.Open(me.GetPath(name), os.O_RDONLY, 0)
if err != nil { if err != nil {
return nil, fuse.OsErrorToFuseError(err) return nil, OsErrorToFuseError(err)
} }
output := make(chan fuse.DirEntry, 500) output := make(chan DirEntry, 500)
go func() { go func() {
for { for {
want := 500 want := 500
infos, err := f.Readdir(want) infos, err := f.Readdir(want)
for i, _ := range infos { for i, _ := range infos {
output <- fuse.DirEntry{ output <- DirEntry{
Name: infos[i].Name, Name: infos[i].Name,
Mode: infos[i].Mode, Mode: infos[i].Mode,
} }
...@@ -69,82 +68,82 @@ func (me *LoopbackFileSystem) OpenDir(name string) (stream chan fuse.DirEntry, s ...@@ -69,82 +68,82 @@ func (me *LoopbackFileSystem) OpenDir(name string) (stream chan fuse.DirEntry, s
break break
} }
} }
output <- fuse.DirEntry{} output <- DirEntry{}
f.Close() f.Close()
}() }()
return output, fuse.OK return output, OK
} }
func (me *LoopbackFileSystem) Open(name string, flags uint32) (fuseFile fuse.RawFuseFile, status fuse.Status) { func (me *LoopbackFileSystem) Open(name string, flags uint32) (fuseFile RawFuseFile, status Status) {
f, err := os.Open(me.GetPath(name), int(flags), 0) f, err := os.Open(me.GetPath(name), int(flags), 0)
if err != nil { if err != nil {
return nil, fuse.OsErrorToFuseError(err) return nil, OsErrorToFuseError(err)
} }
return &LoopbackFile{file: f}, fuse.OK return &LoopbackFile{file: f}, OK
} }
func (me *LoopbackFileSystem) Chmod(path string, mode uint32) (code fuse.Status) { func (me *LoopbackFileSystem) Chmod(path string, mode uint32) (code Status) {
err := os.Chmod(me.GetPath(path), mode) err := os.Chmod(me.GetPath(path), mode)
return fuse.OsErrorToFuseError(err) return OsErrorToFuseError(err)
} }
func (me *LoopbackFileSystem) Chown(path string, uid uint32, gid uint32) (code fuse.Status) { func (me *LoopbackFileSystem) Chown(path string, uid uint32, gid uint32) (code Status) {
return fuse.OsErrorToFuseError(os.Chown(me.GetPath(path), int(uid), int(gid))) return OsErrorToFuseError(os.Chown(me.GetPath(path), int(uid), int(gid)))
} }
func (me *LoopbackFileSystem) Truncate(path string, offset uint64) (code fuse.Status) { func (me *LoopbackFileSystem) Truncate(path string, offset uint64) (code Status) {
return fuse.OsErrorToFuseError(os.Truncate(me.GetPath(path), int64(offset))) return OsErrorToFuseError(os.Truncate(me.GetPath(path), int64(offset)))
} }
func (me *LoopbackFileSystem) Utimens(path string, AtimeNs uint64, MtimeNs uint64) (code fuse.Status) { func (me *LoopbackFileSystem) Utimens(path string, AtimeNs uint64, MtimeNs uint64) (code Status) {
return fuse.OsErrorToFuseError(os.Chtimes(me.GetPath(path), int64(AtimeNs), int64(MtimeNs))) return OsErrorToFuseError(os.Chtimes(me.GetPath(path), int64(AtimeNs), int64(MtimeNs)))
} }
func (me *LoopbackFileSystem) Readlink(name string) (out string, code fuse.Status) { func (me *LoopbackFileSystem) Readlink(name string) (out string, code Status) {
f, err := os.Readlink(me.GetPath(name)) f, err := os.Readlink(me.GetPath(name))
return f, fuse.OsErrorToFuseError(err) return f, OsErrorToFuseError(err)
} }
func (me *LoopbackFileSystem) Mknod(name string, mode uint32, dev uint32) (code fuse.Status) { func (me *LoopbackFileSystem) Mknod(name string, mode uint32, dev uint32) (code Status) {
return fuse.Status(syscall.Mknod(me.GetPath(name), mode, int(dev))) return Status(syscall.Mknod(me.GetPath(name), mode, int(dev)))
} }
func (me *LoopbackFileSystem) Mkdir(path string, mode uint32) (code fuse.Status) { func (me *LoopbackFileSystem) Mkdir(path string, mode uint32) (code Status) {
return fuse.OsErrorToFuseError(os.Mkdir(me.GetPath(path), mode)) return OsErrorToFuseError(os.Mkdir(me.GetPath(path), mode))
} }
func (me *LoopbackFileSystem) Unlink(name string) (code fuse.Status) { func (me *LoopbackFileSystem) Unlink(name string) (code Status) {
return fuse.OsErrorToFuseError(os.Remove(me.GetPath(name))) return OsErrorToFuseError(os.Remove(me.GetPath(name)))
} }
func (me *LoopbackFileSystem) Rmdir(name string) (code fuse.Status) { func (me *LoopbackFileSystem) Rmdir(name string) (code Status) {
return fuse.OsErrorToFuseError(os.Remove(me.GetPath(name))) return OsErrorToFuseError(os.Remove(me.GetPath(name)))
} }
func (me *LoopbackFileSystem) Symlink(pointedTo string, linkName string) (code fuse.Status) { func (me *LoopbackFileSystem) Symlink(pointedTo string, linkName string) (code Status) {
return fuse.OsErrorToFuseError(os.Symlink(pointedTo, me.GetPath(linkName))) return OsErrorToFuseError(os.Symlink(pointedTo, me.GetPath(linkName)))
} }
func (me *LoopbackFileSystem) Rename(oldPath string, newPath string) (code fuse.Status) { func (me *LoopbackFileSystem) Rename(oldPath string, newPath string) (code Status) {
err := os.Rename(me.GetPath(oldPath), me.GetPath(newPath)) err := os.Rename(me.GetPath(oldPath), me.GetPath(newPath))
return fuse.OsErrorToFuseError(err) return OsErrorToFuseError(err)
} }
func (me *LoopbackFileSystem) Link(orig string, newName string) (code fuse.Status) { func (me *LoopbackFileSystem) Link(orig string, newName string) (code Status) {
return fuse.OsErrorToFuseError(os.Link(me.GetPath(orig), me.GetPath(newName))) return OsErrorToFuseError(os.Link(me.GetPath(orig), me.GetPath(newName)))
} }
func (me *LoopbackFileSystem) Access(name string, mode uint32) (code fuse.Status) { func (me *LoopbackFileSystem) Access(name string, mode uint32) (code Status) {
return fuse.Status(syscall.Access(me.GetPath(name), mode)) return Status(syscall.Access(me.GetPath(name), mode))
} }
func (me *LoopbackFileSystem) Create(path string, flags uint32, mode uint32) (fuseFile fuse.RawFuseFile, code fuse.Status) { func (me *LoopbackFileSystem) Create(path string, flags uint32, mode uint32) (fuseFile RawFuseFile, code Status) {
f, err := os.Open(me.GetPath(path), int(flags)|os.O_CREAT, mode) f, err := os.Open(me.GetPath(path), int(flags)|os.O_CREAT, mode)
return &LoopbackFile{file: f}, fuse.OsErrorToFuseError(err) return &LoopbackFile{file: f}, OsErrorToFuseError(err)
} }
func (me *LoopbackFileSystem) SetOptions(options *fuse.PathFileSystemConnectorOptions) { func (me *LoopbackFileSystem) SetOptions(options *PathFileSystemConnectorOptions) {
options.NegativeTimeout = 100.0 options.NegativeTimeout = 100.0
options.AttrTimeout = 100.0 options.AttrTimeout = 100.0
options.EntryTimeout = 100.0 options.EntryTimeout = 100.0
...@@ -155,29 +154,29 @@ func (me *LoopbackFileSystem) SetOptions(options *fuse.PathFileSystemConnectorOp ...@@ -155,29 +154,29 @@ func (me *LoopbackFileSystem) SetOptions(options *fuse.PathFileSystemConnectorOp
type LoopbackFile struct { type LoopbackFile struct {
file *os.File file *os.File
fuse.DefaultRawFuseFile DefaultRawFuseFile
} }
func (me *LoopbackFile) Read(input *fuse.ReadIn, buffers *fuse.BufferPool) ([]byte, fuse.Status) { func (me *LoopbackFile) Read(input *ReadIn, buffers *BufferPool) ([]byte, Status) {
slice := buffers.AllocBuffer(input.Size) slice := buffers.AllocBuffer(input.Size)
n, err := me.file.ReadAt(slice, int64(input.Offset)) n, err := me.file.ReadAt(slice, int64(input.Offset))
if err == os.EOF { if err == os.EOF {
// TODO - how to signal EOF? // TODO - how to signal EOF?
return slice[:n], fuse.OK return slice[:n], OK
} }
return slice[:n], fuse.OsErrorToFuseError(err) return slice[:n], OsErrorToFuseError(err)
} }
func (me *LoopbackFile) Write(input *fuse.WriteIn, data []byte) (uint32, fuse.Status) { func (me *LoopbackFile) Write(input *WriteIn, data []byte) (uint32, Status) {
n, err := me.file.WriteAt(data, int64(input.Offset)) n, err := me.file.WriteAt(data, int64(input.Offset))
return uint32(n), fuse.OsErrorToFuseError(err) return uint32(n), OsErrorToFuseError(err)
} }
func (me *LoopbackFile) Release() { func (me *LoopbackFile) Release() {
me.file.Close() me.file.Close()
} }
func (me *LoopbackFile) Fsync(*fuse.FsyncIn) (code fuse.Status) { func (me *LoopbackFile) Fsync(*FsyncIn) (code Status) {
return fuse.Status(syscall.Fsync(me.file.Fd())) return Status(syscall.Fsync(me.file.Fd()))
} }
package examplelib package fuse
import ( import (
"github.com/hanwen/go-fuse/fuse"
"bytes" "bytes"
"fmt" "fmt"
"log" "log"
...@@ -33,8 +32,8 @@ type testCase struct { ...@@ -33,8 +32,8 @@ type testCase struct {
origSubdir string origSubdir string
origSubfile string origSubfile string
tester *testing.T tester *testing.T
state *fuse.MountState state *MountState
connector *fuse.PathFileSystemConnector connector *PathFileSystemConnector
} }
// Create and mount filesystem. // Create and mount filesystem.
...@@ -44,8 +43,8 @@ func (me *testCase) Setup(t *testing.T) { ...@@ -44,8 +43,8 @@ func (me *testCase) Setup(t *testing.T) {
const name string = "hello.txt" const name string = "hello.txt"
const subdir string = "subdir" const subdir string = "subdir"
me.origDir = fuse.MakeTempDir() me.origDir = MakeTempDir()
me.mountPoint = fuse.MakeTempDir() me.mountPoint = MakeTempDir()
me.mountFile = path.Join(me.mountPoint, name) me.mountFile = path.Join(me.mountPoint, name)
me.mountSubdir = path.Join(me.mountPoint, subdir) me.mountSubdir = path.Join(me.mountPoint, subdir)
...@@ -55,9 +54,9 @@ func (me *testCase) Setup(t *testing.T) { ...@@ -55,9 +54,9 @@ func (me *testCase) Setup(t *testing.T) {
me.origSubfile = path.Join(me.origSubdir, "subfile") me.origSubfile = path.Join(me.origSubdir, "subfile")
pfs := NewLoopbackFileSystem(me.origDir) pfs := NewLoopbackFileSystem(me.origDir)
me.connector = fuse.NewPathFileSystemConnector(pfs) me.connector = NewPathFileSystemConnector(pfs)
me.connector.Debug = true me.connector.Debug = true
me.state = fuse.NewMountState(me.connector) me.state = NewMountState(me.connector)
me.state.Mount(me.mountPoint) me.state.Mount(me.mountPoint)
//me.state.Debug = false //me.state.Debug = false
...@@ -272,10 +271,12 @@ func (me *testCase) testRename() { ...@@ -272,10 +271,12 @@ func (me *testCase) testRename() {
err := os.Rename(me.mountFile, me.mountSubfile) err := os.Rename(me.mountFile, me.mountSubfile)
CheckSuccess(err) CheckSuccess(err)
if FileExists(me.origFile) { f, _ := os.Lstat(me.origFile)
if f != nil {
me.tester.Errorf("original %v still exists.", me.origFile) me.tester.Errorf("original %v still exists.", me.origFile)
} }
if !FileExists(me.origSubfile) { f, _ = os.Lstat(me.origSubfile)
if f == nil {
me.tester.Errorf("destination %v does not exist.", me.origSubfile) me.tester.Errorf("destination %v does not exist.", me.origSubfile)
} }
...@@ -532,7 +533,7 @@ func TestRecursiveMount(t *testing.T) { ...@@ -532,7 +533,7 @@ func TestRecursiveMount(t *testing.T) {
pfs2 := NewLoopbackFileSystem(ts.origDir) pfs2 := NewLoopbackFileSystem(ts.origDir)
code := ts.connector.Mount("/hello.txt", pfs2) code := ts.connector.Mount("/hello.txt", pfs2)
if code != fuse.EINVAL { if code != EINVAL {
t.Error("expect EINVAL", code) t.Error("expect EINVAL", code)
} }
...@@ -540,7 +541,7 @@ func TestRecursiveMount(t *testing.T) { ...@@ -540,7 +541,7 @@ func TestRecursiveMount(t *testing.T) {
err = os.Mkdir(submnt, 0777) err = os.Mkdir(submnt, 0777)
CheckSuccess(err) CheckSuccess(err)
code = ts.connector.Mount("/mnt", pfs2) code = ts.connector.Mount("/mnt", pfs2)
if code != fuse.OK { if code != OK {
t.Errorf("mkdir") t.Errorf("mkdir")
} }
...@@ -552,17 +553,17 @@ func TestRecursiveMount(t *testing.T) { ...@@ -552,17 +553,17 @@ func TestRecursiveMount(t *testing.T) {
f, err = os.Open(path.Join(submnt, "hello.txt"), os.O_RDONLY, 0) f, err = os.Open(path.Join(submnt, "hello.txt"), os.O_RDONLY, 0)
CheckSuccess(err) CheckSuccess(err)
code = ts.connector.Unmount("/mnt") code = ts.connector.Unmount("/mnt")
if code != fuse.EBUSY { if code != EBUSY {
t.Error("expect EBUSY") t.Error("expect EBUSY")
} }
f.Close() f.Close()
// The close takes some time to propagate through FUSE. // The close takes some time to propagate through
time.Sleep(1e9) time.Sleep(1e9)
code = ts.connector.Unmount("/mnt") code = ts.connector.Unmount("/mnt")
if code != fuse.OK { if code != OK {
t.Error("umount failed.", code) t.Error("umount failed.", code)
} }
......
...@@ -295,3 +295,11 @@ func NegativeEntry(time float64) *EntryOut { ...@@ -295,3 +295,11 @@ func NegativeEntry(time float64) *EntryOut {
func ModeToType(mode uint32) uint32 { func ModeToType(mode uint32) uint32 {
return (mode & 0170000) >> 12 return (mode & 0170000) >> 12
} }
func CheckSuccess(e os.Error) {
if e != nil {
panic(fmt.Sprintf("Unexpected error: %v", e))
}
}
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