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

Move path filesystems to a separate package.

Callers can apply the following gofmt rules:

gofmt -w -r 'fuse.NewPathNodeFs -> pathfs.NewPathNodeFs' $*
gofmt -w -r 'fuse.FileSystem -> pathfs.FileSystem' $*
gofmt -w -r 'fuse.LoopbackFileSystem -> pathfs.LoopbackFileSystem' $*
gofmt -w -r 'fuse.LockingFileSystem -> pathfs.LockingFileSystem' $*
gofmt -w -r 'fuse.PathNodeFs -> pathfs.PathNodeFs' $*
gofmt -w -r 'fuse.PathNodeFsOptions -> pathfs.PathNodeFsOptions' $*
gofmt -w -r 'fuse.DefaultFileSystem -> pathfs.DefaultFileSystem' $*
gofmt -w -r 'fuse.NewLoopbackFileSystem -> pathfs.NewLoopbackFileSystem' $*
gofmt -w -r 'fuse.NewLockingFileSystem -> pathfs.NewLockingFileSystem' $*
gofmt -w -r 'fuse.CopyFile -> pathfs.CopyFile' $*
parent a393c5e2
...@@ -4,7 +4,7 @@ set -eux ...@@ -4,7 +4,7 @@ set -eux
sh genversion.sh fuse/version.gen.go sh genversion.sh fuse/version.gen.go
for target in "clean" "install" ; do for target in "clean" "install" ; do
for d in raw fuse benchmark zipfs unionfs \ for d in raw fuse zipfs unionfs \
example/hello example/loopback example/zipfs \ example/hello example/loopback example/zipfs \
example/multizip example/unionfs \ example/multizip example/unionfs \
example/autounionfs ; \ example/autounionfs ; \
......
...@@ -14,14 +14,14 @@ import ( ...@@ -14,14 +14,14 @@ import (
"time" "time"
) )
func setupFs(fs fuse.FileSystem) (string, func()) { func setupFs(fs pathfs.FileSystem) (string, func()) {
opts := &fuse.FileSystemOptions{ opts := &fuse.FileSystemOptions{
EntryTimeout: 0.0, EntryTimeout: 0.0,
AttrTimeout: 0.0, AttrTimeout: 0.0,
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
} }
mountPoint, _ := ioutil.TempDir("", "stat_test") mountPoint, _ := ioutil.TempDir("", "stat_test")
nfs := fuse.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, opts) state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, opts)
if err != nil { if err != nil {
panic(fmt.Sprintf("cannot mount %v", err)) // ugh - benchmark has no error methods. panic(fmt.Sprintf("cannot mount %v", err)) // ugh - benchmark has no error methods.
......
package benchmark package benchmark
import ( import (
"github.com/hanwen/go-fuse/fuse"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var delay = 0 * time.Microsecond var delay = 0 * time.Microsecond
type StatFs struct { type StatFs struct {
fuse.DefaultFileSystem pathfs.DefaultFileSystem
entries map[string]*fuse.Attr entries map[string]*fuse.Attr
dirs map[string][]fuse.DirEntry dirs map[string][]fuse.DirEntry
delay time.Duration delay time.Duration
......
...@@ -3,10 +3,12 @@ package main ...@@ -3,10 +3,12 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/unionfs"
"os" "os"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/unionfs"
) )
func main() { func main() {
...@@ -48,7 +50,7 @@ func main() { ...@@ -48,7 +50,7 @@ func main() {
Owner: fuse.CurrentOwner(), Owner: fuse.CurrentOwner(),
}, },
UpdateOnMount: true, UpdateOnMount: true,
PathNodeFsOptions: fuse.PathNodeFsOptions{ PathNodeFsOptions: pathfs.PathNodeFsOptions{
ClientInodes: *hardlinks, ClientInodes: *hardlinks,
}, },
HideReadonly: *hide_readonly_link, HideReadonly: *hide_readonly_link,
...@@ -58,7 +60,7 @@ func main() { ...@@ -58,7 +60,7 @@ func main() {
} }
fmt.Printf("AutoUnionFs - Go-FUSE Version %v.\n", fuse.Version()) fmt.Printf("AutoUnionFs - Go-FUSE Version %v.\n", fuse.Version())
gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options) gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options)
pathfs := fuse.NewPathNodeFs(gofs, nil) pathfs := pathfs.NewPathNodeFs(gofs, nil)
state, conn, err := fuse.MountNodeFileSystem(flag.Arg(0), pathfs, &fsOpts) state, conn, err := fuse.MountNodeFileSystem(flag.Arg(0), pathfs, &fsOpts)
if err != nil { if err != nil {
fmt.Printf("Mount fail: %v\n", err) fmt.Printf("Mount fail: %v\n", err)
......
...@@ -4,12 +4,14 @@ package main ...@@ -4,12 +4,14 @@ package main
import ( import (
"flag" "flag"
"github.com/hanwen/go-fuse/fuse"
"log" "log"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
type HelloFs struct { type HelloFs struct {
fuse.DefaultFileSystem pathfs.DefaultFileSystem
} }
func (me *HelloFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) { func (me *HelloFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
...@@ -49,7 +51,7 @@ func main() { ...@@ -49,7 +51,7 @@ func main() {
if len(flag.Args()) < 1 { if len(flag.Args()) < 1 {
log.Fatal("Usage:\n hello MOUNTPOINT") log.Fatal("Usage:\n hello MOUNTPOINT")
} }
nfs := fuse.NewPathNodeFs(&HelloFs{}, nil) nfs := pathfs.NewPathNodeFs(&HelloFs{}, nil)
state, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nfs, nil) state, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nfs, nil)
if err != nil { if err != nil {
log.Fatal("Mount fail: %v\n", err) log.Fatal("Mount fail: %v\n", err)
......
...@@ -6,11 +6,13 @@ package main ...@@ -6,11 +6,13 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"log" "log"
"os" "os"
"runtime" "runtime"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = runtime.GOMAXPROCS var _ = runtime.GOMAXPROCS
...@@ -27,9 +29,9 @@ func main() { ...@@ -27,9 +29,9 @@ func main() {
os.Exit(2) os.Exit(2)
} }
var finalFs fuse.FileSystem var finalFs pathfs.FileSystem
orig := flag.Arg(1) orig := flag.Arg(1)
loopbackfs := fuse.NewLoopbackFileSystem(orig) loopbackfs := pathfs.NewLoopbackFileSystem(orig)
finalFs = loopbackfs finalFs = loopbackfs
opts := &fuse.FileSystemOptions{ opts := &fuse.FileSystemOptions{
...@@ -39,7 +41,7 @@ func main() { ...@@ -39,7 +41,7 @@ func main() {
AttrTimeout: time.Second, AttrTimeout: time.Second,
EntryTimeout: time.Second, EntryTimeout: time.Second,
} }
pathFs := fuse.NewPathNodeFs(finalFs, nil) pathFs := pathfs.NewPathNodeFs(finalFs, nil)
conn := fuse.NewFileSystemConnector(pathFs, opts) conn := fuse.NewFileSystemConnector(pathFs, opts)
state := fuse.NewMountState(conn) state := fuse.NewMountState(conn)
state.Debug = *debug state.Debug = *debug
......
...@@ -3,11 +3,13 @@ package main ...@@ -3,11 +3,13 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/zipfs"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/zipfs"
) )
var _ = log.Printf var _ = log.Printf
...@@ -23,7 +25,7 @@ func main() { ...@@ -23,7 +25,7 @@ func main() {
} }
fs := zipfs.NewMultiZipFs() fs := zipfs.NewMultiZipFs()
nfs := fuse.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nfs, nil) state, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nfs, nil)
if err != nil { if err != nil {
fmt.Printf("Mount fail: %v\n", err) fmt.Printf("Mount fail: %v\n", err)
......
...@@ -3,11 +3,13 @@ package main ...@@ -3,11 +3,13 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/unionfs"
"log" "log"
"os" "os"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/unionfs"
) )
func main() { func main() {
...@@ -39,7 +41,7 @@ func main() { ...@@ -39,7 +41,7 @@ func main() {
log.Fatal("Cannot create UnionFs", err) log.Fatal("Cannot create UnionFs", err)
os.Exit(1) os.Exit(1)
} }
nodeFs := fuse.NewPathNodeFs(ufs, &fuse.PathNodeFsOptions{ClientInodes: true}) nodeFs := pathfs.NewPathNodeFs(ufs, &pathfs.PathNodeFsOptions{ClientInodes: true})
mOpts := fuse.FileSystemOptions{ mOpts := fuse.FileSystemOptions{
EntryTimeout: time.Duration(*entry_ttl * float64(time.Second)), EntryTimeout: time.Duration(*entry_ttl * float64(time.Second)),
AttrTimeout: time.Duration(*entry_ttl * float64(time.Second)), AttrTimeout: time.Duration(*entry_ttl * float64(time.Second)),
......
...@@ -93,73 +93,6 @@ type FsNode interface { ...@@ -93,73 +93,6 @@ type FsNode interface {
StatFs() *StatfsOut StatFs() *StatfsOut
} }
// A filesystem API that uses paths rather than inodes. A minimal
// file system should have at least a functional GetAttr method.
// Typically, each call happens in its own goroutine, so take care to
// make the file system thread-safe.
//
// Include DefaultFileSystem to provide a default null implementation of
// required methods.
type FileSystem interface {
// Used for pretty printing.
String() string
// Attributes. This function is the main entry point, through
// which FUSE discovers which files and directories exist.
//
// If the filesystem wants to implement hard-links, it should
// return consistent non-zero FileInfo.Ino data. Using
// hardlinks incurs a performance hit.
GetAttr(name string, context *Context) (*Attr, Status)
// These should update the file's ctime too.
Chmod(name string, mode uint32, context *Context) (code Status)
Chown(name string, uid uint32, gid uint32, context *Context) (code Status)
Utimens(name string, Atime *time.Time, Mtime *time.Time, context *Context) (code Status)
Truncate(name string, size uint64, context *Context) (code Status)
Access(name string, mode uint32, context *Context) (code Status)
// Tree structure
Link(oldName string, newName string, context *Context) (code Status)
Mkdir(name string, mode uint32, context *Context) Status
Mknod(name string, mode uint32, dev uint32, context *Context) Status
Rename(oldName string, newName string, context *Context) (code Status)
Rmdir(name string, context *Context) (code Status)
Unlink(name string, context *Context) (code Status)
// Extended attributes.
GetXAttr(name string, attribute string, context *Context) (data []byte, code Status)
ListXAttr(name string, context *Context) (attributes []string, code Status)
RemoveXAttr(name string, attr string, context *Context) Status
SetXAttr(name string, attr string, data []byte, flags int, context *Context) Status
// Called after mount.
OnMount(nodeFs *PathNodeFs)
OnUnmount()
// File handling. If opening for writing, the file's mtime
// should be updated too.
Open(name string, flags uint32, context *Context) (file File, code Status)
Create(name string, flags uint32, mode uint32, context *Context) (file File, code Status)
// Directory handling
OpenDir(name string, context *Context) (stream []DirEntry, code Status)
// Symlinks.
Symlink(value string, linkName string, context *Context) (code Status)
Readlink(name string, context *Context) (string, Status)
StatFs(name string) *StatfsOut
}
type PathNodeFsOptions struct {
// If ClientInodes is set, use Inode returned from GetAttr to
// find hard-linked files.
ClientInodes bool
}
// A File object should be returned from FileSystem.Open and // A File object should be returned from FileSystem.Open and
// FileSystem.Create. Include DefaultFile into the struct to inherit // FileSystem.Create. Include DefaultFile into the struct to inherit
// a default null implementation. // a default null implementation.
...@@ -280,9 +213,6 @@ type MountOptions struct { ...@@ -280,9 +213,6 @@ type MountOptions struct {
Name string Name string
} }
// DefaultFileSystem implements a FileSystem that returns ENOSYS for every operation.
type DefaultFileSystem struct{}
// DefaultFile returns ENOSYS for every operation. // DefaultFile returns ENOSYS for every operation.
type DefaultFile struct{} type DefaultFile struct{}
......
...@@ -34,7 +34,7 @@ type FileSystemConnector struct { ...@@ -34,7 +34,7 @@ type FileSystemConnector struct {
// Used as the generation inodes. This must be 64-bit aligned, // Used as the generation inodes. This must be 64-bit aligned,
// for sync/atomic on i386 to work properly. // for sync/atomic on i386 to work properly.
generation uint64 generation uint64
DefaultRawFileSystem DefaultRawFileSystem
Debug bool Debug bool
...@@ -129,7 +129,7 @@ func (c *FileSystemConnector) lookupUpdate(node *Inode) (id uint64) { ...@@ -129,7 +129,7 @@ func (c *FileSystemConnector) lookupUpdate(node *Inode) (id uint64) {
func (c *FileSystemConnector) forgetUpdate(nodeID uint64, forgetCount int) { func (c *FileSystemConnector) forgetUpdate(nodeID uint64, forgetCount int) {
if nodeID == raw.FUSE_ROOT_ID { if nodeID == raw.FUSE_ROOT_ID {
c.nodeFs.OnUnmount() c.nodeFs.OnUnmount()
// We never got a lookup for root, so don't try to // We never got a lookup for root, so don't try to
// forget root. // forget root.
return return
......
...@@ -3,158 +3,10 @@ package fuse ...@@ -3,158 +3,10 @@ package fuse
import ( import (
"fmt" "fmt"
"sync" "sync"
"time"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
// This is a wrapper that makes a FileSystem threadsafe by
// trivially locking all operations. For improved performance, you
// should probably invent do your own locking inside the file system.
type LockingFileSystem struct {
// Should be public so people reusing can access the wrapped
// FS.
FS FileSystem
lock sync.Mutex
}
var _ = ((FileSystem)((*LockingFileSystem)(nil)))
func NewLockingFileSystem(pfs FileSystem) *LockingFileSystem {
l := new(LockingFileSystem)
l.FS = pfs
return l
}
func (fs *LockingFileSystem) String() string {
defer fs.locked()()
return fs.FS.String()
}
func (fs *LockingFileSystem) StatFs(name string) *StatfsOut {
defer fs.locked()()
return fs.FS.StatFs(name)
}
func (fs *LockingFileSystem) locked() func() {
fs.lock.Lock()
return func() { fs.lock.Unlock() }
}
func (fs *LockingFileSystem) GetAttr(name string, context *Context) (*Attr, Status) {
defer fs.locked()()
return fs.FS.GetAttr(name, context)
}
func (fs *LockingFileSystem) Readlink(name string, context *Context) (string, Status) {
defer fs.locked()()
return fs.FS.Readlink(name, context)
}
func (fs *LockingFileSystem) Mknod(name string, mode uint32, dev uint32, context *Context) Status {
defer fs.locked()()
return fs.FS.Mknod(name, mode, dev, context)
}
func (fs *LockingFileSystem) Mkdir(name string, mode uint32, context *Context) Status {
defer fs.locked()()
return fs.FS.Mkdir(name, mode, context)
}
func (fs *LockingFileSystem) Unlink(name string, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Unlink(name, context)
}
func (fs *LockingFileSystem) Rmdir(name string, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Rmdir(name, context)
}
func (fs *LockingFileSystem) Symlink(value string, linkName string, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Symlink(value, linkName, context)
}
func (fs *LockingFileSystem) Rename(oldName string, newName string, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Rename(oldName, newName, context)
}
func (fs *LockingFileSystem) Link(oldName string, newName string, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Link(oldName, newName, context)
}
func (fs *LockingFileSystem) Chmod(name string, mode uint32, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Chmod(name, mode, context)
}
func (fs *LockingFileSystem) Chown(name string, uid uint32, gid uint32, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Chown(name, uid, gid, context)
}
func (fs *LockingFileSystem) Truncate(name string, offset uint64, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Truncate(name, offset, context)
}
func (fs *LockingFileSystem) Open(name string, flags uint32, context *Context) (file File, code Status) {
return fs.FS.Open(name, flags, context)
}
func (fs *LockingFileSystem) OpenDir(name string, context *Context) (stream []DirEntry, status Status) {
defer fs.locked()()
return fs.FS.OpenDir(name, context)
}
func (fs *LockingFileSystem) OnMount(nodeFs *PathNodeFs) {
defer fs.locked()()
fs.FS.OnMount(nodeFs)
}
func (fs *LockingFileSystem) OnUnmount() {
defer fs.locked()()
fs.FS.OnUnmount()
}
func (fs *LockingFileSystem) Access(name string, mode uint32, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Access(name, mode, context)
}
func (fs *LockingFileSystem) Create(name string, flags uint32, mode uint32, context *Context) (file File, code Status) {
defer fs.locked()()
return fs.FS.Create(name, flags, mode, context)
}
func (fs *LockingFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *Context) (code Status) {
defer fs.locked()()
return fs.FS.Utimens(name, Atime, Mtime, context)
}
func (fs *LockingFileSystem) GetXAttr(name string, attr string, context *Context) ([]byte, Status) {
defer fs.locked()()
return fs.FS.GetXAttr(name, attr, context)
}
func (fs *LockingFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *Context) Status {
defer fs.locked()()
return fs.FS.SetXAttr(name, attr, data, flags, context)
}
func (fs *LockingFileSystem) ListXAttr(name string, context *Context) ([]string, Status) {
defer fs.locked()()
return fs.FS.ListXAttr(name, context)
}
func (fs *LockingFileSystem) RemoveXAttr(name string, attr string, context *Context) Status {
defer fs.locked()()
return fs.FS.RemoveXAttr(name, attr, context)
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Locking raw FS. // Locking raw FS.
......
...@@ -175,7 +175,7 @@ func (ms *MountState) Unmount() (err error) { ...@@ -175,7 +175,7 @@ func (ms *MountState) Unmount() (err error) {
time.Sleep(delay) time.Sleep(delay)
} }
if err != nil { if err != nil {
return return
} }
// Wait for event loops to exit. // Wait for event loops to exit.
ms.loops.Wait() ms.loops.Wait()
......
package pathfs
import (
"time"
"github.com/hanwen/go-fuse/fuse"
)
// A filesystem API that uses paths rather than inodes. A minimal
// file system should have at least a functional GetAttr method.
// Typically, each call happens in its own goroutine, so take care to
// make the file system thread-safe.
//
// Include DefaultFileSystem to provide a default null implementation of
// required methods.
type FileSystem interface {
// Used for pretty printing.
String() string
// Attributes. This function is the main entry point, through
// which FUSE discovers which files and directories exist.
//
// If the filesystem wants to implement hard-links, it should
// return consistent non-zero FileInfo.Ino data. Using
// hardlinks incurs a performance hit.
GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status)
// These should update the file's ctime too.
Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status)
Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status)
Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status)
Truncate(name string, size uint64, context *fuse.Context) (code fuse.Status)
Access(name string, mode uint32, context *fuse.Context) (code fuse.Status)
// Tree structure
Link(oldName string, newName string, context *fuse.Context) (code fuse.Status)
Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status
Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status
Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status)
Rmdir(name string, context *fuse.Context) (code fuse.Status)
Unlink(name string, context *fuse.Context) (code fuse.Status)
// Extended attributes.
GetXAttr(name string, attribute string, context *fuse.Context) (data []byte, code fuse.Status)
ListXAttr(name string, context *fuse.Context) (attributes []string, code fuse.Status)
RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status
SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status
// Called after mount.
OnMount(nodeFs *PathNodeFs)
OnUnmount()
// File handling. If opening for writing, the file's mtime
// should be updated too.
Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status)
Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status)
// Directory handling
OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, code fuse.Status)
// Symlinks.
Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status)
Readlink(name string, context *fuse.Context) (string, fuse.Status)
StatFs(name string) *fuse.StatfsOut
}
type PathNodeFsOptions struct {
// If ClientInodes is set, use Inode returned from GetAttr to
// find hard-linked files.
ClientInodes bool
}
package fuse package pathfs
import ( import (
"os" "os"
"github.com/hanwen/go-fuse/fuse"
) )
func CopyFile(srcFs, destFs FileSystem, srcFile, destFile string, context *Context) Status { func CopyFile(srcFs, destFs FileSystem, srcFile, destFile string, context *fuse.Context) fuse.Status {
src, code := srcFs.Open(srcFile, uint32(os.O_RDONLY), context) src, code := srcFs.Open(srcFile, uint32(os.O_RDONLY), context)
if !code.Ok() { if !code.Ok() {
return code return code
...@@ -44,12 +46,12 @@ func CopyFile(srcFs, destFs FileSystem, srcFile, destFile string, context *Conte ...@@ -44,12 +46,12 @@ func CopyFile(srcFs, destFs FileSystem, srcFile, destFile string, context *Conte
return code return code
} }
if int(n) < len(data) { if int(n) < len(data) {
return EIO return fuse.EIO
} }
if len(data) < len(buf) { if len(data) < len(buf) {
break break
} }
off += int64(len(data)) off += int64(len(data))
} }
return OK return fuse.OK
} }
package fuse package pathfs
import ( import (
"io/ioutil" "io/ioutil"
......
package fuse package pathfs
import ( import (
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = FileSystem((*DefaultFileSystem)(nil)) var _ = FileSystem((*DefaultFileSystem)(nil))
// DefaultFileSystem implements a FileSystem that returns ENOSYS for every operation.
type DefaultFileSystem struct{}
// DefaultFileSystem // DefaultFileSystem
func (fs *DefaultFileSystem) GetAttr(name string, context *Context) (*Attr, Status) { func (fs *DefaultFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
func (fs *DefaultFileSystem) GetXAttr(name string, attr string, context *Context) ([]byte, Status) { func (fs *DefaultFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
func (fs *DefaultFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *Context) Status { func (fs *DefaultFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) ListXAttr(name string, context *Context) ([]string, Status) { func (fs *DefaultFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
func (fs *DefaultFileSystem) RemoveXAttr(name string, attr string, context *Context) Status { func (fs *DefaultFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Readlink(name string, context *Context) (string, Status) { func (fs *DefaultFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
return "", ENOSYS return "", fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Mknod(name string, mode uint32, dev uint32, context *Context) Status { func (fs *DefaultFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Mkdir(name string, mode uint32, context *Context) Status { func (fs *DefaultFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Unlink(name string, context *Context) (code Status) { func (fs *DefaultFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Rmdir(name string, context *Context) (code Status) { func (fs *DefaultFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Symlink(value string, linkName string, context *Context) (code Status) { func (fs *DefaultFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Rename(oldName string, newName string, context *Context) (code Status) { func (fs *DefaultFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Link(oldName string, newName string, context *Context) (code Status) { func (fs *DefaultFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Chmod(name string, mode uint32, context *Context) (code Status) { func (fs *DefaultFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Chown(name string, uid uint32, gid uint32, context *Context) (code Status) { func (fs *DefaultFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Truncate(name string, offset uint64, context *Context) (code Status) { func (fs *DefaultFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Open(name string, flags uint32, context *Context) (file File, code Status) { func (fs *DefaultFileSystem) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
func (fs *DefaultFileSystem) OpenDir(name string, context *Context) (stream []DirEntry, status Status) { func (fs *DefaultFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
func (fs *DefaultFileSystem) OnMount(nodeFs *PathNodeFs) { func (fs *DefaultFileSystem) OnMount(nodeFs *PathNodeFs) {
...@@ -85,22 +90,22 @@ func (fs *DefaultFileSystem) OnMount(nodeFs *PathNodeFs) { ...@@ -85,22 +90,22 @@ func (fs *DefaultFileSystem) OnMount(nodeFs *PathNodeFs) {
func (fs *DefaultFileSystem) OnUnmount() { func (fs *DefaultFileSystem) OnUnmount() {
} }
func (fs *DefaultFileSystem) Access(name string, mode uint32, context *Context) (code Status) { func (fs *DefaultFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Create(name string, flags uint32, mode uint32, context *Context) (file File, code Status) { func (fs *DefaultFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
func (fs *DefaultFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *Context) (code Status) { func (fs *DefaultFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (fs *DefaultFileSystem) String() string { func (fs *DefaultFileSystem) String() string {
return "DefaultFileSystem" return "DefaultFileSystem"
} }
func (fs *DefaultFileSystem) StatFs(name string) *StatfsOut { func (fs *DefaultFileSystem) StatFs(name string) *fuse.StatfsOut {
return nil return nil
} }
package pathfs
import (
"sync"
"time"
"github.com/hanwen/go-fuse/fuse"
)
// This is a wrapper that makes a FileSystem threadsafe by
// trivially locking all operations. For improved performance, you
// should probably invent do your own locking inside the file system.
type LockingFileSystem struct {
// Should be public so people reusing can access the wrapped
// FS.
FS FileSystem
lock sync.Mutex
}
var _ = ((FileSystem)((*LockingFileSystem)(nil)))
func NewLockingFileSystem(pfs FileSystem) *LockingFileSystem {
l := new(LockingFileSystem)
l.FS = pfs
return l
}
func (fs *LockingFileSystem) String() string {
defer fs.locked()()
return fs.FS.String()
}
func (fs *LockingFileSystem) StatFs(name string) *fuse.StatfsOut {
defer fs.locked()()
return fs.FS.StatFs(name)
}
func (fs *LockingFileSystem) locked() func() {
fs.lock.Lock()
return func() { fs.lock.Unlock() }
}
func (fs *LockingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
defer fs.locked()()
return fs.FS.GetAttr(name, context)
}
func (fs *LockingFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
defer fs.locked()()
return fs.FS.Readlink(name, context)
}
func (fs *LockingFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
defer fs.locked()()
return fs.FS.Mknod(name, mode, dev, context)
}
func (fs *LockingFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
defer fs.locked()()
return fs.FS.Mkdir(name, mode, context)
}
func (fs *LockingFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Unlink(name, context)
}
func (fs *LockingFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Rmdir(name, context)
}
func (fs *LockingFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Symlink(value, linkName, context)
}
func (fs *LockingFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Rename(oldName, newName, context)
}
func (fs *LockingFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Link(oldName, newName, context)
}
func (fs *LockingFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Chmod(name, mode, context)
}
func (fs *LockingFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Chown(name, uid, gid, context)
}
func (fs *LockingFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Truncate(name, offset, context)
}
func (fs *LockingFileSystem) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
return fs.FS.Open(name, flags, context)
}
func (fs *LockingFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
defer fs.locked()()
return fs.FS.OpenDir(name, context)
}
func (fs *LockingFileSystem) OnMount(nodeFs *PathNodeFs) {
defer fs.locked()()
fs.FS.OnMount(nodeFs)
}
func (fs *LockingFileSystem) OnUnmount() {
defer fs.locked()()
fs.FS.OnUnmount()
}
func (fs *LockingFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Access(name, mode, context)
}
func (fs *LockingFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
defer fs.locked()()
return fs.FS.Create(name, flags, mode, context)
}
func (fs *LockingFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) {
defer fs.locked()()
return fs.FS.Utimens(name, Atime, Mtime, context)
}
func (fs *LockingFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
defer fs.locked()()
return fs.FS.GetXAttr(name, attr, context)
}
func (fs *LockingFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
defer fs.locked()()
return fs.FS.SetXAttr(name, attr, data, flags, context)
}
func (fs *LockingFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
defer fs.locked()()
return fs.FS.ListXAttr(name, context)
}
func (fs *LockingFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
defer fs.locked()()
return fs.FS.RemoveXAttr(name, attr, context)
}
package fuse package pathfs
import ( import (
"fmt" "fmt"
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"path/filepath" "path/filepath"
"syscall" "syscall"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = fmt.Println var _ = fmt.Println
...@@ -32,7 +34,7 @@ func (fs *LoopbackFileSystem) GetPath(relPath string) string { ...@@ -32,7 +34,7 @@ func (fs *LoopbackFileSystem) GetPath(relPath string) string {
return filepath.Join(fs.Root, relPath) return filepath.Join(fs.Root, relPath)
} }
func (fs *LoopbackFileSystem) GetAttr(name string, context *Context) (a *Attr, code Status) { func (fs *LoopbackFileSystem) GetAttr(name string, context *fuse.Context) (a *fuse.Attr, code fuse.Status) {
fullPath := fs.GetPath(name) fullPath := fs.GetPath(name)
var err error = nil var err error = nil
st := syscall.Stat_t{} st := syscall.Stat_t{}
...@@ -45,32 +47,32 @@ func (fs *LoopbackFileSystem) GetAttr(name string, context *Context) (a *Attr, c ...@@ -45,32 +47,32 @@ func (fs *LoopbackFileSystem) GetAttr(name string, context *Context) (a *Attr, c
} }
if err != nil { if err != nil {
return nil, ToStatus(err) return nil, fuse.ToStatus(err)
} }
a = &Attr{} a = &fuse.Attr{}
a.FromStat(&st) a.FromStat(&st)
return a, OK return a, fuse.OK
} }
var _ = (FileSystem)((*LoopbackFileSystem)(nil)) var _ = (FileSystem)((*LoopbackFileSystem)(nil))
func (fs *LoopbackFileSystem) OpenDir(name string, context *Context) (stream []DirEntry, status Status) { func (fs *LoopbackFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.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(fs.GetPath(name)) f, err := os.Open(fs.GetPath(name))
if err != nil { if err != nil {
return nil, ToStatus(err) return nil, fuse.ToStatus(err)
} }
want := 500 want := 500
output := make([]DirEntry, 0, want) output := make([]fuse.DirEntry, 0, want)
for { for {
infos, err := f.Readdir(want) infos, err := f.Readdir(want)
for i := range infos { for i := range infos {
n := infos[i].Name() n := infos[i].Name()
d := DirEntry{ d := fuse.DirEntry{
Name: n, Name: n,
} }
if s := ToStatT(infos[i]); s != nil { if s := fuse.ToStatT(infos[i]); s != nil {
d.Mode = uint32(s.Mode) d.Mode = uint32(s.Mode)
} else { } else {
log.Printf("ReadDir entry %q for %q has no stat info", n, name) log.Printf("ReadDir entry %q for %q has no stat info", n, name)
...@@ -87,31 +89,31 @@ func (fs *LoopbackFileSystem) OpenDir(name string, context *Context) (stream []D ...@@ -87,31 +89,31 @@ func (fs *LoopbackFileSystem) OpenDir(name string, context *Context) (stream []D
} }
f.Close() f.Close()
return output, OK return output, fuse.OK
} }
func (fs *LoopbackFileSystem) Open(name string, flags uint32, context *Context) (fuseFile File, status Status) { func (fs *LoopbackFileSystem) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) {
f, err := os.OpenFile(fs.GetPath(name), int(flags), 0) f, err := os.OpenFile(fs.GetPath(name), int(flags), 0)
if err != nil { if err != nil {
return nil, ToStatus(err) return nil, fuse.ToStatus(err)
} }
return &LoopbackFile{File: f}, OK return &fuse.LoopbackFile{File: f}, fuse.OK
} }
func (fs *LoopbackFileSystem) Chmod(path string, mode uint32, context *Context) (code Status) { func (fs *LoopbackFileSystem) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
err := os.Chmod(fs.GetPath(path), os.FileMode(mode)) err := os.Chmod(fs.GetPath(path), os.FileMode(mode))
return ToStatus(err) return fuse.ToStatus(err)
} }
func (fs *LoopbackFileSystem) Chown(path string, uid uint32, gid uint32, context *Context) (code Status) { func (fs *LoopbackFileSystem) Chown(path string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
return ToStatus(os.Chown(fs.GetPath(path), int(uid), int(gid))) return fuse.ToStatus(os.Chown(fs.GetPath(path), int(uid), int(gid)))
} }
func (fs *LoopbackFileSystem) Truncate(path string, offset uint64, context *Context) (code Status) { func (fs *LoopbackFileSystem) Truncate(path string, offset uint64, context *fuse.Context) (code fuse.Status) {
return ToStatus(os.Truncate(fs.GetPath(path), int64(offset))) return fuse.ToStatus(os.Truncate(fs.GetPath(path), int64(offset)))
} }
func (fs *LoopbackFileSystem) Utimens(path string, Atime *time.Time, Mtime *time.Time, context *Context) (code Status) { func (fs *LoopbackFileSystem) Utimens(path string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) {
var a time.Time var a time.Time
if Atime != nil { if Atime != nil {
a = *Atime a = *Atime
...@@ -120,49 +122,49 @@ func (fs *LoopbackFileSystem) Utimens(path string, Atime *time.Time, Mtime *time ...@@ -120,49 +122,49 @@ func (fs *LoopbackFileSystem) Utimens(path string, Atime *time.Time, Mtime *time
if Mtime != nil { if Mtime != nil {
m = *Mtime m = *Mtime
} }
return ToStatus(os.Chtimes(fs.GetPath(path), a, m)) return fuse.ToStatus(os.Chtimes(fs.GetPath(path), a, m))
} }
func (fs *LoopbackFileSystem) Readlink(name string, context *Context) (out string, code Status) { func (fs *LoopbackFileSystem) Readlink(name string, context *fuse.Context) (out string, code fuse.Status) {
f, err := os.Readlink(fs.GetPath(name)) f, err := os.Readlink(fs.GetPath(name))
return f, ToStatus(err) return f, fuse.ToStatus(err)
} }
func (fs *LoopbackFileSystem) Mknod(name string, mode uint32, dev uint32, context *Context) (code Status) { func (fs *LoopbackFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (code fuse.Status) {
return ToStatus(syscall.Mknod(fs.GetPath(name), mode, int(dev))) return fuse.ToStatus(syscall.Mknod(fs.GetPath(name), mode, int(dev)))
} }
func (fs *LoopbackFileSystem) Mkdir(path string, mode uint32, context *Context) (code Status) { func (fs *LoopbackFileSystem) Mkdir(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
return ToStatus(os.Mkdir(fs.GetPath(path), os.FileMode(mode))) return fuse.ToStatus(os.Mkdir(fs.GetPath(path), os.FileMode(mode)))
} }
// Don't use os.Remove, it removes twice (unlink followed by rmdir). // Don't use os.Remove, it removes twice (unlink followed by rmdir).
func (fs *LoopbackFileSystem) Unlink(name string, context *Context) (code Status) { func (fs *LoopbackFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
return ToStatus(syscall.Unlink(fs.GetPath(name))) return fuse.ToStatus(syscall.Unlink(fs.GetPath(name)))
} }
func (fs *LoopbackFileSystem) Rmdir(name string, context *Context) (code Status) { func (fs *LoopbackFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
return ToStatus(syscall.Rmdir(fs.GetPath(name))) return fuse.ToStatus(syscall.Rmdir(fs.GetPath(name)))
} }
func (fs *LoopbackFileSystem) Symlink(pointedTo string, linkName string, context *Context) (code Status) { func (fs *LoopbackFileSystem) Symlink(pointedTo string, linkName string, context *fuse.Context) (code fuse.Status) {
return ToStatus(os.Symlink(pointedTo, fs.GetPath(linkName))) return fuse.ToStatus(os.Symlink(pointedTo, fs.GetPath(linkName)))
} }
func (fs *LoopbackFileSystem) Rename(oldPath string, newPath string, context *Context) (code Status) { func (fs *LoopbackFileSystem) Rename(oldPath string, newPath string, context *fuse.Context) (codee fuse.Status) {
err := os.Rename(fs.GetPath(oldPath), fs.GetPath(newPath)) err := os.Rename(fs.GetPath(oldPath), fs.GetPath(newPath))
return ToStatus(err) return fuse.ToStatus(err)
} }
func (fs *LoopbackFileSystem) Link(orig string, newName string, context *Context) (code Status) { func (fs *LoopbackFileSystem) Link(orig string, newName string, context *fuse.Context) (code fuse.Status) {
return ToStatus(os.Link(fs.GetPath(orig), fs.GetPath(newName))) return fuse.ToStatus(os.Link(fs.GetPath(orig), fs.GetPath(newName)))
} }
func (fs *LoopbackFileSystem) Access(name string, mode uint32, context *Context) (code Status) { func (fs *LoopbackFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
return ToStatus(syscall.Access(fs.GetPath(name), mode)) return fuse.ToStatus(syscall.Access(fs.GetPath(name), mode))
} }
func (fs *LoopbackFileSystem) Create(path string, flags uint32, mode uint32, context *Context) (fuseFile File, code Status) { func (fs *LoopbackFileSystem) Create(path string, flags uint32, mode uint32, context *fuse.Context) (fuseFile fuse.File, code fuse.Status) {
f, err := os.OpenFile(fs.GetPath(path), int(flags)|os.O_CREATE, os.FileMode(mode)) f, err := os.OpenFile(fs.GetPath(path), int(flags)|os.O_CREATE, os.FileMode(mode))
return &LoopbackFile{File: f}, ToStatus(err) return &fuse.LoopbackFile{File: f}, fuse.ToStatus(err)
} }
package fuse package pathfs
import ( import (
"fmt" "fmt"
"syscall" "syscall"
"github.com/hanwen/go-fuse/fuse"
) )
func (fs *LoopbackFileSystem) StatFs(name string) *StatfsOut { func (fs *LoopbackFileSystem) StatFs(name string) *fuse.StatfsOut {
s := syscall.Statfs_t{} s := syscall.Statfs_t{}
err := syscall.Statfs(fs.GetPath(name), &s) err := syscall.Statfs(fs.GetPath(name), &s)
if err == nil { if err == nil {
return &StatfsOut{ return &fuse.StatfsOut{
Blocks: s.Blocks, Blocks: s.Blocks,
Bsize: uint32(s.Bsize), Bsize: uint32(s.Bsize),
Bfree: s.Bfree, Bfree: s.Bfree,
...@@ -23,23 +25,23 @@ func (fs *LoopbackFileSystem) StatFs(name string) *StatfsOut { ...@@ -23,23 +25,23 @@ func (fs *LoopbackFileSystem) StatFs(name string) *StatfsOut {
return nil return nil
} }
func (fs *LoopbackFileSystem) ListXAttr(name string, context *Context) ([]string, Status) { func (fs *LoopbackFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
data, errNo := ListXAttr(fs.GetPath(name)) data, errNo := ListXAttr(fs.GetPath(name))
return data, Status(errNo) return data, fuse.Status(errNo)
} }
func (fs *LoopbackFileSystem) RemoveXAttr(name string, attr string, context *Context) Status { func (fs *LoopbackFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
return Status(Removexattr(fs.GetPath(name), attr)) return fuse.Status(Removexattr(fs.GetPath(name), attr))
} }
func (fs *LoopbackFileSystem) String() string { func (fs *LoopbackFileSystem) String() string {
return fmt.Sprintf("LoopbackFs(%s)", fs.Root) return fmt.Sprintf("LoopbackFs(%s)", fs.Root)
} }
func (fs *LoopbackFileSystem) GetXAttr(name string, attr string, context *Context) ([]byte, Status) { func (fs *LoopbackFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
data := make([]byte, 1024) data := make([]byte, 1024)
data, errNo := GetXAttr(fs.GetPath(name), attr, data) data, errNo := GetXAttr(fs.GetPath(name), attr, data)
return data, Status(errNo) return data, fuse.Status(errNo)
} }
package fuse package pathfs
import ( import (
"io/ioutil" "io/ioutil"
"os" "os"
"syscall" "syscall"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse"
) )
type ownerFs struct { type ownerFs struct {
...@@ -13,26 +15,26 @@ type ownerFs struct { ...@@ -13,26 +15,26 @@ type ownerFs struct {
const _RANDOM_OWNER = 31415265 const _RANDOM_OWNER = 31415265
func (fs *ownerFs) GetAttr(name string, context *Context) (*Attr, Status) { func (fs *ownerFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if name == "" { if name == "" {
return &Attr{ return &fuse.Attr{
Mode: S_IFDIR | 0755, Mode: fuse.S_IFDIR | 0755,
}, OK }, fuse.OK
} }
a := &Attr{ a := &fuse.Attr{
Mode: S_IFREG | 0644, Mode: fuse.S_IFREG | 0644,
} }
a.Uid = _RANDOM_OWNER a.Uid = _RANDOM_OWNER
a.Gid = _RANDOM_OWNER a.Gid = _RANDOM_OWNER
return a, OK return a, fuse.OK
} }
func setupOwnerTest(t *testing.T, opts *FileSystemOptions) (workdir string, cleanup func()) { func setupOwnerTest(t *testing.T, opts *fuse.FileSystemOptions) (workdir string, cleanup func()) {
wd, err := ioutil.TempDir("", "go-fuse-owner_test") wd, err := ioutil.TempDir("", "go-fuse-owner_test")
fs := &ownerFs{} fs := &ownerFs{}
nfs := NewPathNodeFs(fs, nil) nfs := NewPathNodeFs(fs, nil)
state, _, err := MountNodeFileSystem(wd, nfs, opts) state, _, err := fuse.MountNodeFileSystem(wd, nfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
...@@ -44,7 +46,7 @@ func setupOwnerTest(t *testing.T, opts *FileSystemOptions) (workdir string, clea ...@@ -44,7 +46,7 @@ func setupOwnerTest(t *testing.T, opts *FileSystemOptions) (workdir string, clea
} }
func TestOwnerDefault(t *testing.T) { func TestOwnerDefault(t *testing.T) {
wd, cleanup := setupOwnerTest(t, NewFileSystemOptions()) wd, cleanup := setupOwnerTest(t, fuse.NewFileSystemOptions())
defer cleanup() defer cleanup()
var stat syscall.Stat_t var stat syscall.Stat_t
...@@ -59,7 +61,7 @@ func TestOwnerDefault(t *testing.T) { ...@@ -59,7 +61,7 @@ func TestOwnerDefault(t *testing.T) {
} }
func TestOwnerRoot(t *testing.T) { func TestOwnerRoot(t *testing.T) {
wd, cleanup := setupOwnerTest(t, &FileSystemOptions{}) wd, cleanup := setupOwnerTest(t, &fuse.FileSystemOptions{})
defer cleanup() defer cleanup()
var st syscall.Stat_t var st syscall.Stat_t
...@@ -74,7 +76,7 @@ func TestOwnerRoot(t *testing.T) { ...@@ -74,7 +76,7 @@ func TestOwnerRoot(t *testing.T) {
} }
func TestOwnerOverride(t *testing.T) { func TestOwnerOverride(t *testing.T) {
wd, cleanup := setupOwnerTest(t, &FileSystemOptions{Owner: &Owner{42, 43}}) wd, cleanup := setupOwnerTest(t, &fuse.FileSystemOptions{Owner: &fuse.Owner{42, 43}})
defer cleanup() defer cleanup()
var stat syscall.Stat_t var stat syscall.Stat_t
......
package fuse package pathfs
import ( import (
"fmt" "fmt"
...@@ -7,6 +7,8 @@ import ( ...@@ -7,6 +7,8 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = log.Println var _ = log.Println
...@@ -30,7 +32,7 @@ type PathNodeFs struct { ...@@ -30,7 +32,7 @@ type PathNodeFs struct {
Debug bool Debug bool
fs FileSystem fs FileSystem
root *pathInode root *pathInode
connector *FileSystemConnector connector *fuse.FileSystemConnector
// protects clientInodeMap and pathInode.Parent pointers // protects clientInodeMap and pathInode.Parent pointers
pathLock sync.RWMutex pathLock sync.RWMutex
...@@ -42,14 +44,14 @@ type PathNodeFs struct { ...@@ -42,14 +44,14 @@ type PathNodeFs struct {
options *PathNodeFsOptions options *PathNodeFsOptions
} }
func (fs *PathNodeFs) Mount(path string, nodeFs NodeFileSystem, opts *FileSystemOptions) Status { func (fs *PathNodeFs) Mount(path string, nodeFs fuse.NodeFileSystem, opts *fuse.FileSystemOptions) fuse.Status {
dir, name := filepath.Split(path) dir, name := filepath.Split(path)
if dir != "" { if dir != "" {
dir = filepath.Clean(dir) dir = filepath.Clean(dir)
} }
parent := fs.LookupNode(dir) parent := fs.LookupNode(dir)
if parent == nil { if parent == nil {
return ENOENT return fuse.ENOENT
} }
return fs.connector.Mount(parent, name, nodeFs, opts) return fs.connector.Mount(parent, name, nodeFs, opts)
} }
...@@ -74,14 +76,14 @@ func (fs *PathNodeFs) RereadClientInodes() { ...@@ -74,14 +76,14 @@ func (fs *PathNodeFs) RereadClientInodes() {
fs.root.updateClientInodes() fs.root.updateClientInodes()
} }
func (fs *PathNodeFs) UnmountNode(node *Inode) Status { func (fs *PathNodeFs) UnmountNode(node *fuse.Inode) fuse.Status {
return fs.connector.Unmount(node) return fs.connector.Unmount(node)
} }
func (fs *PathNodeFs) Unmount(path string) Status { func (fs *PathNodeFs) Unmount(path string) fuse.Status {
node := fs.Node(path) node := fs.Node(path)
if node == nil { if node == nil {
return ENOENT return fuse.ENOENT
} }
return fs.connector.Unmount(node) return fs.connector.Unmount(node)
} }
...@@ -98,12 +100,12 @@ func (fs *PathNodeFs) String() string { ...@@ -98,12 +100,12 @@ func (fs *PathNodeFs) String() string {
return name return name
} }
func (fs *PathNodeFs) OnMount(conn *FileSystemConnector) { func (fs *PathNodeFs) OnMount(conn *fuse.FileSystemConnector) {
fs.connector = conn fs.connector = conn
fs.fs.OnMount(fs) fs.fs.OnMount(fs)
} }
func (fs *PathNodeFs) Node(name string) *Inode { func (fs *PathNodeFs) Node(name string) *fuse.Inode {
n, rest := fs.LastNode(name) n, rest := fs.LastNode(name)
if len(rest) > 0 { if len(rest) > 0 {
return nil return nil
...@@ -112,36 +114,36 @@ func (fs *PathNodeFs) Node(name string) *Inode { ...@@ -112,36 +114,36 @@ func (fs *PathNodeFs) Node(name string) *Inode {
} }
// Like node, but use Lookup to discover inodes we may not have yet. // Like node, but use Lookup to discover inodes we may not have yet.
func (fs *PathNodeFs) LookupNode(name string) *Inode { func (fs *PathNodeFs) LookupNode(name string) *fuse.Inode {
return fs.connector.LookupNode(fs.Root().Inode(), name) return fs.connector.LookupNode(fs.Root().Inode(), name)
} }
func (fs *PathNodeFs) Path(node *Inode) string { func (fs *PathNodeFs) Path(node *fuse.Inode) string {
pNode := node.FsNode().(*pathInode) pNode := node.FsNode().(*pathInode)
return pNode.GetPath() return pNode.GetPath()
} }
func (fs *PathNodeFs) LastNode(name string) (*Inode, []string) { func (fs *PathNodeFs) LastNode(name string) (*fuse.Inode, []string) {
return fs.connector.Node(fs.Root().Inode(), name) return fs.connector.Node(fs.Root().Inode(), name)
} }
func (fs *PathNodeFs) FileNotify(path string, off int64, length int64) Status { func (fs *PathNodeFs) FileNotify(path string, off int64, length int64) fuse.Status {
node, r := fs.connector.Node(fs.root.Inode(), path) node, r := fs.connector.Node(fs.root.Inode(), path)
if len(r) > 0 { if len(r) > 0 {
return ENOENT return fuse.ENOENT
} }
return fs.connector.FileNotify(node, off, length) return fs.connector.FileNotify(node, off, length)
} }
func (fs *PathNodeFs) EntryNotify(dir string, name string) Status { func (fs *PathNodeFs) EntryNotify(dir string, name string) fuse.Status {
node, rest := fs.connector.Node(fs.root.Inode(), dir) node, rest := fs.connector.Node(fs.root.Inode(), dir)
if len(rest) > 0 { if len(rest) > 0 {
return ENOENT return fuse.ENOENT
} }
return fs.connector.EntryNotify(node, name) return fs.connector.EntryNotify(node, name)
} }
func (fs *PathNodeFs) Notify(path string) Status { func (fs *PathNodeFs) Notify(path string) fuse.Status {
node, rest := fs.connector.Node(fs.root.Inode(), path) node, rest := fs.connector.Node(fs.root.Inode(), path)
if len(rest) > 0 { if len(rest) > 0 {
return fs.connector.EntryNotify(node, rest[0]) return fs.connector.EntryNotify(node, rest[0])
...@@ -149,7 +151,7 @@ func (fs *PathNodeFs) Notify(path string) Status { ...@@ -149,7 +151,7 @@ func (fs *PathNodeFs) Notify(path string) Status {
return fs.connector.FileNotify(node, 0, 0) return fs.connector.FileNotify(node, 0, 0)
} }
func (fs *PathNodeFs) AllFiles(name string, mask uint32) []WithFlags { func (fs *PathNodeFs) AllFiles(name string, mask uint32) []fuse.WithFlags {
n := fs.Node(name) n := fs.Node(name)
if n == nil { if n == nil {
return nil return nil
...@@ -175,7 +177,7 @@ func NewPathNodeFs(fs FileSystem, opts *PathNodeFsOptions) *PathNodeFs { ...@@ -175,7 +177,7 @@ func NewPathNodeFs(fs FileSystem, opts *PathNodeFsOptions) *PathNodeFs {
return pfs return pfs
} }
func (fs *PathNodeFs) Root() FsNode { func (fs *PathNodeFs) Root() fuse.FsNode {
return fs.root return fs.root
} }
...@@ -194,7 +196,7 @@ type pathInode struct { ...@@ -194,7 +196,7 @@ type pathInode struct {
// real filesystem. // real filesystem.
clientInode uint64 clientInode uint64
DefaultFsNode fuse.DefaultFsNode
} }
// Drop all known client inodes. Must have the treeLock. // Drop all known client inodes. Must have the treeLock.
...@@ -207,7 +209,7 @@ func (n *pathInode) forgetClientInodes() { ...@@ -207,7 +209,7 @@ func (n *pathInode) forgetClientInodes() {
// Reread all client nodes below this node. Must run outside the treeLock. // Reread all client nodes below this node. Must run outside the treeLock.
func (n *pathInode) updateClientInodes() { func (n *pathInode) updateClientInodes() {
n.GetAttr(&Attr{}, nil, nil) n.GetAttr(&fuse.Attr{}, nil, nil)
for _, ch := range n.Inode().FsChildren() { for _, ch := range n.Inode().FsChildren() {
ch.FsNode().(*pathInode).updateClientInodes() ch.FsNode().(*pathInode).updateClientInodes()
} }
...@@ -263,7 +265,8 @@ func (n *pathInode) GetPath() string { ...@@ -263,7 +265,8 @@ func (n *pathInode) GetPath() string {
path := string(pathBytes) path := string(pathBytes)
if n.pathFs.Debug { if n.pathFs.Debug {
log.Printf("Inode %d = %q (%s)", n.Inode().handled.handle, path, n.fs.String()) // TODO: print node ID.
log.Printf("Inode = %q (%s)", path, n.fs.String())
} }
return path return path
...@@ -353,48 +356,48 @@ func (n *pathInode) OnForget() { ...@@ -353,48 +356,48 @@ func (n *pathInode) OnForget() {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// FS operations // FS operations
func (n *pathInode) StatFs() *StatfsOut { func (n *pathInode) StatFs() *fuse.StatfsOut {
return n.fs.StatFs(n.GetPath()) return n.fs.StatFs(n.GetPath())
} }
func (n *pathInode) Readlink(c *Context) ([]byte, Status) { func (n *pathInode) Readlink(c *fuse.Context) ([]byte, fuse.Status) {
path := n.GetPath() path := n.GetPath()
val, err := n.fs.Readlink(path, c) val, err := n.fs.Readlink(path, c)
return []byte(val), err return []byte(val), err
} }
func (n *pathInode) Access(mode uint32, context *Context) (code Status) { func (n *pathInode) Access(mode uint32, context *fuse.Context) (code fuse.Status) {
p := n.GetPath() p := n.GetPath()
return n.fs.Access(p, mode, context) return n.fs.Access(p, mode, context)
} }
func (n *pathInode) GetXAttr(attribute string, context *Context) (data []byte, code Status) { func (n *pathInode) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
return n.fs.GetXAttr(n.GetPath(), attribute, context) return n.fs.GetXAttr(n.GetPath(), attribute, context)
} }
func (n *pathInode) RemoveXAttr(attr string, context *Context) Status { func (n *pathInode) RemoveXAttr(attr string, context *fuse.Context) fuse.Status {
p := n.GetPath() p := n.GetPath()
return n.fs.RemoveXAttr(p, attr, context) return n.fs.RemoveXAttr(p, attr, context)
} }
func (n *pathInode) SetXAttr(attr string, data []byte, flags int, context *Context) Status { func (n *pathInode) SetXAttr(attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
return n.fs.SetXAttr(n.GetPath(), attr, data, flags, context) return n.fs.SetXAttr(n.GetPath(), attr, data, flags, context)
} }
func (n *pathInode) ListXAttr(context *Context) (attrs []string, code Status) { func (n *pathInode) ListXAttr(context *fuse.Context) (attrs []string, code fuse.Status) {
return n.fs.ListXAttr(n.GetPath(), context) return n.fs.ListXAttr(n.GetPath(), context)
} }
func (n *pathInode) Flush(file File, openFlags uint32, context *Context) (code Status) { func (n *pathInode) Flush(file fuse.File, openFlags uint32, context *fuse.Context) (code fuse.Status) {
return file.Flush() return file.Flush()
} }
func (n *pathInode) OpenDir(context *Context) ([]DirEntry, Status) { func (n *pathInode) OpenDir(context *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
return n.fs.OpenDir(n.GetPath(), context) return n.fs.OpenDir(n.GetPath(), context)
} }
func (n *pathInode) Mknod(name string, mode uint32, dev uint32, context *Context) (newNode FsNode, code Status) { func (n *pathInode) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (newNode fuse.FsNode, code fuse.Status) {
fullPath := filepath.Join(n.GetPath(), name) fullPath := filepath.Join(n.GetPath(), name)
code = n.fs.Mknod(fullPath, mode, dev, context) code = n.fs.Mknod(fullPath, mode, dev, context)
if code.Ok() { if code.Ok() {
...@@ -405,7 +408,7 @@ func (n *pathInode) Mknod(name string, mode uint32, dev uint32, context *Context ...@@ -405,7 +408,7 @@ func (n *pathInode) Mknod(name string, mode uint32, dev uint32, context *Context
return return
} }
func (n *pathInode) Mkdir(name string, mode uint32, context *Context) (newNode FsNode, code Status) { func (n *pathInode) Mkdir(name string, mode uint32, context *fuse.Context) (newNode fuse.FsNode, code fuse.Status) {
fullPath := filepath.Join(n.GetPath(), name) fullPath := filepath.Join(n.GetPath(), name)
code = n.fs.Mkdir(fullPath, mode, context) code = n.fs.Mkdir(fullPath, mode, context)
if code.Ok() { if code.Ok() {
...@@ -416,7 +419,7 @@ func (n *pathInode) Mkdir(name string, mode uint32, context *Context) (newNode F ...@@ -416,7 +419,7 @@ func (n *pathInode) Mkdir(name string, mode uint32, context *Context) (newNode F
return return
} }
func (n *pathInode) Unlink(name string, context *Context) (code Status) { func (n *pathInode) Unlink(name string, context *fuse.Context) (code fuse.Status) {
code = n.fs.Unlink(filepath.Join(n.GetPath(), name), context) code = n.fs.Unlink(filepath.Join(n.GetPath(), name), context)
if code.Ok() { if code.Ok() {
n.rmChild(name) n.rmChild(name)
...@@ -424,7 +427,7 @@ func (n *pathInode) Unlink(name string, context *Context) (code Status) { ...@@ -424,7 +427,7 @@ func (n *pathInode) Unlink(name string, context *Context) (code Status) {
return code return code
} }
func (n *pathInode) Rmdir(name string, context *Context) (code Status) { func (n *pathInode) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
code = n.fs.Rmdir(filepath.Join(n.GetPath(), name), context) code = n.fs.Rmdir(filepath.Join(n.GetPath(), name), context)
if code.Ok() { if code.Ok() {
n.rmChild(name) n.rmChild(name)
...@@ -432,7 +435,7 @@ func (n *pathInode) Rmdir(name string, context *Context) (code Status) { ...@@ -432,7 +435,7 @@ func (n *pathInode) Rmdir(name string, context *Context) (code Status) {
return code return code
} }
func (n *pathInode) Symlink(name string, content string, context *Context) (newNode FsNode, code Status) { func (n *pathInode) Symlink(name string, content string, context *fuse.Context) (newNode fuse.FsNode, code fuse.Status) {
fullPath := filepath.Join(n.GetPath(), name) fullPath := filepath.Join(n.GetPath(), name)
code = n.fs.Symlink(content, fullPath, context) code = n.fs.Symlink(content, fullPath, context)
if code.Ok() { if code.Ok() {
...@@ -443,7 +446,7 @@ func (n *pathInode) Symlink(name string, content string, context *Context) (newN ...@@ -443,7 +446,7 @@ func (n *pathInode) Symlink(name string, content string, context *Context) (newN
return return
} }
func (n *pathInode) Rename(oldName string, newParent FsNode, newName string, context *Context) (code Status) { func (n *pathInode) Rename(oldName string, newParent fuse.FsNode, newName string, context *fuse.Context) (code fuse.Status) {
p := newParent.(*pathInode) p := newParent.(*pathInode)
oldPath := filepath.Join(n.GetPath(), oldName) oldPath := filepath.Join(n.GetPath(), oldName)
newPath := filepath.Join(p.GetPath(), newName) newPath := filepath.Join(p.GetPath(), newName)
...@@ -456,9 +459,9 @@ func (n *pathInode) Rename(oldName string, newParent FsNode, newName string, con ...@@ -456,9 +459,9 @@ func (n *pathInode) Rename(oldName string, newParent FsNode, newName string, con
return code return code
} }
func (n *pathInode) Link(name string, existingFsnode FsNode, context *Context) (newNode FsNode, code Status) { func (n *pathInode) Link(name string, existingFsnode fuse.FsNode, context *fuse.Context) (newNode fuse.FsNode, code fuse.Status) {
if !n.pathFs.options.ClientInodes { if !n.pathFs.options.ClientInodes {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
newPath := filepath.Join(n.GetPath(), name) newPath := filepath.Join(n.GetPath(), name)
...@@ -466,7 +469,7 @@ func (n *pathInode) Link(name string, existingFsnode FsNode, context *Context) ( ...@@ -466,7 +469,7 @@ func (n *pathInode) Link(name string, existingFsnode FsNode, context *Context) (
oldPath := existing.GetPath() oldPath := existing.GetPath()
code = n.fs.Link(oldPath, newPath, context) code = n.fs.Link(oldPath, newPath, context)
var a *Attr var a *fuse.Attr
if code.Ok() { if code.Ok() {
a, code = n.fs.GetAttr(newPath, context) a, code = n.fs.GetAttr(newPath, context)
} }
...@@ -485,7 +488,7 @@ func (n *pathInode) Link(name string, existingFsnode FsNode, context *Context) ( ...@@ -485,7 +488,7 @@ func (n *pathInode) Link(name string, existingFsnode FsNode, context *Context) (
return return
} }
func (n *pathInode) Create(name string, flags uint32, mode uint32, context *Context) (file File, newNode FsNode, code Status) { func (n *pathInode) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, newNode fuse.FsNode, code fuse.Status) {
fullPath := filepath.Join(n.GetPath(), name) fullPath := filepath.Join(n.GetPath(), name)
file, code = n.fs.Create(fullPath, flags, mode, context) file, code = n.fs.Create(fullPath, flags, mode, context)
if code.Ok() { if code.Ok() {
...@@ -505,10 +508,10 @@ func (n *pathInode) createChild(isDir bool) *pathInode { ...@@ -505,10 +508,10 @@ func (n *pathInode) createChild(isDir bool) *pathInode {
return i return i
} }
func (n *pathInode) Open(flags uint32, context *Context) (file File, code Status) { func (n *pathInode) Open(flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
file, code = n.fs.Open(n.GetPath(), flags, context) file, code = n.fs.Open(n.GetPath(), flags, context)
if n.pathFs.Debug { if n.pathFs.Debug {
file = &WithFlags{ file = &fuse.WithFlags{
File: file, File: file,
Description: n.GetPath(), Description: n.GetPath(),
} }
...@@ -516,7 +519,7 @@ func (n *pathInode) Open(flags uint32, context *Context) (file File, code Status ...@@ -516,7 +519,7 @@ func (n *pathInode) Open(flags uint32, context *Context) (file File, code Status
return return
} }
func (n *pathInode) Lookup(out *Attr, name string, context *Context) (node FsNode, code Status) { func (n *pathInode) Lookup(out *fuse.Attr, name string, context *fuse.Context) (node fuse.FsNode, code fuse.Status) {
fullPath := filepath.Join(n.GetPath(), name) fullPath := filepath.Join(n.GetPath(), name)
fi, code := n.fs.GetAttr(fullPath, context) fi, code := n.fs.GetAttr(fullPath, context)
if code.Ok() { if code.Ok() {
...@@ -527,7 +530,7 @@ func (n *pathInode) Lookup(out *Attr, name string, context *Context) (node FsNod ...@@ -527,7 +530,7 @@ func (n *pathInode) Lookup(out *Attr, name string, context *Context) (node FsNod
return node, code return node, code
} }
func (n *pathInode) findChild(fi *Attr, name string, fullPath string) (out *pathInode) { func (n *pathInode) findChild(fi *fuse.Attr, name string, fullPath string) (out *pathInode) {
if fi.Ino > 0 { if fi.Ino > 0 {
unlock := n.RLockTree() unlock := n.RLockTree()
v := n.pathFs.clientInodeMap[fi.Ino] v := n.pathFs.clientInodeMap[fi.Ino]
...@@ -550,18 +553,18 @@ func (n *pathInode) findChild(fi *Attr, name string, fullPath string) (out *path ...@@ -550,18 +553,18 @@ func (n *pathInode) findChild(fi *Attr, name string, fullPath string) (out *path
return out return out
} }
func (n *pathInode) GetAttr(out *Attr, file File, context *Context) (code Status) { func (n *pathInode) GetAttr(out *fuse.Attr, file fuse.File, context *fuse.Context) (code fuse.Status) {
var fi *Attr var fi *fuse.Attr
if file == nil { if file == nil {
// called on a deleted files. // called on a deleted files.
file = n.inode.AnyFile() file = n.Inode().AnyFile()
} }
if file != nil { if file != nil {
code = file.GetAttr(out) code = file.GetAttr(out)
} }
if file == nil || code == ENOSYS || code == EBADF { if file == nil || code == fuse.ENOSYS || code == fuse.EBADF {
fi, code = n.fs.GetAttr(n.GetPath(), context) fi, code = n.fs.GetAttr(n.GetPath(), context)
} }
...@@ -579,8 +582,8 @@ func (n *pathInode) GetAttr(out *Attr, file File, context *Context) (code Status ...@@ -579,8 +582,8 @@ func (n *pathInode) GetAttr(out *Attr, file File, context *Context) (code Status
return code return code
} }
func (n *pathInode) Chmod(file File, perms uint32, context *Context) (code Status) { func (n *pathInode) Chmod(file fuse.File, perms uint32, context *fuse.Context) (code fuse.Status) {
files := n.inode.Files(O_ANYWRITE) files := n.Inode().Files(fuse.O_ANYWRITE)
for _, f := range files { for _, f := range files {
// TODO - pass context // TODO - pass context
code = f.Chmod(perms) code = f.Chmod(perms)
...@@ -589,14 +592,14 @@ func (n *pathInode) Chmod(file File, perms uint32, context *Context) (code Statu ...@@ -589,14 +592,14 @@ func (n *pathInode) Chmod(file File, perms uint32, context *Context) (code Statu
} }
} }
if len(files) == 0 || code == ENOSYS || code == EBADF { if len(files) == 0 || code == fuse.ENOSYS || code == fuse.EBADF {
code = n.fs.Chmod(n.GetPath(), perms, context) code = n.fs.Chmod(n.GetPath(), perms, context)
} }
return code return code
} }
func (n *pathInode) Chown(file File, uid uint32, gid uint32, context *Context) (code Status) { func (n *pathInode) Chown(file fuse.File, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
files := n.inode.Files(O_ANYWRITE) files := n.Inode().Files(fuse.O_ANYWRITE)
for _, f := range files { for _, f := range files {
// TODO - pass context // TODO - pass context
code = f.Chown(uid, gid) code = f.Chown(uid, gid)
...@@ -604,15 +607,15 @@ func (n *pathInode) Chown(file File, uid uint32, gid uint32, context *Context) ( ...@@ -604,15 +607,15 @@ func (n *pathInode) Chown(file File, uid uint32, gid uint32, context *Context) (
return code return code
} }
} }
if len(files) == 0 || code == ENOSYS || code == EBADF { if len(files) == 0 || code == fuse.ENOSYS || code == fuse.EBADF {
// TODO - can we get just FATTR_GID but not FATTR_UID ? // TODO - can we get just FATTR_GID but not FATTR_UID ?
code = n.fs.Chown(n.GetPath(), uid, gid, context) code = n.fs.Chown(n.GetPath(), uid, gid, context)
} }
return code return code
} }
func (n *pathInode) Truncate(file File, size uint64, context *Context) (code Status) { func (n *pathInode) Truncate(file fuse.File, size uint64, context *fuse.Context) (code fuse.Status) {
files := n.inode.Files(O_ANYWRITE) files := n.Inode().Files(fuse.O_ANYWRITE)
for _, f := range files { for _, f := range files {
// TODO - pass context // TODO - pass context
code = f.Truncate(size) code = f.Truncate(size)
...@@ -620,14 +623,14 @@ func (n *pathInode) Truncate(file File, size uint64, context *Context) (code Sta ...@@ -620,14 +623,14 @@ func (n *pathInode) Truncate(file File, size uint64, context *Context) (code Sta
return code return code
} }
} }
if len(files) == 0 || code == ENOSYS || code == EBADF { if len(files) == 0 || code == fuse.ENOSYS || code == fuse.EBADF {
code = n.fs.Truncate(n.GetPath(), size, context) code = n.fs.Truncate(n.GetPath(), size, context)
} }
return code return code
} }
func (n *pathInode) Utimens(file File, atime *time.Time, mtime *time.Time, context *Context) (code Status) { func (n *pathInode) Utimens(file fuse.File, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status) {
files := n.inode.Files(O_ANYWRITE) files := n.Inode().Files(fuse.O_ANYWRITE)
for _, f := range files { for _, f := range files {
// TODO - pass context // TODO - pass context
code = f.Utimens(atime, mtime) code = f.Utimens(atime, mtime)
...@@ -635,13 +638,13 @@ func (n *pathInode) Utimens(file File, atime *time.Time, mtime *time.Time, conte ...@@ -635,13 +638,13 @@ func (n *pathInode) Utimens(file File, atime *time.Time, mtime *time.Time, conte
return code return code
} }
} }
if len(files) == 0 || code == ENOSYS || code == EBADF { if len(files) == 0 || code == fuse.ENOSYS || code == fuse.EBADF {
code = n.fs.Utimens(n.GetPath(), atime, mtime, context) code = n.fs.Utimens(n.GetPath(), atime, mtime, context)
} }
return code return code
} }
func (n *pathInode) Fallocate(file File, off uint64, size uint64, mode uint32, context *Context) (code Status) { func (n *pathInode) Fallocate(file fuse.File, off uint64, size uint64, mode uint32, context *fuse.Context) (code fuse.Status) {
if file != nil { if file != nil {
code = file.Allocate(off, size, mode) code = file.Allocate(off, size, mode)
if code.Ok() { if code.Ok() {
...@@ -649,7 +652,7 @@ func (n *pathInode) Fallocate(file File, off uint64, size uint64, mode uint32, c ...@@ -649,7 +652,7 @@ func (n *pathInode) Fallocate(file File, off uint64, size uint64, mode uint32, c
} }
} }
files := n.inode.Files(O_ANYWRITE) files := n.Inode().Files(fuse.O_ANYWRITE)
for _, f := range files { for _, f := range files {
// TODO - pass context // TODO - pass context
code = f.Allocate(off, size, mode) code = f.Allocate(off, size, mode)
......
package fuse package pathfs
import ( import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
// PrefixFileSystem adds a path prefix to incoming calls. // PrefixFileSystem adds a path prefix to incoming calls.
...@@ -16,59 +18,59 @@ func (fs *PrefixFileSystem) prefixed(n string) string { ...@@ -16,59 +18,59 @@ func (fs *PrefixFileSystem) prefixed(n string) string {
return filepath.Join(fs.Prefix, n) return filepath.Join(fs.Prefix, n)
} }
func (fs *PrefixFileSystem) GetAttr(name string, context *Context) (*Attr, Status) { func (fs *PrefixFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
return fs.FileSystem.GetAttr(fs.prefixed(name), context) return fs.FileSystem.GetAttr(fs.prefixed(name), context)
} }
func (fs *PrefixFileSystem) Readlink(name string, context *Context) (string, Status) { func (fs *PrefixFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
return fs.FileSystem.Readlink(fs.prefixed(name), context) return fs.FileSystem.Readlink(fs.prefixed(name), context)
} }
func (fs *PrefixFileSystem) Mknod(name string, mode uint32, dev uint32, context *Context) Status { func (fs *PrefixFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
return fs.FileSystem.Mknod(fs.prefixed(name), mode, dev, context) return fs.FileSystem.Mknod(fs.prefixed(name), mode, dev, context)
} }
func (fs *PrefixFileSystem) Mkdir(name string, mode uint32, context *Context) Status { func (fs *PrefixFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
return fs.FileSystem.Mkdir(fs.prefixed(name), mode, context) return fs.FileSystem.Mkdir(fs.prefixed(name), mode, context)
} }
func (fs *PrefixFileSystem) Unlink(name string, context *Context) (code Status) { func (fs *PrefixFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Unlink(fs.prefixed(name), context) return fs.FileSystem.Unlink(fs.prefixed(name), context)
} }
func (fs *PrefixFileSystem) Rmdir(name string, context *Context) (code Status) { func (fs *PrefixFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Rmdir(fs.prefixed(name), context) return fs.FileSystem.Rmdir(fs.prefixed(name), context)
} }
func (fs *PrefixFileSystem) Symlink(value string, linkName string, context *Context) (code Status) { func (fs *PrefixFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Symlink(value, fs.prefixed(linkName), context) return fs.FileSystem.Symlink(value, fs.prefixed(linkName), context)
} }
func (fs *PrefixFileSystem) Rename(oldName string, newName string, context *Context) (code Status) { func (fs *PrefixFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Rename(fs.prefixed(oldName), fs.prefixed(newName), context) return fs.FileSystem.Rename(fs.prefixed(oldName), fs.prefixed(newName), context)
} }
func (fs *PrefixFileSystem) Link(oldName string, newName string, context *Context) (code Status) { func (fs *PrefixFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Link(fs.prefixed(oldName), fs.prefixed(newName), context) return fs.FileSystem.Link(fs.prefixed(oldName), fs.prefixed(newName), context)
} }
func (fs *PrefixFileSystem) Chmod(name string, mode uint32, context *Context) (code Status) { func (fs *PrefixFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Chmod(fs.prefixed(name), mode, context) return fs.FileSystem.Chmod(fs.prefixed(name), mode, context)
} }
func (fs *PrefixFileSystem) Chown(name string, uid uint32, gid uint32, context *Context) (code Status) { func (fs *PrefixFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Chown(fs.prefixed(name), uid, gid, context) return fs.FileSystem.Chown(fs.prefixed(name), uid, gid, context)
} }
func (fs *PrefixFileSystem) Truncate(name string, offset uint64, context *Context) (code Status) { func (fs *PrefixFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Truncate(fs.prefixed(name), offset, context) return fs.FileSystem.Truncate(fs.prefixed(name), offset, context)
} }
func (fs *PrefixFileSystem) Open(name string, flags uint32, context *Context) (file File, code Status) { func (fs *PrefixFileSystem) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
return fs.FileSystem.Open(fs.prefixed(name), flags, context) return fs.FileSystem.Open(fs.prefixed(name), flags, context)
} }
func (fs *PrefixFileSystem) OpenDir(name string, context *Context) (stream []DirEntry, status Status) { func (fs *PrefixFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
return fs.FileSystem.OpenDir(fs.prefixed(name), context) return fs.FileSystem.OpenDir(fs.prefixed(name), context)
} }
...@@ -80,31 +82,31 @@ func (fs *PrefixFileSystem) OnUnmount() { ...@@ -80,31 +82,31 @@ func (fs *PrefixFileSystem) OnUnmount() {
fs.FileSystem.OnUnmount() fs.FileSystem.OnUnmount()
} }
func (fs *PrefixFileSystem) Access(name string, mode uint32, context *Context) (code Status) { func (fs *PrefixFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Access(fs.prefixed(name), mode, context) return fs.FileSystem.Access(fs.prefixed(name), mode, context)
} }
func (fs *PrefixFileSystem) Create(name string, flags uint32, mode uint32, context *Context) (file File, code Status) { func (fs *PrefixFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
return fs.FileSystem.Create(fs.prefixed(name), flags, mode, context) return fs.FileSystem.Create(fs.prefixed(name), flags, mode, context)
} }
func (fs *PrefixFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *Context) (code Status) { func (fs *PrefixFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Utimens(fs.prefixed(name), Atime, Mtime, context) return fs.FileSystem.Utimens(fs.prefixed(name), Atime, Mtime, context)
} }
func (fs *PrefixFileSystem) GetXAttr(name string, attr string, context *Context) ([]byte, Status) { func (fs *PrefixFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
return fs.FileSystem.GetXAttr(fs.prefixed(name), attr, context) return fs.FileSystem.GetXAttr(fs.prefixed(name), attr, context)
} }
func (fs *PrefixFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *Context) Status { func (fs *PrefixFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
return fs.FileSystem.SetXAttr(fs.prefixed(name), attr, data, flags, context) return fs.FileSystem.SetXAttr(fs.prefixed(name), attr, data, flags, context)
} }
func (fs *PrefixFileSystem) ListXAttr(name string, context *Context) ([]string, Status) { func (fs *PrefixFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
return fs.FileSystem.ListXAttr(fs.prefixed(name), context) return fs.FileSystem.ListXAttr(fs.prefixed(name), context)
} }
func (fs *PrefixFileSystem) RemoveXAttr(name string, attr string, context *Context) Status { func (fs *PrefixFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
return fs.FileSystem.RemoveXAttr(fs.prefixed(name), attr, context) return fs.FileSystem.RemoveXAttr(fs.prefixed(name), attr, context)
} }
......
package fuse package pathfs
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
// This is a wrapper that only exposes read-only operations. // This is a wrapper that only exposes read-only operations.
...@@ -12,63 +14,63 @@ type ReadonlyFileSystem struct { ...@@ -12,63 +14,63 @@ type ReadonlyFileSystem struct {
var _ = (FileSystem)((*ReadonlyFileSystem)(nil)) var _ = (FileSystem)((*ReadonlyFileSystem)(nil))
func (fs *ReadonlyFileSystem) GetAttr(name string, context *Context) (*Attr, Status) { func (fs *ReadonlyFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
return fs.FileSystem.GetAttr(name, context) return fs.FileSystem.GetAttr(name, context)
} }
func (fs *ReadonlyFileSystem) Readlink(name string, context *Context) (string, Status) { func (fs *ReadonlyFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
return fs.FileSystem.Readlink(name, context) return fs.FileSystem.Readlink(name, context)
} }
func (fs *ReadonlyFileSystem) Mknod(name string, mode uint32, dev uint32, context *Context) Status { func (fs *ReadonlyFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Mkdir(name string, mode uint32, context *Context) Status { func (fs *ReadonlyFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Unlink(name string, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Rmdir(name string, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Symlink(value string, linkName string, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Rename(oldName string, newName string, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Link(oldName string, newName string, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Chmod(name string, mode uint32, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Chown(name string, uid uint32, gid uint32, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Truncate(name string, offset uint64, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Open(name string, flags uint32, context *Context) (file File, code Status) { func (fs *ReadonlyFileSystem) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
if flags&O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
return nil, EPERM return nil, fuse.EPERM
} }
file, code = fs.FileSystem.Open(name, flags, context) file, code = fs.FileSystem.Open(name, flags, context)
return &ReadOnlyFile{file}, code return &fuse.ReadOnlyFile{file}, code
} }
func (fs *ReadonlyFileSystem) OpenDir(name string, context *Context) (stream []DirEntry, status Status) { func (fs *ReadonlyFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
return fs.FileSystem.OpenDir(name, context) return fs.FileSystem.OpenDir(name, context)
} }
...@@ -84,30 +86,30 @@ func (fs *ReadonlyFileSystem) String() string { ...@@ -84,30 +86,30 @@ func (fs *ReadonlyFileSystem) String() string {
return fmt.Sprintf("ReadonlyFileSystem(%v)", fs.FileSystem) return fmt.Sprintf("ReadonlyFileSystem(%v)", fs.FileSystem)
} }
func (fs *ReadonlyFileSystem) Access(name string, mode uint32, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
return fs.FileSystem.Access(name, mode, context) return fs.FileSystem.Access(name, mode, context)
} }
func (fs *ReadonlyFileSystem) Create(name string, flags uint32, mode uint32, context *Context) (file File, code Status) { func (fs *ReadonlyFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
return nil, EPERM return nil, fuse.EPERM
} }
func (fs *ReadonlyFileSystem) Utimens(name string, atime *time.Time, ctime *time.Time, context *Context) (code Status) { func (fs *ReadonlyFileSystem) Utimens(name string, atime *time.Time, ctime *time.Time, context *fuse.Context) (code fuse.Status) {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) GetXAttr(name string, attr string, context *Context) ([]byte, Status) { func (fs *ReadonlyFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
return fs.FileSystem.GetXAttr(name, attr, context) return fs.FileSystem.GetXAttr(name, attr, context)
} }
func (fs *ReadonlyFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *Context) Status { func (fs *ReadonlyFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
return EPERM return fuse.EPERM
} }
func (fs *ReadonlyFileSystem) ListXAttr(name string, context *Context) ([]string, Status) { func (fs *ReadonlyFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
return fs.FileSystem.ListXAttr(name, context) return fs.FileSystem.ListXAttr(name, context)
} }
func (fs *ReadonlyFileSystem) RemoveXAttr(name string, attr string, context *Context) Status { func (fs *ReadonlyFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
return EPERM return fuse.EPERM
} }
package pathfs
import (
"bytes"
"syscall"
"unsafe"
)
func getxattr(path string, attr string, dest []byte) (sz int, errno int) {
pathBs := syscall.StringBytePtr(path)
attrBs := syscall.StringBytePtr(attr)
size, _, errNo := syscall.Syscall6(
syscall.SYS_GETXATTR,
uintptr(unsafe.Pointer(pathBs)),
uintptr(unsafe.Pointer(attrBs)),
uintptr(unsafe.Pointer(&dest[0])),
uintptr(len(dest)),
0, 0)
return int(size), int(errNo)
}
func GetXAttr(path string, attr string, dest []byte) (value []byte, errno int) {
sz, errno := getxattr(path, attr, dest)
for sz > cap(dest) && errno == 0 {
dest = make([]byte, sz)
sz, errno = getxattr(path, attr, dest)
}
if errno != 0 {
return nil, errno
}
return dest[:sz], errno
}
func listxattr(path string, dest []byte) (sz int, errno int) {
pathbs := syscall.StringBytePtr(path)
var destPointer unsafe.Pointer
if len(dest) > 0 {
destPointer = unsafe.Pointer(&dest[0])
}
size, _, errNo := syscall.Syscall(
syscall.SYS_LISTXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(destPointer),
uintptr(len(dest)))
return int(size), int(errNo)
}
func ListXAttr(path string) (attributes []string, errno int) {
dest := make([]byte, 0)
sz, errno := listxattr(path, dest)
if errno != 0 {
return nil, errno
}
for sz > cap(dest) && errno == 0 {
dest = make([]byte, sz)
sz, errno = listxattr(path, dest)
}
// -1 to drop the final empty slice.
dest = dest[:sz-1]
attributesBytes := bytes.Split(dest, []byte{0})
attributes = make([]string, len(attributesBytes))
for i, v := range attributesBytes {
attributes[i] = string(v)
}
return attributes, errno
}
func Setxattr(path string, attr string, data []byte, flags int) (errno int) {
pathbs := syscall.StringBytePtr(path)
attrbs := syscall.StringBytePtr(attr)
_, _, errNo := syscall.Syscall6(
syscall.SYS_SETXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(unsafe.Pointer(attrbs)),
uintptr(unsafe.Pointer(&data[0])),
uintptr(len(data)),
uintptr(flags), 0)
return int(errNo)
}
func Removexattr(path string, attr string) (errno int) {
pathbs := syscall.StringBytePtr(path)
attrbs := syscall.StringBytePtr(attr)
_, _, errNo := syscall.Syscall(
syscall.SYS_REMOVEXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(unsafe.Pointer(attrbs)), 0)
return int(errNo)
}
package fuse package pathfs
import ( import (
"bytes" "bytes"
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"path/filepath" "path/filepath"
"syscall" "syscall"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = log.Print var _ = log.Print
...@@ -35,64 +37,64 @@ func NewXAttrFs(nm string, m map[string][]byte) *XAttrTestFs { ...@@ -35,64 +37,64 @@ func NewXAttrFs(nm string, m map[string][]byte) *XAttrTestFs {
return x return x
} }
func (fs *XAttrTestFs) GetAttr(name string, context *Context) (*Attr, Status) { func (fs *XAttrTestFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
a := &Attr{} a := &fuse.Attr{}
if name == "" || name == "/" { if name == "" || name == "/" {
a.Mode = S_IFDIR | 0700 a.Mode = fuse.S_IFDIR | 0700
return a, OK return a, fuse.OK
} }
if name == fs.filename { if name == fs.filename {
a.Mode = S_IFREG | 0600 a.Mode = fuse.S_IFREG | 0600
return a, OK return a, fuse.OK
} }
return nil, ENOENT return nil, fuse.ENOENT
} }
func (fs *XAttrTestFs) SetXAttr(name string, attr string, data []byte, flags int, context *Context) Status { func (fs *XAttrTestFs) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
fs.tester.Log("SetXAttr", name, attr, string(data), flags) fs.tester.Log("SetXAttr", name, attr, string(data), flags)
if name != fs.filename { if name != fs.filename {
return ENOENT return fuse.ENOENT
} }
dest := make([]byte, len(data)) dest := make([]byte, len(data))
copy(dest, data) copy(dest, data)
fs.attrs[attr] = dest fs.attrs[attr] = dest
return OK return fuse.OK
} }
func (fs *XAttrTestFs) GetXAttr(name string, attr string, context *Context) ([]byte, Status) { func (fs *XAttrTestFs) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
if name != fs.filename { if name != fs.filename {
return nil, ENOENT return nil, fuse.ENOENT
} }
v, ok := fs.attrs[attr] v, ok := fs.attrs[attr]
if !ok { if !ok {
return nil, ENODATA return nil, fuse.ENODATA
} }
fs.tester.Log("GetXAttr", string(v)) fs.tester.Log("GetXAttr", string(v))
return v, OK return v, fuse.OK
} }
func (fs *XAttrTestFs) ListXAttr(name string, context *Context) (data []string, code Status) { func (fs *XAttrTestFs) ListXAttr(name string, context *fuse.Context) (data []string, code fuse.Status) {
if name != fs.filename { if name != fs.filename {
return nil, ENOENT return nil, fuse.ENOENT
} }
for k := range fs.attrs { for k := range fs.attrs {
data = append(data, k) data = append(data, k)
} }
return data, OK return data, fuse.OK
} }
func (fs *XAttrTestFs) RemoveXAttr(name string, attr string, context *Context) Status { func (fs *XAttrTestFs) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
if name != fs.filename { if name != fs.filename {
return ENOENT return fuse.ENOENT
} }
_, ok := fs.attrs[attr] _, ok := fs.attrs[attr]
fs.tester.Log("RemoveXAttr", name, attr, ok) fs.tester.Log("RemoveXAttr", name, attr, ok)
if !ok { if !ok {
return ENODATA return fuse.ENODATA
} }
delete(fs.attrs, attr) delete(fs.attrs, attr)
return OK return fuse.OK
} }
func readXAttr(p, a string) (val []byte, errno int) { func readXAttr(p, a string) (val []byte, errno int) {
...@@ -109,11 +111,11 @@ func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func()) ...@@ -109,11 +111,11 @@ func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func())
} }
nfs := NewPathNodeFs(xfs, nil) nfs := NewPathNodeFs(xfs, nil)
state, _, err := MountNodeFileSystem(mountPoint, nfs, nil) state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, nil)
if err != nil { if err != nil {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
state.Debug = VerboseTest() state.Debug = fuse.VerboseTest()
go state.Loop() go state.Loop()
return mountPoint, func() { return mountPoint, func() {
...@@ -180,7 +182,7 @@ func TestXAttrRead(t *testing.T) { ...@@ -180,7 +182,7 @@ func TestXAttrRead(t *testing.T) {
Removexattr(mounted, "third") Removexattr(mounted, "third")
val, errno = readXAttr(mounted, "third") val, errno = readXAttr(mounted, "third")
if errno != int(ENODATA) { if errno != int(fuse.ENODATA) {
t.Error("Data not removed?", errno, val) t.Error("Data not removed?", errno, val)
} }
} }
package fuse
import (
"fmt"
"io/ioutil"
"log"
"os"
"regexp"
"sync"
"testing"
"time"
)
var _ = log.Println
// This test checks that highly concurrent loads don't use a lot of
// memory if it is not needed: The input buffer needs to accomodata
// the max write size, but it is only really needed when we are
// processing writes.
type DelayFs struct {
DefaultFileSystem
fileRegex *regexp.Regexp
dirRegex *regexp.Regexp
}
func (d *DelayFs) GetAttr(name string, c *Context) (*Attr, Status) {
if name == "" || d.dirRegex.MatchString(name) {
return &Attr{Mode: S_IFDIR | 0755}, OK
}
if d.fileRegex.MatchString(name) {
time.Sleep(time.Second)
return &Attr{Mode: S_IFREG | 0644}, OK
}
return nil, ENOENT
}
func TestMemoryPressure(t *testing.T) {
fs := &DelayFs{
fileRegex: regexp.MustCompile("^dir[0-9]*/file[0-9]*$"),
dirRegex: regexp.MustCompile("^dir[0-9]*$"),
}
dir, err := ioutil.TempDir("", "go-fuse-pressure_test")
if err != nil {
t.Fatalf("TempDir failed: %v", err)
}
defer os.RemoveAll(dir)
nfs := NewPathNodeFs(fs, nil)
o := &FileSystemOptions{PortableInodes: true}
conn := NewFileSystemConnector(nfs, o)
state := NewMountState(conn)
bufs := NewBufferPool()
err = state.Mount(dir, &MountOptions{Buffers: bufs})
if err != nil {
t.Fatalf("mount failed: %v", err)
}
state.Debug = VerboseTest()
go state.Loop()
defer state.Unmount()
// Wait for FS to get ready.
os.Lstat(dir)
var wg sync.WaitGroup
for i := 0; i < 10*_MAX_READERS; i++ {
wg.Add(1)
go func(x int) {
fn := fmt.Sprintf("%s/dir%d/file%d", dir, x, x)
_, err := os.Lstat(fn)
if err != nil {
t.Errorf("parallel stat %q: %v", fn, err)
}
wg.Done()
}(i)
}
time.Sleep(100 * time.Millisecond)
state.reqMu.Lock()
bufs.lock.Lock()
created := bufs.createdBuffers + state.outstandingReadBufs
bufs.lock.Unlock()
state.reqMu.Unlock()
t.Logf("Have %d read bufs", state.outstandingReadBufs)
// +1 due to batch forget?
if created > _MAX_READERS+1 {
t.Errorf("created %d buffers, max reader %d", created, _MAX_READERS)
}
wg.Wait()
}
...@@ -125,4 +125,3 @@ func Removexattr(path string, attr string) (errno int) { ...@@ -125,4 +125,3 @@ func Removexattr(path string, attr string) (errno int) {
uintptr(unsafe.Pointer(attrbs)), 0) uintptr(unsafe.Pointer(attrbs)), 0)
return int(errNo) return int(errNo)
} }
package fuse package fuse
import ( import (
"bytes"
"os" "os"
"syscall" "syscall"
"unsafe" "unsafe"
...@@ -37,96 +36,6 @@ func Writev(fd int, packet [][]byte) (n int, err error) { ...@@ -37,96 +36,6 @@ func Writev(fd int, packet [][]byte) (n int, err error) {
return n, err return n, err
} }
func getxattr(path string, attr string, dest []byte) (sz int, errno int) {
pathBs := syscall.StringBytePtr(path)
attrBs := syscall.StringBytePtr(attr)
size, _, errNo := syscall.Syscall6(
syscall.SYS_GETXATTR,
uintptr(unsafe.Pointer(pathBs)),
uintptr(unsafe.Pointer(attrBs)),
uintptr(unsafe.Pointer(&dest[0])),
uintptr(len(dest)),
0, 0)
return int(size), int(errNo)
}
func GetXAttr(path string, attr string, dest []byte) (value []byte, errno int) {
sz, errno := getxattr(path, attr, dest)
for sz > cap(dest) && errno == 0 {
dest = make([]byte, sz)
sz, errno = getxattr(path, attr, dest)
}
if errno != 0 {
return nil, errno
}
return dest[:sz], errno
}
func listxattr(path string, dest []byte) (sz int, errno int) {
pathbs := syscall.StringBytePtr(path)
var destPointer unsafe.Pointer
if len(dest) > 0 {
destPointer = unsafe.Pointer(&dest[0])
}
size, _, errNo := syscall.Syscall(
syscall.SYS_LISTXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(destPointer),
uintptr(len(dest)))
return int(size), int(errNo)
}
func ListXAttr(path string) (attributes []string, errno int) {
dest := make([]byte, 0)
sz, errno := listxattr(path, dest)
if errno != 0 {
return nil, errno
}
for sz > cap(dest) && errno == 0 {
dest = make([]byte, sz)
sz, errno = listxattr(path, dest)
}
// -1 to drop the final empty slice.
dest = dest[:sz-1]
attributesBytes := bytes.Split(dest, []byte{0})
attributes = make([]string, len(attributesBytes))
for i, v := range attributesBytes {
attributes[i] = string(v)
}
return attributes, errno
}
func Setxattr(path string, attr string, data []byte, flags int) (errno int) {
pathbs := syscall.StringBytePtr(path)
attrbs := syscall.StringBytePtr(attr)
_, _, errNo := syscall.Syscall6(
syscall.SYS_SETXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(unsafe.Pointer(attrbs)),
uintptr(unsafe.Pointer(&data[0])),
uintptr(len(data)),
uintptr(flags), 0)
return int(errNo)
}
func Removexattr(path string, attr string) (errno int) {
pathbs := syscall.StringBytePtr(path)
attrbs := syscall.StringBytePtr(attr)
_, _, errNo := syscall.Syscall(
syscall.SYS_REMOVEXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(unsafe.Pointer(attrbs)), 0)
return int(errNo)
}
const AT_FDCWD = -100 const AT_FDCWD = -100
func Linkat(fd1 int, n1 string, fd2 int, n2 string) int { func Linkat(fd1 int, n1 string, fd2 int, n2 string) int {
......
package fuse package test
import ( import (
"bytes" "bytes"
"github.com/hanwen/go-fuse/raw"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"sync" "sync"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw"
) )
var _ = log.Println var _ = log.Println
type cacheFs struct { type cacheFs struct {
*LoopbackFileSystem *pathfs.LoopbackFileSystem
} }
func (fs *cacheFs) Open(name string, flags uint32, context *Context) (fuseFile File, status Status) { func (fs *cacheFs) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) {
f, c := fs.LoopbackFileSystem.Open(name, flags, context) f, c := fs.LoopbackFileSystem.Open(name, flags, context)
if !c.Ok() { if !c.Ok() {
return f, c return f, c
} }
return &WithFlags{ return &fuse.WithFlags{
File: f, File: f,
FuseFlags: raw.FOPEN_KEEP_CACHE, FuseFlags: raw.FOPEN_KEEP_CACHE,
}, c }, c
} }
func setupCacheTest(t *testing.T) (string, *PathNodeFs, func()) { func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
dir, err := ioutil.TempDir("", "go-fuse-cachetest") dir, err := ioutil.TempDir("", "go-fuse-cachetest")
if err != nil { if err != nil {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
...@@ -37,16 +40,16 @@ func setupCacheTest(t *testing.T) (string, *PathNodeFs, func()) { ...@@ -37,16 +40,16 @@ func setupCacheTest(t *testing.T) (string, *PathNodeFs, func()) {
os.Mkdir(dir+"/orig", 0755) os.Mkdir(dir+"/orig", 0755)
fs := &cacheFs{ fs := &cacheFs{
LoopbackFileSystem: NewLoopbackFileSystem(dir + "/orig"), LoopbackFileSystem: pathfs.NewLoopbackFileSystem(dir + "/orig"),
} }
pfs := NewPathNodeFs(fs, nil) pfs := pathfs.NewPathNodeFs(fs, nil)
state, conn, err := MountNodeFileSystem(dir+"/mnt", pfs, nil) state, conn, err := fuse.MountNodeFileSystem(dir+"/mnt", pfs, nil)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
state.Debug = VerboseTest() state.Debug = fuse.VerboseTest()
conn.Debug = VerboseTest() conn.Debug = fuse.VerboseTest()
pfs.Debug = VerboseTest() pfs.Debug = fuse.VerboseTest()
go state.Loop() go state.Loop()
return dir, pfs, func() { return dir, pfs, func() {
...@@ -106,28 +109,28 @@ func TestCacheFs(t *testing.T) { ...@@ -106,28 +109,28 @@ func TestCacheFs(t *testing.T) {
} }
type nonseekFs struct { type nonseekFs struct {
DefaultFileSystem pathfs.DefaultFileSystem
Length int Length int
} }
func (fs *nonseekFs) GetAttr(name string, context *Context) (fi *Attr, status Status) { func (fs *nonseekFs) GetAttr(name string, context *fuse.Context) (fi *fuse.Attr, status fuse.Status) {
if name == "file" { if name == "file" {
return &Attr{Mode: S_IFREG | 0644}, OK return &fuse.Attr{Mode: fuse.S_IFREG | 0644}, fuse.OK
} }
return nil, ENOENT return nil, fuse.ENOENT
} }
func (fs *nonseekFs) Open(name string, flags uint32, context *Context) (fuseFile File, status Status) { func (fs *nonseekFs) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) {
if name != "file" { if name != "file" {
return nil, ENOENT return nil, fuse.ENOENT
} }
data := bytes.Repeat([]byte{42}, fs.Length) data := bytes.Repeat([]byte{42}, fs.Length)
f := NewDataFile(data) f := fuse.NewDataFile(data)
return &WithFlags{ return &fuse.WithFlags{
File: f, File: f,
FuseFlags: raw.FOPEN_NONSEEKABLE, FuseFlags: raw.FOPEN_NONSEEKABLE,
}, OK }, fuse.OK
} }
func TestNonseekable(t *testing.T) { func TestNonseekable(t *testing.T) {
...@@ -139,12 +142,12 @@ func TestNonseekable(t *testing.T) { ...@@ -139,12 +142,12 @@ func TestNonseekable(t *testing.T) {
t.Fatalf("failed: %v", err) t.Fatalf("failed: %v", err)
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
nfs := NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := MountNodeFileSystem(dir, nfs, nil) state, _, err := fuse.MountNodeFileSystem(dir, nfs, nil)
if err != nil { if err != nil {
t.Fatalf("failed: %v", err) t.Fatalf("failed: %v", err)
} }
state.Debug = VerboseTest() state.Debug = fuse.VerboseTest()
defer state.Unmount() defer state.Unmount()
go state.Loop() go state.Loop()
...@@ -171,16 +174,16 @@ func TestGetAttrRace(t *testing.T) { ...@@ -171,16 +174,16 @@ func TestGetAttrRace(t *testing.T) {
os.Mkdir(dir+"/mnt", 0755) os.Mkdir(dir+"/mnt", 0755)
os.Mkdir(dir+"/orig", 0755) os.Mkdir(dir+"/orig", 0755)
fs := NewLoopbackFileSystem(dir + "/orig") fs := pathfs.NewLoopbackFileSystem(dir + "/orig")
pfs := NewPathNodeFs(fs, nil) pfs := pathfs.NewPathNodeFs(fs, nil)
state, conn, err := MountNodeFileSystem(dir+"/mnt", pfs, state, conn, err := fuse.MountNodeFileSystem(dir+"/mnt", pfs,
&FileSystemOptions{}) &fuse.FileSystemOptions{})
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
state.Debug = VerboseTest() state.Debug = fuse.VerboseTest()
conn.Debug = VerboseTest() conn.Debug = fuse.VerboseTest()
pfs.Debug = VerboseTest() pfs.Debug = fuse.VerboseTest()
go state.Loop() go state.Loop()
defer state.Unmount() defer state.Unmount()
......
...@@ -7,12 +7,13 @@ import ( ...@@ -7,12 +7,13 @@ import (
"testing" "testing"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = log.Println var _ = log.Println
type DefaultReadFS struct { type DefaultReadFS struct {
fuse.DefaultFileSystem pathfs.DefaultFileSystem
size uint64 size uint64
exist bool exist bool
} }
...@@ -38,7 +39,7 @@ func defaultReadTest(t *testing.T) (root string, cleanup func()) { ...@@ -38,7 +39,7 @@ func defaultReadTest(t *testing.T) (root string, cleanup func()) {
if err != nil { if err != nil {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
pathfs := fuse.NewPathNodeFs(fs, nil) pathfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, pathfs, nil) state, _, err := fuse.MountNodeFileSystem(dir, pathfs, nil)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
......
...@@ -59,7 +59,7 @@ func TestDeleteNotify(t *testing.T) { ...@@ -59,7 +59,7 @@ func TestDeleteNotify(t *testing.T) {
ch.FsNode().SetInode(nil) ch.FsNode().SetInode(nil)
flip := flipNode{ flip := flipNode{
FsNode: ch.FsNode(), FsNode: ch.FsNode(),
ok: make(chan int), ok: make(chan int),
} }
newCh := fs.Root().Inode().New(true, &flip) newCh := fs.Root().Inode().New(true, &flip)
fs.Root().Inode().AddChild("testdir", newCh) fs.Root().Inode().AddChild("testdir", newCh)
......
...@@ -7,8 +7,9 @@ import ( ...@@ -7,8 +7,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw"
) )
type MutableDataFile struct { type MutableDataFile struct {
...@@ -89,7 +90,7 @@ func (f *MutableDataFile) Chmod(perms uint32) fuse.Status { ...@@ -89,7 +90,7 @@ func (f *MutableDataFile) Chmod(perms uint32) fuse.Status {
// This FS only supports a single r/w file called "/file". // This FS only supports a single r/w file called "/file".
type FSetAttrFs struct { type FSetAttrFs struct {
fuse.DefaultFileSystem pathfs.DefaultFileSystem
file *MutableDataFile file *MutableDataFile
} }
...@@ -131,12 +132,12 @@ func NewFile() *MutableDataFile { ...@@ -131,12 +132,12 @@ func NewFile() *MutableDataFile {
return &MutableDataFile{} return &MutableDataFile{}
} }
func setupFAttrTest(t *testing.T, fs fuse.FileSystem) (dir string, clean func(), sync func()) { func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func(), sync func()) {
dir, err := ioutil.TempDir("", "go-fuse-fsetattr_test") dir, err := ioutil.TempDir("", "go-fuse-fsetattr_test")
if err != nil { if err != nil {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
nfs := fuse.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, nfs, nil) state, _, err := fuse.MountNodeFileSystem(dir, nfs, nil)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
......
...@@ -6,7 +6,6 @@ import ( ...@@ -6,7 +6,6 @@ import (
"syscall" "syscall"
"testing" "testing"
"time" "time"
) )
func TestTouch(t *testing.T) { func TestTouch(t *testing.T) {
......
...@@ -14,8 +14,9 @@ import ( ...@@ -14,8 +14,9 @@ import (
"syscall" "syscall"
"testing" "testing"
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = strings.Join var _ = strings.Join
...@@ -37,7 +38,7 @@ type testCase struct { ...@@ -37,7 +38,7 @@ type testCase struct {
origSubdir string origSubdir string
tester *testing.T tester *testing.T
state *fuse.MountState state *fuse.MountState
pathFs *fuse.PathNodeFs pathFs *pathfs.PathNodeFs
connector *fuse.FileSystemConnector connector *fuse.FileSystemConnector
} }
...@@ -70,12 +71,12 @@ func NewTestCase(t *testing.T) *testCase { ...@@ -70,12 +71,12 @@ func NewTestCase(t *testing.T) *testCase {
me.origFile = filepath.Join(me.orig, name) me.origFile = filepath.Join(me.orig, name)
me.origSubdir = filepath.Join(me.orig, subdir) me.origSubdir = filepath.Join(me.orig, subdir)
var pfs fuse.FileSystem var pfs pathfs.FileSystem
pfs = fuse.NewLoopbackFileSystem(me.orig) pfs = pathfs.NewLoopbackFileSystem(me.orig)
pfs = fuse.NewLockingFileSystem(pfs) pfs = pathfs.NewLockingFileSystem(pfs)
var rfs fuse.RawFileSystem var rfs fuse.RawFileSystem
me.pathFs = fuse.NewPathNodeFs(pfs, &fuse.PathNodeFsOptions{ me.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{
ClientInodes: true}) ClientInodes: true})
me.connector = fuse.NewFileSystemConnector(me.pathFs, me.connector = fuse.NewFileSystemConnector(me.pathFs,
&fuse.FileSystemOptions{ &fuse.FileSystemOptions{
...@@ -928,8 +929,8 @@ func TestOriginalIsSymlink(t *testing.T) { ...@@ -928,8 +929,8 @@ func TestOriginalIsSymlink(t *testing.T) {
t.Fatalf("Symlink failed: %v", err) t.Fatalf("Symlink failed: %v", err)
} }
fs := fuse.NewLoopbackFileSystem(link) fs := pathfs.NewLoopbackFileSystem(link)
nfs := fuse.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mnt, nfs, nil) state, _, err := fuse.MountNodeFileSystem(mnt, nfs, nil)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
func TestMountOnExisting(t *testing.T) { func TestMountOnExisting(t *testing.T) {
...@@ -43,7 +44,7 @@ func TestMountRename(t *testing.T) { ...@@ -43,7 +44,7 @@ func TestMountRename(t *testing.T) {
ts := NewTestCase(t) ts := NewTestCase(t)
defer ts.Cleanup() defer ts.Cleanup()
fs := fuse.NewPathNodeFs(fuse.NewLoopbackFileSystem(ts.orig), nil) fs := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil) code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil)
if !code.Ok() { if !code.Ok() {
t.Fatal("mount should succeed") t.Fatal("mount should succeed")
...@@ -59,7 +60,7 @@ func TestMountReaddir(t *testing.T) { ...@@ -59,7 +60,7 @@ func TestMountReaddir(t *testing.T) {
ts := NewTestCase(t) ts := NewTestCase(t)
defer ts.Cleanup() defer ts.Cleanup()
fs := fuse.NewPathNodeFs(fuse.NewLoopbackFileSystem(ts.orig), nil) fs := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil) code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil)
if !code.Ok() { if !code.Ok() {
t.Fatal("mount should succeed") t.Fatal("mount should succeed")
...@@ -84,7 +85,7 @@ func TestRecursiveMount(t *testing.T) { ...@@ -84,7 +85,7 @@ func TestRecursiveMount(t *testing.T) {
t.Fatalf("WriteFile failed: %v", err) t.Fatalf("WriteFile failed: %v", err)
} }
fs := fuse.NewPathNodeFs(fuse.NewLoopbackFileSystem(ts.orig), nil) fs := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil) code := ts.connector.Mount(ts.rootNode(), "mnt", fs, nil)
if !code.Ok() { if !code.Ok() {
t.Fatal("mount should succeed") t.Fatal("mount should succeed")
...@@ -126,7 +127,7 @@ func TestDeletedUnmount(t *testing.T) { ...@@ -126,7 +127,7 @@ func TestDeletedUnmount(t *testing.T) {
defer ts.Cleanup() defer ts.Cleanup()
submnt := filepath.Join(ts.mnt, "mnt") submnt := filepath.Join(ts.mnt, "mnt")
pfs2 := fuse.NewPathNodeFs(fuse.NewLoopbackFileSystem(ts.orig), nil) pfs2 := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
code := ts.connector.Mount(ts.rootNode(), "mnt", pfs2, nil) code := ts.connector.Mount(ts.rootNode(), "mnt", pfs2, nil)
if !code.Ok() { if !code.Ok() {
t.Fatal("Mount error", code) t.Fatal("Mount error", code)
......
...@@ -8,12 +8,13 @@ import ( ...@@ -8,12 +8,13 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = log.Println var _ = log.Println
type NotifyFs struct { type NotifyFs struct {
fuse.DefaultFileSystem pathfs.DefaultFileSystem
size uint64 size uint64
exist bool exist bool
} }
...@@ -37,7 +38,7 @@ func (fs *NotifyFs) Open(name string, f uint32, context *fuse.Context) (fuse.Fil ...@@ -37,7 +38,7 @@ func (fs *NotifyFs) Open(name string, f uint32, context *fuse.Context) (fuse.Fil
type NotifyTest struct { type NotifyTest struct {
fs *NotifyFs fs *NotifyFs
pathfs *fuse.PathNodeFs pathfs *pathfs.PathNodeFs
connector *fuse.FileSystemConnector connector *fuse.FileSystemConnector
dir string dir string
state *fuse.MountState state *fuse.MountState
...@@ -58,7 +59,7 @@ func NewNotifyTest(t *testing.T) *NotifyTest { ...@@ -58,7 +59,7 @@ func NewNotifyTest(t *testing.T) *NotifyTest {
NegativeTimeout: entryTtl, NegativeTimeout: entryTtl,
} }
me.pathfs = fuse.NewPathNodeFs(me.fs, nil) me.pathfs = pathfs.NewPathNodeFs(me.fs, nil)
me.state, me.connector, err = fuse.MountNodeFileSystem(me.dir, me.pathfs, opts) me.state, me.connector, err = fuse.MountNodeFileSystem(me.dir, me.pathfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
......
...@@ -12,11 +12,12 @@ import ( ...@@ -12,11 +12,12 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
type knownFs struct { type knownFs struct {
*UnionFs *UnionFs
*fuse.PathNodeFs *pathfs.PathNodeFs
} }
// Creates unions for all files under a given directory, // Creates unions for all files under a given directory,
...@@ -25,14 +26,14 @@ type knownFs struct { ...@@ -25,14 +26,14 @@ type knownFs struct {
// //
// A union for A/B/C will placed under directory A-B-C. // A union for A/B/C will placed under directory A-B-C.
type AutoUnionFs struct { type AutoUnionFs struct {
fuse.DefaultFileSystem pathfs.DefaultFileSystem
lock sync.RWMutex lock sync.RWMutex
knownFileSystems map[string]knownFs knownFileSystems map[string]knownFs
nameRootMap map[string]string nameRootMap map[string]string
root string root string
nodeFs *fuse.PathNodeFs nodeFs *pathfs.PathNodeFs
options *AutoUnionFsOptions options *AutoUnionFsOptions
mountState *fuse.MountState mountState *fuse.MountState
...@@ -42,7 +43,7 @@ type AutoUnionFs struct { ...@@ -42,7 +43,7 @@ type AutoUnionFs struct {
type AutoUnionFsOptions struct { type AutoUnionFsOptions struct {
UnionFsOptions UnionFsOptions
fuse.FileSystemOptions fuse.FileSystemOptions
fuse.PathNodeFsOptions pathfs.PathNodeFsOptions
// If set, run updateKnownFses() after mounting. // If set, run updateKnownFses() after mounting.
UpdateOnMount bool UpdateOnMount bool
...@@ -82,7 +83,7 @@ func (fs *AutoUnionFs) String() string { ...@@ -82,7 +83,7 @@ func (fs *AutoUnionFs) String() string {
return fmt.Sprintf("AutoUnionFs(%s)", fs.root) return fmt.Sprintf("AutoUnionFs(%s)", fs.root)
} }
func (fs *AutoUnionFs) OnMount(nodeFs *fuse.PathNodeFs) { func (fs *AutoUnionFs) OnMount(nodeFs *pathfs.PathNodeFs) {
fs.nodeFs = nodeFs fs.nodeFs = nodeFs
if fs.options.UpdateOnMount { if fs.options.UpdateOnMount {
time.AfterFunc(100*time.Millisecond, func() { fs.updateKnownFses() }) time.AfterFunc(100*time.Millisecond, func() { fs.updateKnownFses() })
...@@ -123,7 +124,7 @@ func (fs *AutoUnionFs) createFs(name string, roots []string) fuse.Status { ...@@ -123,7 +124,7 @@ func (fs *AutoUnionFs) createFs(name string, roots []string) fuse.Status {
} }
log.Printf("Adding workspace %v for roots %v", name, ufs.String()) log.Printf("Adding workspace %v for roots %v", name, ufs.String())
nfs := fuse.NewPathNodeFs(ufs, &fs.options.PathNodeFsOptions) nfs := pathfs.NewPathNodeFs(ufs, &fs.options.PathNodeFsOptions)
code := fs.nodeFs.Mount(name, nfs, &fs.options.FileSystemOptions) code := fs.nodeFs.Mount(name, nfs, &fs.options.FileSystemOptions)
if code.Ok() { if code.Ok() {
fs.knownFileSystems[name] = knownFs{ fs.knownFileSystems[name] = knownFs{
......
...@@ -2,12 +2,14 @@ package unionfs ...@@ -2,12 +2,14 @@ package unionfs
import ( import (
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"testing" "testing"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = fmt.Print var _ = fmt.Print
...@@ -53,7 +55,7 @@ func setup(t *testing.T) (workdir string, cleanup func()) { ...@@ -53,7 +55,7 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
fs := NewAutoUnionFs(wd+"/store", testAOpts) fs := NewAutoUnionFs(wd+"/store", testAOpts)
nfs := fuse.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, conn, err := fuse.MountNodeFileSystem(wd+"/mnt", nfs, &testAOpts.FileSystemOptions) state, conn, err := fuse.MountNodeFileSystem(wd+"/mnt", nfs, &testAOpts.FileSystemOptions)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
......
...@@ -2,10 +2,12 @@ package unionfs ...@@ -2,10 +2,12 @@ package unionfs
import ( import (
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"log" "log"
"strings" "strings"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = fmt.Println var _ = fmt.Println
...@@ -34,7 +36,7 @@ type linkResponse struct { ...@@ -34,7 +36,7 @@ type linkResponse struct {
// Caches filesystem metadata. // Caches filesystem metadata.
type CachingFileSystem struct { type CachingFileSystem struct {
fuse.FileSystem pathfs.FileSystem
attributes *TimedCache attributes *TimedCache
dirs *TimedCache dirs *TimedCache
...@@ -42,7 +44,7 @@ type CachingFileSystem struct { ...@@ -42,7 +44,7 @@ type CachingFileSystem struct {
xattr *TimedCache xattr *TimedCache
} }
func readDir(fs fuse.FileSystem, name string) *dirResponse { func readDir(fs pathfs.FileSystem, name string) *dirResponse {
origStream, code := fs.OpenDir(name, nil) origStream, code := fs.OpenDir(name, nil)
r := &dirResponse{nil, code} r := &dirResponse{nil, code}
...@@ -53,7 +55,7 @@ func readDir(fs fuse.FileSystem, name string) *dirResponse { ...@@ -53,7 +55,7 @@ func readDir(fs fuse.FileSystem, name string) *dirResponse {
return r return r
} }
func getAttr(fs fuse.FileSystem, name string) *attrResponse { func getAttr(fs pathfs.FileSystem, name string) *attrResponse {
a, code := fs.GetAttr(name, nil) a, code := fs.GetAttr(name, nil)
return &attrResponse{ return &attrResponse{
Attr: a, Attr: a,
...@@ -61,7 +63,7 @@ func getAttr(fs fuse.FileSystem, name string) *attrResponse { ...@@ -61,7 +63,7 @@ func getAttr(fs fuse.FileSystem, name string) *attrResponse {
} }
} }
func getXAttr(fs fuse.FileSystem, nameAttr string) *xattrResponse { func getXAttr(fs pathfs.FileSystem, nameAttr string) *xattrResponse {
ns := strings.SplitN(nameAttr, _XATTRSEP, 2) ns := strings.SplitN(nameAttr, _XATTRSEP, 2)
a, code := fs.GetXAttr(ns[0], ns[1], nil) a, code := fs.GetXAttr(ns[0], ns[1], nil)
return &xattrResponse{ return &xattrResponse{
...@@ -70,7 +72,7 @@ func getXAttr(fs fuse.FileSystem, nameAttr string) *xattrResponse { ...@@ -70,7 +72,7 @@ func getXAttr(fs fuse.FileSystem, nameAttr string) *xattrResponse {
} }
} }
func readLink(fs fuse.FileSystem, name string) *linkResponse { func readLink(fs pathfs.FileSystem, name string) *linkResponse {
a, code := fs.Readlink(name, nil) a, code := fs.Readlink(name, nil)
return &linkResponse{ return &linkResponse{
linkContent: a, linkContent: a,
...@@ -78,7 +80,7 @@ func readLink(fs fuse.FileSystem, name string) *linkResponse { ...@@ -78,7 +80,7 @@ func readLink(fs fuse.FileSystem, name string) *linkResponse {
} }
} }
func NewCachingFileSystem(fs fuse.FileSystem, ttl time.Duration) *CachingFileSystem { func NewCachingFileSystem(fs pathfs.FileSystem, ttl time.Duration) *CachingFileSystem {
c := new(CachingFileSystem) c := new(CachingFileSystem)
c.FileSystem = fs c.FileSystem = fs
c.attributes = NewTimedCache(func(n string) (interface{}, bool) { c.attributes = NewTimedCache(func(n string) (interface{}, bool) {
......
...@@ -2,12 +2,14 @@ package unionfs ...@@ -2,12 +2,14 @@ package unionfs
import ( import (
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"syscall" "syscall"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = fmt.Print var _ = fmt.Print
...@@ -31,7 +33,7 @@ func TestCachingFs(t *testing.T) { ...@@ -31,7 +33,7 @@ func TestCachingFs(t *testing.T) {
wd, _ := ioutil.TempDir("", "") wd, _ := ioutil.TempDir("", "")
defer os.RemoveAll(wd) defer os.RemoveAll(wd)
fs := fuse.NewLoopbackFileSystem(wd) fs := pathfs.NewLoopbackFileSystem(wd)
cfs := NewCachingFileSystem(fs, 0) cfs := NewCachingFileSystem(fs, 0)
os.Mkdir(wd+"/orig", 0755) os.Mkdir(wd+"/orig", 0755)
......
package unionfs package unionfs
import ( import (
"github.com/hanwen/go-fuse/fuse"
"os" "os"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
func NewUnionFsFromRoots(roots []string, opts *UnionFsOptions, roCaching bool) (*UnionFs, error) { func NewUnionFsFromRoots(roots []string, opts *UnionFsOptions, roCaching bool) (*UnionFs, error) {
fses := make([]fuse.FileSystem, 0) fses := make([]pathfs.FileSystem, 0)
for i, r := range roots { for i, r := range roots {
var fs fuse.FileSystem var fs pathfs.FileSystem
fi, err := os.Stat(r) fi, err := os.Stat(r)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if fi.IsDir() { if fi.IsDir() {
fs = fuse.NewLoopbackFileSystem(r) fs = pathfs.NewLoopbackFileSystem(r)
} }
if fs == nil { if fs == nil {
return nil, err return nil, err
......
package unionfs package unionfs
import ( import (
"github.com/hanwen/go-fuse/fuse"
"log" "log"
"sync" "sync"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
// newDirnameMap reads the contents of the given directory. On error, // newDirnameMap reads the contents of the given directory. On error,
// returns a nil map. This forces reloads in the DirCache until we // returns a nil map. This forces reloads in the DirCache until we
// succeed. // succeed.
func newDirnameMap(fs fuse.FileSystem, dir string) map[string]bool { func newDirnameMap(fs pathfs.FileSystem, dir string) map[string]bool {
stream, code := fs.OpenDir(dir, nil) stream, code := fs.OpenDir(dir, nil)
if code == fuse.ENOENT { if code == fuse.ENOENT {
// The directory not existing is not an error. // The directory not existing is not an error.
...@@ -38,7 +40,7 @@ func newDirnameMap(fs fuse.FileSystem, dir string) map[string]bool { ...@@ -38,7 +40,7 @@ func newDirnameMap(fs fuse.FileSystem, dir string) map[string]bool {
type DirCache struct { type DirCache struct {
dir string dir string
ttl time.Duration ttl time.Duration
fs fuse.FileSystem fs pathfs.FileSystem
// Protects data below. // Protects data below.
lock sync.RWMutex lock sync.RWMutex
...@@ -100,7 +102,7 @@ func (c *DirCache) AddEntry(name string) { ...@@ -100,7 +102,7 @@ func (c *DirCache) AddEntry(name string) {
c.names[name] = true c.names[name] = true
} }
func NewDirCache(fs fuse.FileSystem, dir string, ttl time.Duration) *DirCache { func NewDirCache(fs pathfs.FileSystem, dir string, ttl time.Duration) *DirCache {
dc := new(DirCache) dc := new(DirCache)
dc.dir = dir dc.dir = dir
dc.fs = fs dc.fs = fs
......
...@@ -3,8 +3,6 @@ package unionfs ...@@ -3,8 +3,6 @@ package unionfs
import ( import (
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw"
"log" "log"
"os" "os"
"path" "path"
...@@ -13,6 +11,10 @@ import ( ...@@ -13,6 +11,10 @@ import (
"sync" "sync"
"syscall" "syscall"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw"
) )
func filePathHash(path string) string { func filePathHash(path string) string {
...@@ -55,10 +57,10 @@ func filePathHash(path string) string { ...@@ -55,10 +57,10 @@ func filePathHash(path string) string {
*/ */
type UnionFs struct { type UnionFs struct {
fuse.DefaultFileSystem pathfs.DefaultFileSystem
// The same, but as interfaces. // The same, but as interfaces.
fileSystems []fuse.FileSystem fileSystems []pathfs.FileSystem
// A file-existence cache. // A file-existence cache.
deletionCache *DirCache deletionCache *DirCache
...@@ -70,7 +72,7 @@ type UnionFs struct { ...@@ -70,7 +72,7 @@ type UnionFs struct {
hiddenFiles map[string]bool hiddenFiles map[string]bool
options *UnionFsOptions options *UnionFsOptions
nodeFs *fuse.PathNodeFs nodeFs *pathfs.PathNodeFs
} }
type UnionFsOptions struct { type UnionFsOptions struct {
...@@ -84,7 +86,7 @@ const ( ...@@ -84,7 +86,7 @@ const (
_DROP_CACHE = ".drop_cache" _DROP_CACHE = ".drop_cache"
) )
func NewUnionFs(fileSystems []fuse.FileSystem, options UnionFsOptions) *UnionFs { func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) *UnionFs {
g := new(UnionFs) g := new(UnionFs)
g.options = &options g.options = &options
g.fileSystems = fileSystems g.fileSystems = fileSystems
...@@ -109,7 +111,7 @@ func NewUnionFs(fileSystems []fuse.FileSystem, options UnionFsOptions) *UnionFs ...@@ -109,7 +111,7 @@ func NewUnionFs(fileSystems []fuse.FileSystem, options UnionFsOptions) *UnionFs
return g return g
} }
func (fs *UnionFs) OnMount(nodeFs *fuse.PathNodeFs) { func (fs *UnionFs) OnMount(nodeFs *pathfs.PathNodeFs) {
fs.nodeFs = nodeFs fs.nodeFs = nodeFs
} }
...@@ -275,7 +277,7 @@ func (fs *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co ...@@ -275,7 +277,7 @@ func (fs *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co
fs.promoteDirsTo(name) fs.promoteDirsTo(name)
if srcResult.attr.IsRegular() { if srcResult.attr.IsRegular() {
code = fuse.CopyFile(sourceFs, writable, name, name, context) code = pathfs.CopyFile(sourceFs, writable, name, name, context)
if code.Ok() { if code.Ok() {
code = writable.Chmod(name, srcResult.attr.Mode&07777|0200, context) code = writable.Chmod(name, srcResult.attr.Mode&07777|0200, context)
...@@ -598,7 +600,7 @@ func (fs *UnionFs) Readlink(name string, context *fuse.Context) (out string, cod ...@@ -598,7 +600,7 @@ func (fs *UnionFs) Readlink(name string, context *fuse.Context) (out string, cod
return "", fuse.ENOENT return "", fuse.ENOENT
} }
func IsDir(fs fuse.FileSystem, name string) bool { func IsDir(fs pathfs.FileSystem, name string) bool {
a, code := fs.GetAttr(name, nil) a, code := fs.GetAttr(name, nil)
return code.Ok() && a.IsDir() return code.Ok() && a.IsDir()
} }
...@@ -742,7 +744,7 @@ func (fs *UnionFs) OpenDir(directory string, context *fuse.Context) (stream []fu ...@@ -742,7 +744,7 @@ func (fs *UnionFs) OpenDir(directory string, context *fuse.Context) (stream []fu
for i, l := range fs.fileSystems { for i, l := range fs.fileSystems {
if i >= dirBranch.branch { if i >= dirBranch.branch {
wg.Add(1) wg.Add(1)
go func(j int, pfs fuse.FileSystem) { go func(j int, pfs pathfs.FileSystem) {
ch, s := pfs.OpenDir(directory, context) ch, s := pfs.OpenDir(directory, context)
statuses[j] = s statuses[j] = s
for _, v := range ch { for _, v := range ch {
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
...@@ -76,10 +77,10 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) { ...@@ -76,10 +77,10 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
t.Fatalf("Mkdir failed: %v", err) t.Fatalf("Mkdir failed: %v", err)
} }
var fses []fuse.FileSystem var fses []pathfs.FileSystem
fses = append(fses, fuse.NewLoopbackFileSystem(wd+"/rw")) fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/rw"))
fses = append(fses, fses = append(fses,
NewCachingFileSystem(fuse.NewLoopbackFileSystem(wd+"/ro"), 0)) NewCachingFileSystem(pathfs.NewLoopbackFileSystem(wd+"/ro"), 0))
ufs := NewUnionFs(fses, testOpts) ufs := NewUnionFs(fses, testOpts)
// We configure timeouts are smaller, so we can check for // We configure timeouts are smaller, so we can check for
...@@ -90,8 +91,8 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) { ...@@ -90,8 +91,8 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
NegativeTimeout: entryTtl / 2, NegativeTimeout: entryTtl / 2,
} }
pathfs := fuse.NewPathNodeFs(ufs, pathfs := pathfs.NewPathNodeFs(ufs,
&fuse.PathNodeFsOptions{ClientInodes: true}) &pathfs.PathNodeFsOptions{ClientInodes: true})
state, conn, err := fuse.MountNodeFileSystem(wd+"/mnt", pathfs, opts) state, conn, err := fuse.MountNodeFileSystem(wd+"/mnt", pathfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
...@@ -1099,10 +1100,10 @@ func TestUnionFsDisappearing(t *testing.T) { ...@@ -1099,10 +1100,10 @@ func TestUnionFsDisappearing(t *testing.T) {
t.Fatalf("Mkdir failed: %v", err) t.Fatalf("Mkdir failed: %v", err)
} }
wrFs := fuse.NewLoopbackFileSystem(wd + "/rw") wrFs := pathfs.NewLoopbackFileSystem(wd + "/rw")
var fses []fuse.FileSystem var fses []pathfs.FileSystem
fses = append(fses, wrFs) fses = append(fses, wrFs)
fses = append(fses, fuse.NewLoopbackFileSystem(wd+"/ro")) fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/ro"))
ufs := NewUnionFs(fses, testOpts) ufs := NewUnionFs(fses, testOpts)
opts := &fuse.FileSystemOptions{ opts := &fuse.FileSystemOptions{
...@@ -1111,7 +1112,7 @@ func TestUnionFsDisappearing(t *testing.T) { ...@@ -1111,7 +1112,7 @@ func TestUnionFsDisappearing(t *testing.T) {
NegativeTimeout: entryTtl, NegativeTimeout: entryTtl,
} }
nfs := fuse.NewPathNodeFs(ufs, nil) nfs := pathfs.NewPathNodeFs(ufs, nil)
state, _, err := fuse.MountNodeFileSystem(wd+"/mnt", nfs, opts) state, _, err := fuse.MountNodeFileSystem(wd+"/mnt", nfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
......
...@@ -11,14 +11,16 @@ symlinking path/to/zipfile to /config/zipmount ...@@ -11,14 +11,16 @@ symlinking path/to/zipfile to /config/zipmount
*/ */
import ( import (
"github.com/hanwen/go-fuse/fuse"
"log" "log"
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = log.Printf var _ = log.Printf
var _ = (fuse.FileSystem)((*MultiZipFs)(nil)) var _ = (pathfs.FileSystem)((*MultiZipFs)(nil))
const ( const (
CONFIG_PREFIX = "config/" CONFIG_PREFIX = "config/"
...@@ -32,8 +34,8 @@ type MultiZipFs struct { ...@@ -32,8 +34,8 @@ type MultiZipFs struct {
zips map[string]*MemTreeFs zips map[string]*MemTreeFs
dirZipFileMap map[string]string dirZipFileMap map[string]string
nodeFs *fuse.PathNodeFs nodeFs *pathfs.PathNodeFs
fuse.DefaultFileSystem pathfs.DefaultFileSystem
} }
func NewMultiZipFs() *MultiZipFs { func NewMultiZipFs() *MultiZipFs {
...@@ -47,7 +49,7 @@ func (fs *MultiZipFs) String() string { ...@@ -47,7 +49,7 @@ func (fs *MultiZipFs) String() string {
return "MultiZipFs" return "MultiZipFs"
} }
func (fs *MultiZipFs) OnMount(nodeFs *fuse.PathNodeFs) { func (fs *MultiZipFs) OnMount(nodeFs *pathfs.PathNodeFs) {
fs.nodeFs = nodeFs fs.nodeFs = nodeFs
} }
......
package zipfs package zipfs
import ( import (
"github.com/hanwen/go-fuse/fuse"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"testing" "testing"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
) )
var _ = log.Printf var _ = log.Printf
...@@ -16,7 +18,7 @@ const testTtl = 100 * time.Millisecond ...@@ -16,7 +18,7 @@ const testTtl = 100 * time.Millisecond
func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) { func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
fs := NewMultiZipFs() fs := NewMultiZipFs()
mountPoint, _ = ioutil.TempDir("", "") mountPoint, _ = ioutil.TempDir("", "")
nfs := fuse.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, &fuse.FileSystemOptions{ state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, &fuse.FileSystemOptions{
EntryTimeout: testTtl, EntryTimeout: testTtl,
AttrTimeout: testTtl, AttrTimeout: testTtl,
......
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