Commit 480c7997 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

fuse: Split off node FS code into fuse/nodefs/ package.

Update client code with:

gofmt -w -r 'fuse.File -> nodefs.File' $*
gofmt -w -r 'fuse.StatfsOut -> nodefs.StatfsOut' $*
gofmt -w -r 'fuse.FileSystemConnector -> nodefs.FileSystemConnector' $*
gofmt -w -r 'fuse.Inode -> nodefs.Inode' $*
gofmt -w -r 'fuse.NodeFileSystem -> nodefs.FileSystem' $*
gofmt -w -r 'fuse.FileSystemOptions -> nodefs.Options' $*
gofmt -w -r 'fuse.NewFileSystemOptions -> nodefs.NewOptions' $*
gofmt -w -r 'fuse.FsNode -> nodefs.Node' $*
gofmt -w -r 'fuse.WithFlags -> nodefs.WithFlags' $*
gofmt -w -r 'fuse.NewLoopbackFile -> nodefs.NewLoopbackFile' $*
gofmt -w -r 'x.FsNode -> x.Node' $*
gofmt -w -r 'fuse.NewReadOnlyFile -> nodefs.NewReadOnlyFile' $*
gofmt -w -r 'fuse.MountNodeFileSystem -> nodefs.MountFileSystem' $*
gofmt -w -r 'fuse.NewDataFile -> nodefs.NewDataFile' $*
gofmt -w -r 'fuse.NewDefaultFile -> nodefs.NewDefaultFile' $*
gofmt -w -r 'fuse.NewMemNodeFs -> nodefs.NewMemNodeFs' $*
gofmt -w -r 'fuse.NewFileSystemConnector -> nodefs.NewFileSystemConnector' $*
gofmt -w -r 'fuse.NewDefaultNodeFileSystem -> nodefs.NewDefaultFileSystem' $*
gofmt -w -r 'fuse.NewDefaultFsNode -> nodefs.NewDefaultNode' $*
gofmt -w -r 'fuse.NewDevNullFile -> nodefs.NewDevNullFile' $*
parent 674cd032
...@@ -12,19 +12,19 @@ import ( ...@@ -12,19 +12,19 @@ import (
"testing" "testing"
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
func setupFs(fs pathfs.FileSystem) (string, func()) { func setupFs(fs pathfs.FileSystem) (string, func()) {
opts := &fuse.FileSystemOptions{ opts := &nodefs.Options{
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 := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, opts) state, _, err := nodefs.MountFileSystem(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.
} }
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/unionfs" "github.com/hanwen/go-fuse/unionfs"
) )
...@@ -43,7 +44,7 @@ func main() { ...@@ -43,7 +44,7 @@ func main() {
} }
options := unionfs.AutoUnionFsOptions{ options := unionfs.AutoUnionFsOptions{
UnionFsOptions: ufsOptions, UnionFsOptions: ufsOptions,
FileSystemOptions: fuse.FileSystemOptions{ Options: nodefs.Options{
EntryTimeout: time.Second, EntryTimeout: time.Second,
AttrTimeout: time.Second, AttrTimeout: time.Second,
NegativeTimeout: time.Second, NegativeTimeout: time.Second,
...@@ -55,13 +56,13 @@ func main() { ...@@ -55,13 +56,13 @@ func main() {
}, },
HideReadonly: *hide_readonly_link, HideReadonly: *hide_readonly_link,
} }
fsOpts := fuse.FileSystemOptions{ fsOpts := nodefs.Options{
PortableInodes: *portableInodes, PortableInodes: *portableInodes,
} }
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 := pathfs.NewPathNodeFs(gofs, nil) pathfs := pathfs.NewPathNodeFs(gofs, nil)
state, conn, err := fuse.MountNodeFileSystem(flag.Arg(0), pathfs, &fsOpts) state, conn, err := nodefs.MountFileSystem(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)
os.Exit(1) os.Exit(1)
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"log" "log"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -36,14 +37,14 @@ func (me *HelloFs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntr ...@@ -36,14 +37,14 @@ func (me *HelloFs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntr
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (me *HelloFs) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) { func (me *HelloFs) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
if name != "file.txt" { if name != "file.txt" {
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM return nil, fuse.EPERM
} }
return fuse.NewDataFile([]byte(name)), fuse.OK return nodefs.NewDataFile([]byte(name)), fuse.OK
} }
func main() { func main() {
...@@ -52,7 +53,7 @@ func main() { ...@@ -52,7 +53,7 @@ func main() {
log.Fatal("Usage:\n hello MOUNTPOINT") log.Fatal("Usage:\n hello MOUNTPOINT")
} }
nfs := pathfs.NewPathNodeFs(&HelloFs{FileSystem: pathfs.NewDefaultFileSystem()}, nil) nfs := pathfs.NewPathNodeFs(&HelloFs{FileSystem: pathfs.NewDefaultFileSystem()}, nil)
state, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nfs, nil) state, _, err := nodefs.MountFileSystem(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)
} }
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -34,7 +35,7 @@ func main() { ...@@ -34,7 +35,7 @@ func main() {
loopbackfs := pathfs.NewLoopbackFileSystem(orig) loopbackfs := pathfs.NewLoopbackFileSystem(orig)
finalFs = loopbackfs finalFs = loopbackfs
opts := &fuse.FileSystemOptions{ opts := &nodefs.Options{
// These options are to be compatible with libfuse defaults, // These options are to be compatible with libfuse defaults,
// making benchmarking easier. // making benchmarking easier.
NegativeTimeout: time.Second, NegativeTimeout: time.Second,
...@@ -42,7 +43,7 @@ func main() { ...@@ -42,7 +43,7 @@ func main() {
EntryTimeout: time.Second, EntryTimeout: time.Second,
} }
pathFs := pathfs.NewPathNodeFs(finalFs, nil) pathFs := pathfs.NewPathNodeFs(finalFs, nil)
conn := fuse.NewFileSystemConnector(pathFs, opts) conn := nodefs.NewFileSystemConnector(pathFs, opts)
state := fuse.NewMountState(conn.RawFS()) state := fuse.NewMountState(conn.RawFS())
state.SetDebug(*debug) state.SetDebug(*debug)
......
...@@ -5,14 +5,11 @@ package main ...@@ -5,14 +5,11 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"log"
"os" "os"
"runtime"
)
var _ = runtime.GOMAXPROCS "github.com/hanwen/go-fuse/fuse"
var _ = log.Print "github.com/hanwen/go-fuse/fuse/nodefs"
)
func main() { func main() {
// Scans the arg list and sets up flags // Scans the arg list and sets up flags
...@@ -26,9 +23,9 @@ func main() { ...@@ -26,9 +23,9 @@ func main() {
mountPoint := flag.Arg(0) mountPoint := flag.Arg(0)
prefix := flag.Arg(1) prefix := flag.Arg(1)
fs := fuse.NewMemNodeFs(prefix) fs := nodefs.NewMemNodeFs(prefix)
conn := fuse.NewFileSystemConnector(fs, nil) conn := nodefs.NewFileSystemConnector(fs, nil)
state := fuse.NewMountState(conn) state := fuse.NewMountState(conn.RawFS())
state.SetDebug(*debug) state.SetDebug(*debug)
fmt.Println("Mounting") fmt.Println("Mounting")
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/zipfs" "github.com/hanwen/go-fuse/zipfs"
) )
...@@ -26,7 +26,7 @@ func main() { ...@@ -26,7 +26,7 @@ func main() {
fs := zipfs.NewMultiZipFs() fs := zipfs.NewMultiZipFs()
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nfs, nil) state, _, err := nodefs.MountFileSystem(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)
os.Exit(1) os.Exit(1)
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"os" "os"
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/unionfs" "github.com/hanwen/go-fuse/unionfs"
) )
...@@ -42,13 +42,13 @@ func main() { ...@@ -42,13 +42,13 @@ func main() {
os.Exit(1) os.Exit(1)
} }
nodeFs := pathfs.NewPathNodeFs(ufs, &pathfs.PathNodeFsOptions{ClientInodes: true}) nodeFs := pathfs.NewPathNodeFs(ufs, &pathfs.PathNodeFsOptions{ClientInodes: true})
mOpts := fuse.FileSystemOptions{ mOpts := nodefs.Options{
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)),
NegativeTimeout: time.Duration(*negative_ttl * float64(time.Second)), NegativeTimeout: time.Duration(*negative_ttl * float64(time.Second)),
PortableInodes: *portable, PortableInodes: *portable,
} }
mountState, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nodeFs, &mOpts) mountState, _, err := nodefs.MountFileSystem(flag.Arg(0), nodeFs, &mOpts)
if err != nil { if err != nil {
log.Fatal("Mount fail:", err) log.Fatal("Mount fail:", err)
} }
......
...@@ -3,8 +3,6 @@ package main ...@@ -3,8 +3,6 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/zipfs"
"io" "io"
"log" "log"
"os" "os"
...@@ -13,9 +11,10 @@ import ( ...@@ -13,9 +11,10 @@ import (
"runtime/pprof" "runtime/pprof"
"strings" "strings"
"time" "time"
)
var _ = log.Printf "github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/zipfs"
)
func main() { func main() {
// Scans the arg list and sets up flags // Scans the arg list and sets up flags
...@@ -45,18 +44,18 @@ func main() { ...@@ -45,18 +44,18 @@ func main() {
} }
} }
var fs fuse.NodeFileSystem var fs nodefs.FileSystem
fs, err = zipfs.NewArchiveFileSystem(flag.Arg(1)) fs, err = zipfs.NewArchiveFileSystem(flag.Arg(1))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "NewArchiveFileSystem failed: %v\n", err) fmt.Fprintf(os.Stderr, "NewArchiveFileSystem failed: %v\n", err)
os.Exit(1) os.Exit(1)
} }
opts := &fuse.FileSystemOptions{ opts := &nodefs.Options{
AttrTimeout: time.Duration(*ttl * float64(time.Second)), AttrTimeout: time.Duration(*ttl * float64(time.Second)),
EntryTimeout: time.Duration(*ttl * float64(time.Second)), EntryTimeout: time.Duration(*ttl * float64(time.Second)),
} }
state, _, err := fuse.MountNodeFileSystem(flag.Arg(0), fs, opts) state, _, err := nodefs.MountFileSystem(flag.Arg(0), fs, opts)
if err != nil { if err != nil {
fmt.Printf("Mount fail: %v\n", err) fmt.Printf("Mount fail: %v\n", err)
os.Exit(1) os.Exit(1)
......
// The fuse package provides APIs to implement filesystems in // The fuse package provides APIs to implement filesystems in
// userspace. Typically, each call of the API happens in its own // userspace. Typically, each call of the API happens in its own
// goroutine, so take care to make the file system thread-safe. // goroutine, so take care to make the file system thread-safe.
package fuse package fuse
import ( import (
"time"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
// Types for users to implement. // Types for users to implement.
// NodeFileSystem is a high level API that resembles the kernel's idea
// of what an FS looks like. NodeFileSystems can have multiple
// hard-links to one file, for example. It is also suited if the data
// to represent fits in memory: you can construct FsNode at mount
// time, and the filesystem will be ready.
type NodeFileSystem interface {
// OnUnmount is executed just before a submount is removed,
// and when the process receives a forget for the FUSE root
// node.
OnUnmount()
// OnMount is called just after a mount is executed, either
// when the root is mounted, or when other filesystem are
// mounted in-process. The passed-in FileSystemConnector gives
// access to Notify methods and Debug settings.
OnMount(conn *FileSystemConnector)
// Root should return the inode for root of this file system.
Root() FsNode
// Used for debug outputs
String() string
// If called, provide debug output through the log package.
SetDebug(debug bool)
}
// The FsNode implements the basic functionality of inodes; this is
// where the majority of the FS code for a typical filesystem will be.
type FsNode interface {
// Inode and SetInode are basic getter/setters. They are
// called by the FileSystemConnector. You get them for free by
// embedding the result of NewDefaultFsNode() in your node
// struct.
Inode() *Inode
SetInode(node *Inode)
// Lookup finds a child node to this node; it is only called
// for directory FsNodes.
Lookup(out *Attr, name string, context *Context) (node FsNode, code Status)
// Deletable() should return true if this inode may be
// discarded from the children list. This will be called from
// within the treeLock critical section, so you cannot look at
// other inodes.
Deletable() bool
// OnForget is called when the reference to this inode is
// dropped from the tree.
OnForget()
// Misc.
Access(mode uint32, context *Context) (code Status)
Readlink(c *Context) ([]byte, Status)
// Namespace operations; these are only called on directory FsNodes.
Mknod(name string, mode uint32, dev uint32, context *Context) (newNode FsNode, code Status)
Mkdir(name string, mode uint32, context *Context) (newNode FsNode, code Status)
Unlink(name string, context *Context) (code Status)
Rmdir(name string, context *Context) (code Status)
Symlink(name string, content string, context *Context) (newNode FsNode, code Status)
Rename(oldName string, newParent FsNode, newName string, context *Context) (code Status)
Link(name string, existing FsNode, context *Context) (newNode FsNode, code Status)
// Files
Create(name string, flags uint32, mode uint32, context *Context) (file File, newNode FsNode, code Status)
Open(flags uint32, context *Context) (file File, code Status)
OpenDir(context *Context) ([]DirEntry, Status)
// XAttrs
GetXAttr(attribute string, context *Context) (data []byte, code Status)
RemoveXAttr(attr string, context *Context) Status
SetXAttr(attr string, data []byte, flags int, context *Context) Status
ListXAttr(context *Context) (attrs []string, code Status)
// Attributes
GetAttr(out *Attr, file File, context *Context) (code Status)
Chmod(file File, perms uint32, context *Context) (code Status)
Chown(file File, uid uint32, gid uint32, context *Context) (code Status)
Truncate(file File, size uint64, context *Context) (code Status)
Utimens(file File, atime *time.Time, mtime *time.Time, context *Context) (code Status)
Fallocate(file File, off uint64, size uint64, mode uint32, context *Context) (code Status)
StatFs() *StatfsOut
}
// A File object should be returned from FileSystem.Open and
// FileSystem.Create. Include the NewDefaultFile return value into
// the struct to inherit a default null implementation.
//
// TODO - should File be thread safe?
// TODO - should we pass a *Context argument?
type File interface {
// Called upon registering the filehandle in the inode.
SetInode(*Inode)
// The String method is for debug printing.
String() string
// Wrappers around other File implementations, should return
// the inner file here.
InnerFile() File
Read(dest []byte, off int64) (ReadResult, Status)
Write(data []byte, off int64) (written uint32, code Status)
Flush() Status
Release()
Fsync(flags int) (code Status)
// The methods below may be called on closed files, due to
// concurrency. In that case, you should return EBADF.
Truncate(size uint64) Status
GetAttr(out *Attr) Status
Chown(uid uint32, gid uint32) Status
Chmod(perms uint32) Status
Utimens(atime *time.Time, mtime *time.Time) Status
Allocate(off uint64, size uint64, mode uint32) (code Status)
}
// The result of Read is an array of bytes, but for performance // The result of Read is an array of bytes, but for performance
// reasons, we can also return data as a file-descriptor/offset/size // reasons, we can also return data as a file-descriptor/offset/size
// tuple. If the backing store for a file is another filesystem, this // tuple. If the backing store for a file is another filesystem, this
...@@ -148,41 +28,6 @@ type ReadResult interface { ...@@ -148,41 +28,6 @@ type ReadResult interface {
Done() Done()
} }
// Wrap a File return in this to set FUSE flags. Also used internally
// to store open file data.
type WithFlags struct {
File
// For debugging.
Description string
// Put FOPEN_* flags here.
FuseFlags uint32
// O_RDWR, O_TRUNCATE, etc.
OpenFlags uint32
}
// MountOptions contains time out options for a (Node)FileSystem. The
// default copied from libfuse and set in NewMountOptions() is
// (1s,1s,0s).
type FileSystemOptions struct {
EntryTimeout time.Duration
AttrTimeout time.Duration
NegativeTimeout time.Duration
// If set, replace all uids with given UID.
// NewFileSystemOptions() will set this to the daemon's
// uid/gid.
*Owner
// If set, use a more portable, but slower inode number
// generation scheme. This will make inode numbers (exported
// back to callers) stay within int32, which is necessary for
// making stat() succeed in 32-bit programs.
PortableInodes bool
}
type MountOptions struct { type MountOptions struct {
AllowOther bool AllowOther bool
...@@ -275,7 +120,7 @@ type RawFileSystem interface { ...@@ -275,7 +120,7 @@ type RawFileSystem interface {
FsyncDir(context *Context, input *raw.FsyncIn) (code Status) FsyncDir(context *Context, input *raw.FsyncIn) (code Status)
// //
StatFs(out *StatfsOut, context *Context) (code Status) StatFs(out *raw.StatfsOut, context *Context) (code Status)
// Provide callbacks for pushing notifications to the kernel. // Provide callbacks for pushing notifications to the kernel.
Init(params *RawFsInit) Init(params *RawFsInit)
......
...@@ -2,13 +2,13 @@ package fuse ...@@ -2,13 +2,13 @@ package fuse
import ( import (
"fmt" "fmt"
"log"
"strings" "strings"
"sync" "sync"
"unsafe" "unsafe"
) )
var _ = log.Println
var paranoia bool
type BufferPool interface { type BufferPool interface {
AllocBuffer(size uint32) []byte AllocBuffer(size uint32) []byte
......
package fuse
import (
"time"
)
// NewDefaultNodeFileSystem returns a dummy implementation of
// NodeFileSystem, for embedding in structs.
func NewDefaultNodeFileSystem() NodeFileSystem {
return (*defaultNodeFileSystem)(nil)
}
type defaultNodeFileSystem struct {
}
func (fs *defaultNodeFileSystem) OnUnmount() {
}
func (fs *defaultNodeFileSystem) OnMount(conn *FileSystemConnector) {
}
func (fs *defaultNodeFileSystem) Root() FsNode {
return NewDefaultFsNode()
}
func (fs *defaultNodeFileSystem) String() string {
return "defaultNodeFileSystem"
}
func (fs *defaultNodeFileSystem) SetDebug(dbg bool) {
}
// NewDefaultFsNode returns an implementation of FsNode that returns
// ENOSYS for all operations.
func NewDefaultFsNode() FsNode {
return &defaultFsNode{}
}
type defaultFsNode struct {
inode *Inode
}
func (n *defaultFsNode) StatFs() *StatfsOut {
return nil
}
func (n *defaultFsNode) SetInode(node *Inode) {
n.inode = node
}
func (n *defaultFsNode) Deletable() bool {
return true
}
func (n *defaultFsNode) Inode() *Inode {
return n.inode
}
func (n *defaultFsNode) OnForget() {
}
func (n *defaultFsNode) Lookup(out *Attr, name string, context *Context) (node FsNode, code Status) {
return nil, ENOENT
}
func (n *defaultFsNode) Access(mode uint32, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Readlink(c *Context) ([]byte, Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) Mknod(name string, mode uint32, dev uint32, context *Context) (newNode FsNode, code Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) Mkdir(name string, mode uint32, context *Context) (newNode FsNode, code Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) Unlink(name string, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Rmdir(name string, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Symlink(name string, content string, context *Context) (newNode FsNode, code Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) Rename(oldName string, newParent FsNode, newName string, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Link(name string, existing FsNode, context *Context) (newNode FsNode, code Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) Create(name string, flags uint32, mode uint32, context *Context) (file File, newNode FsNode, code Status) {
return nil, nil, ENOSYS
}
func (n *defaultFsNode) Open(flags uint32, context *Context) (file File, code Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) Flush(file File, openFlags uint32, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) OpenDir(context *Context) ([]DirEntry, Status) {
ch := n.Inode().Children()
s := make([]DirEntry, 0, len(ch))
for name, child := range ch {
var a Attr
code := child.FsNode().GetAttr(&a, nil, context)
if code.Ok() {
s = append(s, DirEntry{Name: name, Mode: a.Mode})
}
}
return s, OK
}
func (n *defaultFsNode) GetXAttr(attribute string, context *Context) (data []byte, code Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) RemoveXAttr(attr string, context *Context) Status {
return ENOSYS
}
func (n *defaultFsNode) SetXAttr(attr string, data []byte, flags int, context *Context) Status {
return ENOSYS
}
func (n *defaultFsNode) ListXAttr(context *Context) (attrs []string, code Status) {
return nil, ENOSYS
}
func (n *defaultFsNode) GetAttr(out *Attr, file File, context *Context) (code Status) {
if n.Inode().IsDir() {
out.Mode = S_IFDIR | 0755
} else {
out.Mode = S_IFREG | 0644
}
return OK
}
func (n *defaultFsNode) Chmod(file File, perms uint32, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Chown(file File, uid uint32, gid uint32, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Truncate(file File, size uint64, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Utimens(file File, atime *time.Time, mtime *time.Time, context *Context) (code Status) {
return ENOSYS
}
func (n *defaultFsNode) Fallocate(file File, off uint64, size uint64, mode uint32, context *Context) (code Status) {
return ENOSYS
}
...@@ -25,7 +25,7 @@ func (fs *defaultRawFileSystem) String() string { ...@@ -25,7 +25,7 @@ func (fs *defaultRawFileSystem) String() string {
func (fs *defaultRawFileSystem) SetDebug(dbg bool) { func (fs *defaultRawFileSystem) SetDebug(dbg bool) {
} }
func (fs *defaultRawFileSystem) StatFs(out *StatfsOut, context *Context) Status { func (fs *defaultRawFileSystem) StatFs(out *raw.StatfsOut, context *Context) Status {
return ENOSYS return ENOSYS
} }
......
...@@ -24,17 +24,20 @@ type DirEntry struct { ...@@ -24,17 +24,20 @@ type DirEntry struct {
type DirEntryList struct { type DirEntryList struct {
buf []byte buf []byte
size int size int
offset uint64
// TODO - hide this again.
Offset uint64
} }
func NewDirEntryList(data []byte, off uint64) *DirEntryList { func NewDirEntryList(data []byte, off uint64) *DirEntryList {
return &DirEntryList{ return &DirEntryList{
buf: data[:0], buf: data[:0],
size: len(data), size: len(data),
offset: off, Offset: off,
} }
} }
// AddDirEntry tries to add an entry.
func (l *DirEntryList) AddDirEntry(e DirEntry) bool { func (l *DirEntryList) AddDirEntry(e DirEntry) bool {
return l.Add(e.Name, uint64(raw.FUSE_UNKNOWN_INO), e.Mode) return l.Add(e.Name, uint64(raw.FUSE_UNKNOWN_INO), e.Mode)
} }
...@@ -50,7 +53,7 @@ func (l *DirEntryList) Add(name string, inode uint64, mode uint32) bool { ...@@ -50,7 +53,7 @@ func (l *DirEntryList) Add(name string, inode uint64, mode uint32) bool {
} }
l.buf = l.buf[:newLen] l.buf = l.buf[:newLen]
dirent := (*raw.Dirent)(unsafe.Pointer(&l.buf[oldLen])) dirent := (*raw.Dirent)(unsafe.Pointer(&l.buf[oldLen]))
dirent.Off = l.offset + 1 dirent.Off = l.Offset + 1
dirent.Ino = inode dirent.Ino = inode
dirent.NameLen = uint32(len(name)) dirent.NameLen = uint32(len(name))
dirent.Typ = ModeToType(mode) dirent.Typ = ModeToType(mode)
...@@ -62,7 +65,7 @@ func (l *DirEntryList) Add(name string, inode uint64, mode uint32) bool { ...@@ -62,7 +65,7 @@ func (l *DirEntryList) Add(name string, inode uint64, mode uint32) bool {
copy(l.buf[oldLen:], eightPadding[:padding]) copy(l.buf[oldLen:], eightPadding[:padding])
} }
l.offset = dirent.Off l.Offset = dirent.Off
return true return true
} }
...@@ -72,44 +75,4 @@ func (l *DirEntryList) Bytes() []byte { ...@@ -72,44 +75,4 @@ func (l *DirEntryList) Bytes() []byte {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
type rawDir interface {
ReadDir(out *DirEntryList, input *raw.ReadIn) Status
Release()
}
type connectorDir struct {
node FsNode
stream []DirEntry
lastOffset uint64
}
func (d *connectorDir) ReadDir(list *DirEntryList, input *raw.ReadIn) (code Status) {
if d.stream == nil {
return OK
}
// rewinddir() should be as if reopening directory.
// TODO - test this.
if d.lastOffset > 0 && input.Offset == 0 {
d.stream, code = d.node.OpenDir(nil)
if !code.Ok() {
return code
}
}
todo := d.stream[input.Offset:]
for _, e := range todo {
if e.Name == "" {
log.Printf("got emtpy directory entry, mode %o.", e.Mode)
continue
}
if !list.AddDirEntry(e) {
break
}
}
d.lastOffset = list.offset
return OK
}
// Read everything so we make goroutines exit.
func (d *connectorDir) Release() {
}
...@@ -189,7 +189,7 @@ func (fs *lockingRawFileSystem) Init(params *RawFsInit) { ...@@ -189,7 +189,7 @@ func (fs *lockingRawFileSystem) Init(params *RawFsInit) {
fs.RawFS.Init(params) fs.RawFS.Init(params)
} }
func (fs *lockingRawFileSystem) StatFs(out *StatfsOut, context *Context) (code Status) { func (fs *lockingRawFileSystem) StatFs(out *raw.StatfsOut, context *Context) (code Status) {
defer fs.locked()() defer fs.locked()()
return fs.RawFS.StatFs(out, context) return fs.RawFS.StatFs(out, context)
} }
......
package fuse
import (
"syscall"
)
func (fs *LoopbackFileSystem) StatFs(name string) *StatfsOut {
s := syscall.Statfs_t{}
err := syscall.Statfs(fs.GetPath(name), &s)
if err == nil {
return &StatfsOut{
Blocks: s.Blocks,
Bsize: uint32(s.Bsize),
Bfree: s.Bfree,
Bavail: s.Bavail,
Files: s.Files,
Ffree: s.Ffree,
}
}
return nil
}
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"os" "os"
"reflect" "reflect"
"syscall" "syscall"
"time"
"unsafe" "unsafe"
) )
...@@ -61,12 +60,6 @@ func ToStatus(err error) Status { ...@@ -61,12 +60,6 @@ func ToStatus(err error) Status {
return ENOSYS return ENOSYS
} }
func splitDuration(dt time.Duration, secs *uint64, nsecs *uint32) {
ns := int64(dt)
*nsecs = uint32(ns % 1e9)
*secs = uint64(ns / 1e9)
}
func ModeToType(mode uint32) uint32 { func ModeToType(mode uint32) uint32 {
return (mode & 0170000) >> 12 return (mode & 0170000) >> 12
} }
......
package nodefs
import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw"
)
type StatfsOut raw.StatfsOut
// FileSystem is a high level API that resembles the kernel's idea
// of what an FS looks like. FileSystems can have multiple
// hard-links to one file, for example. It is also suited if the data
// to represent fits in memory: you can construct Node at mount
// time, and the filesystem will be ready.
type FileSystem interface {
// OnUnmount is executed just before a submount is removed,
// and when the process receives a forget for the FUSE root
// node.
OnUnmount()
// OnMount is called just after a mount is executed, either
// when the root is mounted, or when other filesystem are
// mounted in-process. The passed-in FileSystemConnector gives
// access to Notify methods and Debug settings.
OnMount(conn *FileSystemConnector)
// Root should return the inode for root of this file system.
Root() Node
// Used for debug outputs
String() string
// If called, provide debug output through the log package.
SetDebug(debug bool)
}
// The Node implements the basic functionality of inodes; this is
// where the majority of the FS code for a typical filesystem will be.
type Node interface {
// Inode and SetInode are basic getter/setters. They are
// called by the FileSystemConnector. You get them for free by
// embedding the result of NewDefaultNode() in your node
// struct.
Inode() *Inode
SetInode(node *Inode)
// Lookup finds a child node to this node; it is only called
// for directory Nodes.
Lookup(out *fuse.Attr, name string, context *fuse.Context) (node Node, code fuse.Status)
// Deletable() should return true if this inode may be
// discarded from the children list. This will be called from
// within the treeLock critical section, so you cannot look at
// other inodes.
Deletable() bool
// OnForget is called when the reference to this inode is
// dropped from the tree.
OnForget()
// Misc.
Access(mode uint32, context *fuse.Context) (code fuse.Status)
Readlink(c *fuse.Context) ([]byte, fuse.Status)
// Namespace operations; these are only called on directory Nodes.
Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (newNode Node, code fuse.Status)
Mkdir(name string, mode uint32, context *fuse.Context) (newNode Node, code fuse.Status)
Unlink(name string, context *fuse.Context) (code fuse.Status)
Rmdir(name string, context *fuse.Context) (code fuse.Status)
Symlink(name string, content string, context *fuse.Context) (newNode Node, code fuse.Status)
Rename(oldName string, newParent Node, newName string, context *fuse.Context) (code fuse.Status)
Link(name string, existing Node, context *fuse.Context) (newNode Node, code fuse.Status)
// Files
Create(name string, flags uint32, mode uint32, context *fuse.Context) (file File, newNode Node, code fuse.Status)
Open(flags uint32, context *fuse.Context) (file File, code fuse.Status)
OpenDir(context *fuse.Context) ([]fuse.DirEntry, fuse.Status)
// XAttrs
GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status)
RemoveXAttr(attr string, context *fuse.Context) fuse.Status
SetXAttr(attr string, data []byte, flags int, context *fuse.Context) fuse.Status
ListXAttr(context *fuse.Context) (attrs []string, code fuse.Status)
// Attributes
GetAttr(out *fuse.Attr, file File, context *fuse.Context) (code fuse.Status)
Chmod(file File, perms uint32, context *fuse.Context) (code fuse.Status)
Chown(file File, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status)
Truncate(file File, size uint64, context *fuse.Context) (code fuse.Status)
Utimens(file File, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status)
Fallocate(file File, off uint64, size uint64, mode uint32, context *fuse.Context) (code fuse.Status)
StatFs() *StatfsOut
}
// A File object should be returned from FileSystem.Open and
// FileSystem.Create. Include the NewDefaultFile return value into
// the struct to inherit a default null implementation.
//
// TODO - should File be thread safe?
// TODO - should we pass a *fuse.Context argument?
type File interface {
// Called upon registering the filehandle in the inode.
SetInode(*Inode)
// The String method is for debug printing.
String() string
// Wrappers around other File implementations, should return
// the inner file here.
InnerFile() File
Read(dest []byte, off int64) (fuse.ReadResult, fuse.Status)
Write(data []byte, off int64) (written uint32, code fuse.Status)
Flush() fuse.Status
Release()
Fsync(flags int) (code fuse.Status)
// The methods below may be called on closed files, due to
// concurrency. In that case, you should return EBADF.
Truncate(size uint64) fuse.Status
GetAttr(out *fuse.Attr) fuse.Status
Chown(uid uint32, gid uint32) fuse.Status
Chmod(perms uint32) fuse.Status
Utimens(atime *time.Time, mtime *time.Time) fuse.Status
Allocate(off uint64, size uint64, mode uint32) (code fuse.Status)
}
// Wrap a File return in this to set FUSE flags. Also used internally
// to store open file data.
type WithFlags struct {
File
// For debugging.
Description string
// Put FOPEN_* flags here.
FuseFlags uint32
// O_RDWR, O_TRUNCATE, etc.
OpenFlags uint32
}
// Options contains time out options for a node FileSystem. The
// default copied from libfuse and set in NewMountOptions() is
// (1s,1s,0s).
type Options struct {
EntryTimeout time.Duration
AttrTimeout time.Duration
NegativeTimeout time.Duration
// If set, replace all uids with given UID.
// NewFileSystemOptions() will set this to the daemon's
// uid/gid.
*fuse.Owner
// If set, use a more portable, but slower inode number
// generation scheme. This will make inode numbers (exported
// back to callers) stay within int32, which is necessary for
// making stat() succeed in 32-bit programs.
PortableInodes bool
}
package fuse package nodefs
import ( import (
"time" "time"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
) )
type defaultFile struct{} type defaultFile struct{}
...@@ -25,50 +26,50 @@ func (f *defaultFile) String() string { ...@@ -25,50 +26,50 @@ func (f *defaultFile) String() string {
return "defaultFile" return "defaultFile"
} }
func (f *defaultFile) Read(buf []byte, off int64) (ReadResult, Status) { func (f *defaultFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
return nil, ENOSYS return nil, fuse.ENOSYS
} }
func (f *defaultFile) Write(data []byte, off int64) (uint32, Status) { func (f *defaultFile) Write(data []byte, off int64) (uint32, fuse.Status) {
return 0, ENOSYS return 0, fuse.ENOSYS
} }
func (f *defaultFile) Flush() Status { func (f *defaultFile) Flush() fuse.Status {
return OK return fuse.OK
} }
func (f *defaultFile) Release() { func (f *defaultFile) Release() {
} }
func (f *defaultFile) GetAttr(*Attr) Status { func (f *defaultFile) GetAttr(*fuse.Attr) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (f *defaultFile) Fsync(flags int) (code Status) { func (f *defaultFile) Fsync(flags int) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
func (f *defaultFile) Utimens(atime *time.Time, mtime *time.Time) Status { func (f *defaultFile) Utimens(atime *time.Time, mtime *time.Time) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (f *defaultFile) Truncate(size uint64) Status { func (f *defaultFile) Truncate(size uint64) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (f *defaultFile) Chown(uid uint32, gid uint32) Status { func (f *defaultFile) Chown(uid uint32, gid uint32) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (f *defaultFile) Chmod(perms uint32) Status { func (f *defaultFile) Chmod(perms uint32) fuse.Status {
return ENOSYS return fuse.ENOSYS
} }
func (f *defaultFile) Ioctl(input *raw.IoctlIn) (output *raw.IoctlOut, data []byte, code Status) { func (f *defaultFile) Ioctl(input *raw.IoctlIn) (output *raw.IoctlOut, data []byte, code fuse.Status) {
return nil, nil, ENOSYS return nil, nil, fuse.ENOSYS
} }
func (f *defaultFile) Allocate(off uint64, size uint64, mode uint32) (code Status) { func (f *defaultFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) {
return ENOSYS return fuse.ENOSYS
} }
package nodefs
import (
"time"
"github.com/hanwen/go-fuse/fuse"
)
// NewDefaultNodeFileSystem returns a dummy implementation of
// NodeFileSystem, for embedding in structs.
func NewDefaultFileSystem() FileSystem {
return (*defaultFileSystem)(nil)
}
type defaultFileSystem struct {
}
func (fs *defaultFileSystem) OnUnmount() {
}
func (fs *defaultFileSystem) OnMount(conn *FileSystemConnector) {
}
func (fs *defaultFileSystem) Root() Node {
return NewDefaultNode()
}
func (fs *defaultFileSystem) String() string {
return "defaultFileSystem"
}
func (fs *defaultFileSystem) SetDebug(dbg bool) {
}
// NewDefaultNode returns an implementation of Node that returns
// ENOSYS for all operations.
func NewDefaultNode() Node {
return &defaultNode{}
}
type defaultNode struct {
inode *Inode
}
func (n *defaultNode) StatFs() *StatfsOut {
return nil
}
func (n *defaultNode) SetInode(node *Inode) {
n.inode = node
}
func (n *defaultNode) Deletable() bool {
return true
}
func (n *defaultNode) Inode() *Inode {
return n.inode
}
func (n *defaultNode) OnForget() {
}
func (n *defaultNode) Lookup(out *fuse.Attr, name string, context *fuse.Context) (node Node, code fuse.Status) {
return nil, fuse.ENOENT
}
func (n *defaultNode) Access(mode uint32, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Readlink(c *fuse.Context) ([]byte, fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (newNode Node, code fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) Mkdir(name string, mode uint32, context *fuse.Context) (newNode Node, code fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) Unlink(name string, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Symlink(name string, content string, context *fuse.Context) (newNode Node, code fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) Rename(oldName string, newParent Node, newName string, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Link(name string, existing Node, context *fuse.Context) (newNode Node, code fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file File, newNode Node, code fuse.Status) {
return nil, nil, fuse.ENOSYS
}
func (n *defaultNode) Open(flags uint32, context *fuse.Context) (file File, code fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) Flush(file File, openFlags uint32, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) OpenDir(context *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
ch := n.Inode().Children()
s := make([]fuse.DirEntry, 0, len(ch))
for name, child := range ch {
var a fuse.Attr
code := child.Node().GetAttr(&a, nil, context)
if code.Ok() {
s = append(s, fuse.DirEntry{Name: name, Mode: a.Mode})
}
}
return s, fuse.OK
}
func (n *defaultNode) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) RemoveXAttr(attr string, context *fuse.Context) fuse.Status {
return fuse.ENOSYS
}
func (n *defaultNode) SetXAttr(attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
return fuse.ENOSYS
}
func (n *defaultNode) ListXAttr(context *fuse.Context) (attrs []string, code fuse.Status) {
return nil, fuse.ENOSYS
}
func (n *defaultNode) GetAttr(out *fuse.Attr, file File, context *fuse.Context) (code fuse.Status) {
if n.Inode().IsDir() {
out.Mode = fuse.S_IFDIR | 0755
} else {
out.Mode = fuse.S_IFREG | 0644
}
return fuse.OK
}
func (n *defaultNode) Chmod(file File, perms uint32, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Chown(file File, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Truncate(file File, size uint64, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Utimens(file File, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
func (n *defaultNode) Fallocate(file File, off uint64, size uint64, mode uint32, context *fuse.Context) (code fuse.Status) {
return fuse.ENOSYS
}
package nodefs
import (
"log"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
)
type connectorDir struct {
node Node
stream []fuse.DirEntry
lastOffset uint64
}
func (d *connectorDir) ReadDir(list *fuse.DirEntryList, input *raw.ReadIn) (code fuse.Status) {
if d.stream == nil {
return fuse.OK
}
// rewinddir() should be as if reopening directory.
// TODO - test this.
if d.lastOffset > 0 && input.Offset == 0 {
d.stream, code = d.node.OpenDir(nil)
if !code.Ok() {
return code
}
}
todo := d.stream[input.Offset:]
for _, e := range todo {
if e.Name == "" {
log.Printf("got emtpy directory entry, mode %o.", e.Mode)
continue
}
if !list.AddDirEntry(e) {
break
}
}
d.lastOffset = list.Offset
return fuse.OK
}
// Read everything so we make goroutines exit.
func (d *connectorDir) Release() {
}
type rawDir interface {
ReadDir(out *fuse.DirEntryList, input *raw.ReadIn) fuse.Status
Release()
}
package fuse package nodefs
import ( import (
"fmt" "fmt"
"os" "os"
"sync" "sync"
"syscall" "syscall"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = fmt.Println var _ = fmt.Println
...@@ -28,10 +30,10 @@ func (f *dataFile) String() string { ...@@ -28,10 +30,10 @@ func (f *dataFile) String() string {
return fmt.Sprintf("dataFile(%x)", f.data[:l]) return fmt.Sprintf("dataFile(%x)", f.data[:l])
} }
func (f *dataFile) GetAttr(out *Attr) Status { func (f *dataFile) GetAttr(out *fuse.Attr) fuse.Status {
out.Mode = S_IFREG | 0644 out.Mode = fuse.S_IFREG | 0644
out.Size = uint64(len(f.data)) out.Size = uint64(len(f.data))
return OK return fuse.OK
} }
func NewDataFile(data []byte) File { func NewDataFile(data []byte) File {
...@@ -41,13 +43,13 @@ func NewDataFile(data []byte) File { ...@@ -41,13 +43,13 @@ func NewDataFile(data []byte) File {
return f return f
} }
func (f *dataFile) Read(buf []byte, off int64) (res ReadResult, code Status) { func (f *dataFile) Read(buf []byte, off int64) (res fuse.ReadResult, code fuse.Status) {
end := int(off) + int(len(buf)) end := int(off) + int(len(buf))
if end > len(f.data) { if end > len(f.data) {
end = len(f.data) end = len(f.data)
} }
return &ReadResultData{f.data[off:end]}, OK return &fuse.ReadResultData{f.data[off:end]}, fuse.OK
} }
//////////////// ////////////////
...@@ -64,32 +66,32 @@ func NewDevNullFile() File { ...@@ -64,32 +66,32 @@ func NewDevNullFile() File {
} }
} }
func (f *devNullFile) Allocate(off uint64, size uint64, mode uint32) (code Status) { func (f *devNullFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) {
return OK return fuse.OK
} }
func (f *devNullFile) String() string { func (f *devNullFile) String() string {
return "devNullFile" return "devNullFile"
} }
func (f *devNullFile) Read(buf []byte, off int64) (ReadResult, Status) { func (f *devNullFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
return &ReadResultData{}, OK return &fuse.ReadResultData{}, fuse.OK
} }
func (f *devNullFile) Write(content []byte, off int64) (uint32, Status) { func (f *devNullFile) Write(content []byte, off int64) (uint32, fuse.Status) {
return uint32(len(content)), OK return uint32(len(content)), fuse.OK
} }
func (f *devNullFile) Flush() Status { func (f *devNullFile) Flush() fuse.Status {
return OK return fuse.OK
} }
func (f *devNullFile) Fsync(flags int) (code Status) { func (f *devNullFile) Fsync(flags int) (code fuse.Status) {
return OK return fuse.OK
} }
func (f *devNullFile) Truncate(size uint64) (code Status) { func (f *devNullFile) Truncate(size uint64) (code fuse.Status) {
return OK return fuse.OK
} }
//////////////// ////////////////
...@@ -124,22 +126,22 @@ func (f *loopbackFile) String() string { ...@@ -124,22 +126,22 @@ func (f *loopbackFile) String() string {
return fmt.Sprintf("loopbackFile(%s)", f.File.Name()) return fmt.Sprintf("loopbackFile(%s)", f.File.Name())
} }
func (f *loopbackFile) Read(buf []byte, off int64) (res ReadResult, code Status) { func (f *loopbackFile) Read(buf []byte, off int64) (res fuse.ReadResult, code fuse.Status) {
f.lock.Lock() f.lock.Lock()
r := &ReadResultFd{ r := &fuse.ReadResultFd{
Fd: f.File.Fd(), Fd: f.File.Fd(),
Off: off, Off: off,
Sz: len(buf), Sz: len(buf),
} }
f.lock.Unlock() f.lock.Unlock()
return r, OK return r, fuse.OK
} }
func (f *loopbackFile) Write(data []byte, off int64) (uint32, Status) { func (f *loopbackFile) Write(data []byte, off int64) (uint32, fuse.Status) {
f.lock.Lock() f.lock.Lock()
n, err := f.File.WriteAt(data, off) n, err := f.File.WriteAt(data, off)
f.lock.Unlock() f.lock.Unlock()
return uint32(n), ToStatus(err) return uint32(n), fuse.ToStatus(err)
} }
func (f *loopbackFile) Release() { func (f *loopbackFile) Release() {
...@@ -148,7 +150,7 @@ func (f *loopbackFile) Release() { ...@@ -148,7 +150,7 @@ func (f *loopbackFile) Release() {
f.lock.Unlock() f.lock.Unlock()
} }
func (f *loopbackFile) Flush() Status { func (f *loopbackFile) Flush() fuse.Status {
f.lock.Lock() f.lock.Lock()
// Since Flush() may be called for each dup'd fd, we don't // Since Flush() may be called for each dup'd fd, we don't
...@@ -158,55 +160,55 @@ func (f *loopbackFile) Flush() Status { ...@@ -158,55 +160,55 @@ func (f *loopbackFile) Flush() Status {
f.lock.Unlock() f.lock.Unlock()
if err != nil { if err != nil {
return ToStatus(err) return fuse.ToStatus(err)
} }
err = syscall.Close(newFd) err = syscall.Close(newFd)
return ToStatus(err) return fuse.ToStatus(err)
} }
func (f *loopbackFile) Fsync(flags int) (code Status) { func (f *loopbackFile) Fsync(flags int) (code fuse.Status) {
f.lock.Lock() f.lock.Lock()
r := ToStatus(syscall.Fsync(int(f.File.Fd()))) r := fuse.ToStatus(syscall.Fsync(int(f.File.Fd())))
f.lock.Unlock() f.lock.Unlock()
return r return r
} }
func (f *loopbackFile) Truncate(size uint64) Status { func (f *loopbackFile) Truncate(size uint64) fuse.Status {
f.lock.Lock() f.lock.Lock()
r := ToStatus(syscall.Ftruncate(int(f.File.Fd()), int64(size))) r := fuse.ToStatus(syscall.Ftruncate(int(f.File.Fd()), int64(size)))
f.lock.Unlock() f.lock.Unlock()
return r return r
} }
func (f *loopbackFile) Chmod(mode uint32) Status { func (f *loopbackFile) Chmod(mode uint32) fuse.Status {
f.lock.Lock() f.lock.Lock()
r := ToStatus(f.File.Chmod(os.FileMode(mode))) r := fuse.ToStatus(f.File.Chmod(os.FileMode(mode)))
f.lock.Unlock() f.lock.Unlock()
return r return r
} }
func (f *loopbackFile) Chown(uid uint32, gid uint32) Status { func (f *loopbackFile) Chown(uid uint32, gid uint32) fuse.Status {
f.lock.Lock() f.lock.Lock()
r := ToStatus(f.File.Chown(int(uid), int(gid))) r := fuse.ToStatus(f.File.Chown(int(uid), int(gid)))
f.lock.Unlock() f.lock.Unlock()
return r return r
} }
func (f *loopbackFile) GetAttr(a *Attr) Status { func (f *loopbackFile) GetAttr(a *fuse.Attr) fuse.Status {
st := syscall.Stat_t{} st := syscall.Stat_t{}
f.lock.Lock() f.lock.Lock()
err := syscall.Fstat(int(f.File.Fd()), &st) err := syscall.Fstat(int(f.File.Fd()), &st)
f.lock.Unlock() f.lock.Unlock()
if err != nil { if err != nil {
return ToStatus(err) return fuse.ToStatus(err)
} }
a.FromStat(&st) a.FromStat(&st)
return OK return fuse.OK
} }
// Allocate, Utimens implemented in files_linux.go // Allocate, Utimens implemented in files_linux.go
...@@ -228,26 +230,26 @@ func (f *readOnlyFile) String() string { ...@@ -228,26 +230,26 @@ func (f *readOnlyFile) String() string {
return fmt.Sprintf("readOnlyFile(%s)", f.File.String()) return fmt.Sprintf("readOnlyFile(%s)", f.File.String())
} }
func (f *readOnlyFile) Write(data []byte, off int64) (uint32, Status) { func (f *readOnlyFile) Write(data []byte, off int64) (uint32, fuse.Status) {
return 0, EPERM return 0, fuse.EPERM
} }
func (f *readOnlyFile) Fsync(flag int) (code Status) { func (f *readOnlyFile) Fsync(flag int) (code fuse.Status) {
return OK return fuse.OK
} }
func (f *readOnlyFile) Truncate(size uint64) Status { func (f *readOnlyFile) Truncate(size uint64) fuse.Status {
return EPERM return fuse.EPERM
} }
func (f *readOnlyFile) Chmod(mode uint32) Status { func (f *readOnlyFile) Chmod(mode uint32) fuse.Status {
return EPERM return fuse.EPERM
} }
func (f *readOnlyFile) Chown(uid uint32, gid uint32) Status { func (f *readOnlyFile) Chown(uid uint32, gid uint32) fuse.Status {
return EPERM return fuse.EPERM
} }
func (f *readOnlyFile) Allocate(off uint64, sz uint64, mode uint32) Status { func (f *readOnlyFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status {
return EPERM return fuse.EPERM
} }
package fuse package nodefs
import ( import (
"time" "time"
"syscall" "syscall"
"github.com/hanwen/go-fuse/fuse"
) )
func (f *loopbackFile) Allocate(off uint64, sz uint64, mode uint32) Status { func (f *loopbackFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status {
f.lock.Lock() f.lock.Lock()
err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz)) err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz))
f.lock.Unlock() f.lock.Unlock()
if err != nil { if err != nil {
return ToStatus(err) return fuse.ToStatus(err)
} }
return OK return fuse.OK
} }
const _UTIME_NOW = ((1 << 30) - 1) const _UTIME_NOW = ((1 << 30) - 1)
const _UTIME_OMIT = ((1 << 30) - 2) const _UTIME_OMIT = ((1 << 30) - 2)
func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) Status { func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
tv := make([]syscall.Timeval, 2) tv := make([]syscall.Timeval, 2)
if a == nil { if a == nil {
tv[0].Usec = _UTIME_OMIT tv[0].Usec = _UTIME_OMIT
...@@ -35,5 +37,5 @@ func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) Status { ...@@ -35,5 +37,5 @@ func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) Status {
} }
err := syscall.Futimes(int(f.File.Fd()), tv) err := syscall.Futimes(int(f.File.Fd()), tv)
return ToStatus(err) return fuse.ToStatus(err)
} }
package fuse package nodefs
// This file contains the internal logic of the // This file contains the internal logic of the
// FileSystemConnector. The functions for satisfying the raw interface // FileSystemConnector. The functions for satisfying the raw interface
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"unsafe" "unsafe"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
) )
// Tests should set to true. // Tests should set to true.
...@@ -35,9 +36,9 @@ type FileSystemConnector struct { ...@@ -35,9 +36,9 @@ type FileSystemConnector struct {
debug bool debug bool
// Callbacks for talking back to the kernel. // Callbacks for talking back to the kernel.
fsInit RawFsInit fsInit fuse.RawFsInit
nodeFs NodeFileSystem nodeFs FileSystem
// Translate between uint64 handles and *Inode. // Translate between uint64 handles and *Inode.
inodeMap handleMap inodeMap handleMap
...@@ -46,19 +47,19 @@ type FileSystemConnector struct { ...@@ -46,19 +47,19 @@ type FileSystemConnector struct {
rootNode *Inode rootNode *Inode
} }
func NewFileSystemOptions() *FileSystemOptions { func NewOptions() *Options {
return &FileSystemOptions{ return &Options{
NegativeTimeout: 0, NegativeTimeout: 0,
AttrTimeout: time.Second, AttrTimeout: time.Second,
EntryTimeout: time.Second, EntryTimeout: time.Second,
Owner: CurrentOwner(), Owner: fuse.CurrentOwner(),
} }
} }
func NewFileSystemConnector(nodeFs NodeFileSystem, opts *FileSystemOptions) (c *FileSystemConnector) { func NewFileSystemConnector(nodeFs FileSystem, opts *Options) (c *FileSystemConnector) {
c = new(FileSystemConnector) c = new(FileSystemConnector)
if opts == nil { if opts == nil {
opts = NewFileSystemOptions() opts = NewOptions()
} }
c.nodeFs = nodeFs c.nodeFs = nodeFs
c.inodeMap = newHandleMap(opts.PortableInodes) c.inodeMap = newHandleMap(opts.PortableInodes)
...@@ -95,9 +96,9 @@ func (c *FileSystemConnector) verify() { ...@@ -95,9 +96,9 @@ func (c *FileSystemConnector) verify() {
root.verify(c.rootNode.mountPoint) root.verify(c.rootNode.mountPoint)
} }
func (c *rawBridge) childLookup(out *raw.EntryOut, fsi FsNode) { func (c *rawBridge) childLookup(out *raw.EntryOut, fsi Node) {
n := fsi.Inode() n := fsi.Inode()
fsi.GetAttr((*Attr)(&out.Attr), nil, nil) fsi.GetAttr((*fuse.Attr)(&out.Attr), nil, nil)
n.mount.fillEntry(out) n.mount.fillEntry(out)
out.Ino = c.fsConn().lookupUpdate(n) out.Ino = c.fsConn().lookupUpdate(n)
out.NodeId = out.Ino out.NodeId = out.Ino
...@@ -167,7 +168,7 @@ func (c *FileSystemConnector) recursiveConsiderDropInode(n *Inode) (drop bool) { ...@@ -167,7 +168,7 @@ func (c *FileSystemConnector) recursiveConsiderDropInode(n *Inode) (drop bool) {
ch.fsInode.OnForget() ch.fsInode.OnForget()
} }
if len(n.children) > 0 || !n.FsNode().Deletable() { if len(n.children) > 0 || !n.Node().Deletable() {
return false return false
} }
if n == c.rootNode || n.mountPoint != nil { if n == c.rootNode || n.mountPoint != nil {
...@@ -228,7 +229,7 @@ func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode { ...@@ -228,7 +229,7 @@ func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode {
} }
components := strings.Split(path, "/") components := strings.Split(path, "/")
for _, r := range components { for _, r := range components {
var a Attr var a fuse.Attr
child, _ := c.internalLookup(&a, parent, r, nil) child, _ := c.internalLookup(&a, parent, r, nil)
if child == nil { if child == nil {
return nil return nil
...@@ -242,7 +243,7 @@ func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode { ...@@ -242,7 +243,7 @@ func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
func (c *FileSystemConnector) MountRoot(nodeFs NodeFileSystem, opts *FileSystemOptions) { func (c *FileSystemConnector) MountRoot(nodeFs FileSystem, opts *Options) {
c.rootNode.mountFs(nodeFs, opts) c.rootNode.mountFs(nodeFs, opts)
c.rootNode.mount.connector = c c.rootNode.mount.connector = c
nodeFs.OnMount(c) nodeFs.OnMount(c)
...@@ -260,13 +261,13 @@ func (c *FileSystemConnector) MountRoot(nodeFs NodeFileSystem, opts *FileSystemO ...@@ -260,13 +261,13 @@ func (c *FileSystemConnector) MountRoot(nodeFs NodeFileSystem, opts *FileSystemO
// ENOENT: the directory containing the mount point does not exist. // ENOENT: the directory containing the mount point does not exist.
// //
// EBUSY: the intended mount point already exists. // EBUSY: the intended mount point already exists.
func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFileSystem, opts *FileSystemOptions) Status { func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs FileSystem, opts *Options) fuse.Status {
defer c.verify() defer c.verify()
parent.mount.treeLock.Lock() parent.mount.treeLock.Lock()
defer parent.mount.treeLock.Unlock() defer parent.mount.treeLock.Unlock()
node := parent.children[name] node := parent.children[name]
if node != nil { if node != nil {
return EBUSY return fuse.EBUSY
} }
node = newInode(true, nodeFs.Root()) node = newInode(true, nodeFs.Root())
...@@ -284,7 +285,7 @@ func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFileS ...@@ -284,7 +285,7 @@ func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFileS
"parent", c.inodeMap.Handle(&parent.handled)) "parent", c.inodeMap.Handle(&parent.handled))
} }
nodeFs.OnMount(c) nodeFs.OnMount(c)
return OK return fuse.OK
} }
// Unmount() tries to unmount the given inode. // Unmount() tries to unmount the given inode.
...@@ -294,11 +295,11 @@ func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFileS ...@@ -294,11 +295,11 @@ func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFileS
// EINVAL: path does not exist, or is not a mount point. // EINVAL: path does not exist, or is not a mount point.
// //
// EBUSY: there are open files, or submounts below this node. // EBUSY: there are open files, or submounts below this node.
func (c *FileSystemConnector) Unmount(node *Inode) Status { func (c *FileSystemConnector) Unmount(node *Inode) fuse.Status {
// TODO - racy. // TODO - racy.
if node.mountPoint == nil { if node.mountPoint == nil {
log.Println("not a mountpoint:", c.inodeMap.Handle(&node.handled)) log.Println("not a mountpoint:", c.inodeMap.Handle(&node.handled))
return EINVAL return fuse.EINVAL
} }
nodeId := c.inodeMap.Handle(&node.handled) nodeId := c.inodeMap.Handle(&node.handled)
...@@ -311,7 +312,7 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status { ...@@ -311,7 +312,7 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
mount := node.mountPoint mount := node.mountPoint
name := node.mountPoint.mountName() name := node.mountPoint.mountName()
if mount.openFiles.Count() > 0 { if mount.openFiles.Count() > 0 {
return EBUSY return fuse.EBUSY
} }
node.mount.treeLock.Lock() node.mount.treeLock.Lock()
...@@ -324,7 +325,7 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status { ...@@ -324,7 +325,7 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
} }
if !node.canUnmount() { if !node.canUnmount() {
return EBUSY return fuse.EBUSY
} }
delete(parentNode.children, name) delete(parentNode.children, name)
...@@ -360,10 +361,10 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status { ...@@ -360,10 +361,10 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
mount.mountInode = nil mount.mountInode = nil
node.mountPoint = nil node.mountPoint = nil
return OK return fuse.OK
} }
func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) Status { func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) fuse.Status {
var nId uint64 var nId uint64
if node == c.rootNode { if node == c.rootNode {
nId = raw.FUSE_ROOT_ID nId = raw.FUSE_ROOT_ID
...@@ -372,7 +373,7 @@ func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) S ...@@ -372,7 +373,7 @@ func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) S
} }
if nId == 0 { if nId == 0 {
return OK return fuse.OK
} }
out := raw.NotifyInvalInodeOut{ out := raw.NotifyInvalInodeOut{
Length: length, Length: length,
...@@ -382,7 +383,7 @@ func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) S ...@@ -382,7 +383,7 @@ func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) S
return c.fsInit.InodeNotify(&out) return c.fsInit.InodeNotify(&out)
} }
func (c *FileSystemConnector) EntryNotify(node *Inode, name string) Status { func (c *FileSystemConnector) EntryNotify(node *Inode, name string) fuse.Status {
var nId uint64 var nId uint64
if node == c.rootNode { if node == c.rootNode {
nId = raw.FUSE_ROOT_ID nId = raw.FUSE_ROOT_ID
...@@ -391,12 +392,12 @@ func (c *FileSystemConnector) EntryNotify(node *Inode, name string) Status { ...@@ -391,12 +392,12 @@ func (c *FileSystemConnector) EntryNotify(node *Inode, name string) Status {
} }
if nId == 0 { if nId == 0 {
return OK return fuse.OK
} }
return c.fsInit.EntryNotify(nId, name) return c.fsInit.EntryNotify(nId, name)
} }
func (c *FileSystemConnector) DeleteNotify(dir *Inode, child *Inode, name string) Status { func (c *FileSystemConnector) DeleteNotify(dir *Inode, child *Inode, name string) fuse.Status {
var nId uint64 var nId uint64
if dir == c.rootNode { if dir == c.rootNode {
...@@ -406,7 +407,7 @@ func (c *FileSystemConnector) DeleteNotify(dir *Inode, child *Inode, name string ...@@ -406,7 +407,7 @@ func (c *FileSystemConnector) DeleteNotify(dir *Inode, child *Inode, name string
} }
if nId == 0 { if nId == 0 {
return OK return fuse.OK
} }
chId := c.inodeMap.Handle(&child.handled) chId := c.inodeMap.Handle(&child.handled)
......
package fuse package nodefs
import ( import (
"log" "log"
"sync" "sync"
"unsafe" "unsafe"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
...@@ -21,7 +22,7 @@ type openedFile struct { ...@@ -21,7 +22,7 @@ type openedFile struct {
type fileSystemMount struct { type fileSystemMount struct {
// The file system we mounted here. // The file system we mounted here.
fs NodeFileSystem fs FileSystem
// Node that we were mounted on. // Node that we were mounted on.
mountInode *Inode mountInode *Inode
...@@ -30,7 +31,7 @@ type fileSystemMount struct { ...@@ -30,7 +31,7 @@ type fileSystemMount struct {
parentInode *Inode parentInode *Inode
// Options for the mount. // Options for the mount.
options *FileSystemOptions options *Options
// Protects Children hashmaps within the mount. treeLock // Protects Children hashmaps within the mount. treeLock
// should be acquired before openFilesLock. // should be acquired before openFilesLock.
...@@ -68,7 +69,7 @@ func (m *fileSystemMount) fillEntry(out *raw.EntryOut) { ...@@ -68,7 +69,7 @@ func (m *fileSystemMount) fillEntry(out *raw.EntryOut) {
splitDuration(m.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec) splitDuration(m.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec)
splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec) splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
m.setOwner(&out.Attr) m.setOwner(&out.Attr)
if out.Mode&S_IFDIR == 0 && out.Nlink == 0 { if out.Mode&fuse.S_IFDIR == 0 && out.Nlink == 0 {
out.Nlink = 1 out.Nlink = 1
} }
} }
......
This diff is collapsed.
package fuse package nodefs
import "log" import (
"github.com/hanwen/go-fuse/fuse"
)
var _ = log.Println func MountFileSystem(mountpoint string, nodeFs FileSystem, opts *Options) (*fuse.MountState, *FileSystemConnector, error) {
func MountNodeFileSystem(mountpoint string, nodeFs NodeFileSystem, opts *FileSystemOptions) (*MountState, *FileSystemConnector, error) {
conn := NewFileSystemConnector(nodeFs, opts) conn := NewFileSystemConnector(nodeFs, opts)
mountState := NewMountState(conn.RawFS()) mountState := fuse.NewMountState(conn.RawFS())
err := mountState.Mount(mountpoint, nil) err := mountState.Mount(mountpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
......
package fuse package nodefs
import ( import (
"fmt" "fmt"
......
package fuse package nodefs
import ( import (
"log" "log"
......
package fuse package nodefs
import ( import (
"log" "log"
"sync" "sync"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = log.Println
// The inode reflects the kernel's idea of the inode. Inodes may be // The inode reflects the kernel's idea of the inode. Inodes may be
// created automatically when the kernel does lookups inode, or by // created automatically when the kernel does lookups inode, or by
...@@ -21,7 +22,7 @@ type Inode struct { ...@@ -21,7 +22,7 @@ type Inode struct {
openFilesMutex sync.Mutex openFilesMutex sync.Mutex
openFiles []*openedFile openFiles []*openedFile
fsInode FsNode fsInode Node
// Each inode belongs to exactly one fileSystemMount. This // Each inode belongs to exactly one fileSystemMount. This
// pointer is constant during the lifetime, except upon // pointer is constant during the lifetime, except upon
...@@ -36,7 +37,7 @@ type Inode struct { ...@@ -36,7 +37,7 @@ type Inode struct {
mountPoint *fileSystemMount mountPoint *fileSystemMount
} }
func newInode(isDir bool, fsNode FsNode) *Inode { func newInode(isDir bool, fsNode Node) *Inode {
me := new(Inode) me := new(Inode)
if isDir { if isDir {
me.children = make(map[string]*Inode, initDirSize) me.children = make(map[string]*Inode, initDirSize)
...@@ -52,7 +53,7 @@ func newInode(isDir bool, fsNode FsNode) *Inode { ...@@ -52,7 +53,7 @@ func newInode(isDir bool, fsNode FsNode) *Inode {
func (n *Inode) AnyFile() (file File) { func (n *Inode) AnyFile() (file File) {
n.openFilesMutex.Lock() n.openFilesMutex.Lock()
for _, f := range n.openFiles { for _, f := range n.openFiles {
if file == nil || f.WithFlags.OpenFlags&O_ANYWRITE != 0 { if file == nil || f.WithFlags.OpenFlags&fuse.O_ANYWRITE != 0 {
file = f.WithFlags.File file = f.WithFlags.File
} }
} }
...@@ -87,7 +88,7 @@ func (n *Inode) FsChildren() (out map[string]*Inode) { ...@@ -87,7 +88,7 @@ func (n *Inode) FsChildren() (out map[string]*Inode) {
return out return out
} }
func (n *Inode) FsNode() FsNode { func (n *Inode) Node() Node {
return n.fsInode return n.fsInode
} }
...@@ -108,7 +109,7 @@ func (n *Inode) IsDir() bool { ...@@ -108,7 +109,7 @@ func (n *Inode) IsDir() bool {
return n.children != nil return n.children != nil
} }
func (n *Inode) New(isDir bool, fsi FsNode) *Inode { func (n *Inode) New(isDir bool, fsi Node) *Inode {
ch := newInode(isDir, fsi) ch := newInode(isDir, fsi)
ch.mount = n.mount ch.mount = n.mount
n.generation = ch.mount.connector.nextGeneration() n.generation = ch.mount.connector.nextGeneration()
...@@ -163,7 +164,7 @@ func (n *Inode) rmChild(name string) (ch *Inode) { ...@@ -163,7 +164,7 @@ func (n *Inode) rmChild(name string) (ch *Inode) {
} }
// Can only be called on untouched inodes. // Can only be called on untouched inodes.
func (n *Inode) mountFs(fs NodeFileSystem, opts *FileSystemOptions) { func (n *Inode) mountFs(fs FileSystem, opts *Options) {
n.mountPoint = &fileSystemMount{ n.mountPoint = &fileSystemMount{
fs: fs, fs: fs,
openFiles: newHandleMap(false), openFiles: newHandleMap(false),
...@@ -192,13 +193,13 @@ func (n *Inode) canUnmount() bool { ...@@ -192,13 +193,13 @@ func (n *Inode) canUnmount() bool {
return ok return ok
} }
func (n *Inode) getMountDirEntries() (out []DirEntry) { func (n *Inode) getMountDirEntries() (out []fuse.DirEntry) {
n.mount.treeLock.RLock() n.mount.treeLock.RLock()
for k, v := range n.children { for k, v := range n.children {
if v.mountPoint != nil { if v.mountPoint != nil {
out = append(out, DirEntry{ out = append(out, fuse.DirEntry{
Name: k, Name: k,
Mode: S_IFDIR, Mode: fuse.S_IFDIR,
}) })
} }
} }
......
package fuse package nodefs
import ( import (
"fmt" "fmt"
...@@ -7,6 +7,8 @@ import ( ...@@ -7,6 +7,8 @@ import (
"sync" "sync"
"syscall" "syscall"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = log.Println var _ = log.Println
...@@ -23,7 +25,7 @@ func (fs *MemNodeFs) String() string { ...@@ -23,7 +25,7 @@ func (fs *MemNodeFs) String() string {
return fmt.Sprintf("MemNodeFs(%s)", fs.backingStorePrefix) return fmt.Sprintf("MemNodeFs(%s)", fs.backingStorePrefix)
} }
func (fs *MemNodeFs) Root() FsNode { func (fs *MemNodeFs) Root() Node {
return fs.root return fs.root
} }
...@@ -39,13 +41,13 @@ func (fs *MemNodeFs) OnUnmount() { ...@@ -39,13 +41,13 @@ func (fs *MemNodeFs) OnUnmount() {
func (fs *MemNodeFs) newNode() *memNode { func (fs *MemNodeFs) newNode() *memNode {
fs.mutex.Lock() fs.mutex.Lock()
n := &memNode{ n := &memNode{
FsNode: NewDefaultFsNode(), Node: NewDefaultNode(),
fs: fs, fs: fs,
id: fs.nextFree, id: fs.nextFree,
} }
now := time.Now() now := time.Now()
n.info.SetTimes(&now, &now, &now) n.info.SetTimes(&now, &now, &now)
n.info.Mode = S_IFDIR | 0777 n.info.Mode = fuse.S_IFDIR | 0777
fs.nextFree++ fs.nextFree++
fs.mutex.Unlock() fs.mutex.Unlock()
return n return n
...@@ -60,17 +62,17 @@ func NewMemNodeFs(prefix string) *MemNodeFs { ...@@ -60,17 +62,17 @@ func NewMemNodeFs(prefix string) *MemNodeFs {
} }
func (fs *MemNodeFs) Filename(n *Inode) string { func (fs *MemNodeFs) Filename(n *Inode) string {
mn := n.FsNode().(*memNode) mn := n.Node().(*memNode)
return mn.filename() return mn.filename()
} }
type memNode struct { type memNode struct {
FsNode Node
fs *MemNodeFs fs *MemNodeFs
id int id int
link string link string
info Attr info fuse.Attr
} }
func (n *memNode) newNode(isdir bool) *memNode { func (n *memNode) newNode(isdir bool) *memNode {
...@@ -87,60 +89,60 @@ func (n *memNode) Deletable() bool { ...@@ -87,60 +89,60 @@ func (n *memNode) Deletable() bool {
return false return false
} }
func (n *memNode) Readlink(c *Context) ([]byte, Status) { func (n *memNode) Readlink(c *fuse.Context) ([]byte, fuse.Status) {
return []byte(n.link), OK return []byte(n.link), fuse.OK
} }
func (n *memNode) Mkdir(name string, mode uint32, context *Context) (newNode FsNode, code Status) { func (n *memNode) Mkdir(name string, mode uint32, context *fuse.Context) (newNode Node, code fuse.Status) {
ch := n.newNode(true) ch := n.newNode(true)
ch.info.Mode = mode | S_IFDIR ch.info.Mode = mode | fuse.S_IFDIR
n.Inode().AddChild(name, ch.Inode()) n.Inode().AddChild(name, ch.Inode())
return ch, OK return ch, fuse.OK
} }
func (n *memNode) Unlink(name string, context *Context) (code Status) { func (n *memNode) Unlink(name string, context *fuse.Context) (code fuse.Status) {
ch := n.Inode().RmChild(name) ch := n.Inode().RmChild(name)
if ch == nil { if ch == nil {
return ENOENT return fuse.ENOENT
} }
return OK return fuse.OK
} }
func (n *memNode) Rmdir(name string, context *Context) (code Status) { func (n *memNode) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
return n.Unlink(name, context) return n.Unlink(name, context)
} }
func (n *memNode) Symlink(name string, content string, context *Context) (newNode FsNode, code Status) { func (n *memNode) Symlink(name string, content string, context *fuse.Context) (newNode Node, code fuse.Status) {
ch := n.newNode(false) ch := n.newNode(false)
ch.info.Mode = S_IFLNK | 0777 ch.info.Mode = fuse.S_IFLNK | 0777
ch.link = content ch.link = content
n.Inode().AddChild(name, ch.Inode()) n.Inode().AddChild(name, ch.Inode())
return ch, OK return ch, fuse.OK
} }
func (n *memNode) Rename(oldName string, newParent FsNode, newName string, context *Context) (code Status) { func (n *memNode) Rename(oldName string, newParent Node, newName string, context *fuse.Context) (code fuse.Status) {
ch := n.Inode().RmChild(oldName) ch := n.Inode().RmChild(oldName)
newParent.Inode().RmChild(newName) newParent.Inode().RmChild(newName)
newParent.Inode().AddChild(newName, ch) newParent.Inode().AddChild(newName, ch)
return OK return fuse.OK
} }
func (n *memNode) Link(name string, existing FsNode, context *Context) (newNode FsNode, code Status) { func (n *memNode) Link(name string, existing Node, context *fuse.Context) (newNode Node, code fuse.Status) {
n.Inode().AddChild(name, existing.Inode()) n.Inode().AddChild(name, existing.Inode())
return existing, code return existing, code
} }
func (n *memNode) Create(name string, flags uint32, mode uint32, context *Context) (file File, newNode FsNode, code Status) { func (n *memNode) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file File, newNode Node, code fuse.Status) {
ch := n.newNode(false) ch := n.newNode(false)
ch.info.Mode = mode | S_IFREG ch.info.Mode = mode | fuse.S_IFREG
f, err := os.Create(ch.filename()) f, err := os.Create(ch.filename())
if err != nil { if err != nil {
return nil, nil, ToStatus(err) return nil, nil, fuse.ToStatus(err)
} }
n.Inode().AddChild(name, ch.Inode()) n.Inode().AddChild(name, ch.Inode())
return ch.newFile(f), ch, OK return ch.newFile(f), ch, fuse.OK
} }
type memNodeFile struct { type memNodeFile struct {
...@@ -156,7 +158,7 @@ func (n *memNodeFile) InnerFile() File { ...@@ -156,7 +158,7 @@ func (n *memNodeFile) InnerFile() File {
return n.File return n.File
} }
func (n *memNodeFile) Flush() Status { func (n *memNodeFile) Flush() fuse.Status {
code := n.File.Flush() code := n.File.Flush()
if !code.Ok() { if !code.Ok() {
...@@ -167,7 +169,7 @@ func (n *memNodeFile) Flush() Status { ...@@ -167,7 +169,7 @@ func (n *memNodeFile) Flush() Status {
err := syscall.Stat(n.node.filename(), &st) err := syscall.Stat(n.node.filename(), &st)
n.node.info.Size = uint64(st.Size) n.node.info.Size = uint64(st.Size)
n.node.info.Blocks = uint64(st.Blocks) n.node.info.Blocks = uint64(st.Blocks)
return ToStatus(err) return fuse.ToStatus(err)
} }
func (n *memNode) newFile(f *os.File) File { func (n *memNode) newFile(f *os.File) File {
...@@ -177,26 +179,26 @@ func (n *memNode) newFile(f *os.File) File { ...@@ -177,26 +179,26 @@ func (n *memNode) newFile(f *os.File) File {
} }
} }
func (n *memNode) Open(flags uint32, context *Context) (file File, code Status) { func (n *memNode) Open(flags uint32, context *fuse.Context) (file File, code fuse.Status) {
f, err := os.OpenFile(n.filename(), int(flags), 0666) f, err := os.OpenFile(n.filename(), int(flags), 0666)
if err != nil { if err != nil {
return nil, ToStatus(err) return nil, fuse.ToStatus(err)
} }
return n.newFile(f), OK return n.newFile(f), fuse.OK
} }
func (n *memNode) GetAttr(fi *Attr, file File, context *Context) (code Status) { func (n *memNode) GetAttr(fi *fuse.Attr, file File, context *fuse.Context) (code fuse.Status) {
*fi = n.info *fi = n.info
return OK return fuse.OK
} }
func (n *memNode) Truncate(file File, size uint64, context *Context) (code Status) { func (n *memNode) Truncate(file File, size uint64, context *fuse.Context) (code fuse.Status) {
if file != nil { if file != nil {
code = file.Truncate(size) code = file.Truncate(size)
} else { } else {
err := os.Truncate(n.filename(), int64(size)) err := os.Truncate(n.filename(), int64(size))
code = ToStatus(err) code = fuse.ToStatus(err)
} }
if code.Ok() { if code.Ok() {
now := time.Now() now := time.Now()
...@@ -207,23 +209,23 @@ func (n *memNode) Truncate(file File, size uint64, context *Context) (code Statu ...@@ -207,23 +209,23 @@ func (n *memNode) Truncate(file File, size uint64, context *Context) (code Statu
return code return code
} }
func (n *memNode) Utimens(file File, atime *time.Time, mtime *time.Time, context *Context) (code Status) { func (n *memNode) Utimens(file File, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status) {
c := time.Now() c := time.Now()
n.info.SetTimes(atime, mtime, &c) n.info.SetTimes(atime, mtime, &c)
return OK return fuse.OK
} }
func (n *memNode) Chmod(file File, perms uint32, context *Context) (code Status) { func (n *memNode) Chmod(file File, perms uint32, context *fuse.Context) (code fuse.Status) {
n.info.Mode = (n.info.Mode ^ 07777) | perms n.info.Mode = (n.info.Mode ^ 07777) | perms
now := time.Now() now := time.Now()
n.info.SetTimes(nil, nil, &now) n.info.SetTimes(nil, nil, &now)
return OK return fuse.OK
} }
func (n *memNode) Chown(file File, uid uint32, gid uint32, context *Context) (code Status) { func (n *memNode) Chown(file File, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
n.info.Uid = uid n.info.Uid = uid
n.info.Gid = gid n.info.Gid = gid
now := time.Now() now := time.Now()
n.info.SetTimes(nil, nil, &now) n.info.SetTimes(nil, nil, &now)
return OK return fuse.OK
} }
package fuse package nodefs
import ( import (
"io/ioutil" "io/ioutil"
...@@ -6,6 +6,8 @@ import ( ...@@ -6,6 +6,8 @@ import (
"os" "os"
"testing" "testing"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
var _ = log.Println var _ = log.Println
...@@ -24,17 +26,17 @@ func setupMemNodeTest(t *testing.T) (wd string, fs *MemNodeFs, clean func()) { ...@@ -24,17 +26,17 @@ func setupMemNodeTest(t *testing.T) (wd string, fs *MemNodeFs, clean func()) {
os.Mkdir(mnt, 0700) os.Mkdir(mnt, 0700)
connector := NewFileSystemConnector(fs, connector := NewFileSystemConnector(fs,
&FileSystemOptions{ &Options{
EntryTimeout: testTtl, EntryTimeout: testTtl,
AttrTimeout: testTtl, AttrTimeout: testTtl,
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
}) })
connector.SetDebug(VerboseTest()) connector.SetDebug(fuse.VerboseTest())
state := NewMountState(connector.RawFS()) state := fuse.NewMountState(connector.RawFS())
state.Mount(mnt, nil) state.Mount(mnt, nil)
//me.state.SetDebug(false) //me.state.SetDebug(false)
state.SetDebug(VerboseTest()) state.SetDebug(fuse.VerboseTest())
// Unthreaded, but in background. // Unthreaded, but in background.
go state.Loop() go state.Loop()
......
package nodefs
import "time"
func splitDuration(dt time.Duration, secs *uint64, nsecs *uint32) {
ns := int64(dt)
*nsecs = uint32(ns % 1e9)
*secs = uint64(ns / 1e9)
}
package nodefs
import (
"fmt"
"github.com/hanwen/go-fuse/raw"
)
func (me *WithFlags) String() string {
return fmt.Sprintf("File %s (%s) %s %s",
me.File, me.Description, raw.FlagString(raw.OpenFlagNames, int64(me.OpenFlags), "O_RDONLY"),
raw.FlagString(raw.FuseOpenFlagNames, int64(me.FuseFlags), ""))
}
...@@ -327,7 +327,7 @@ func doRename(state *MountState, req *request) { ...@@ -327,7 +327,7 @@ func doRename(state *MountState, req *request) {
} }
func doStatFs(state *MountState, req *request) { func doStatFs(state *MountState, req *request) {
stat := (*StatfsOut)(req.outData) stat := (*raw.StatfsOut)(req.outData)
req.status = state.fileSystem.StatFs(stat, &req.context) req.status = state.fileSystem.StatFs(stat, &req.context)
} }
...@@ -431,7 +431,7 @@ func init() { ...@@ -431,7 +431,7 @@ func init() {
_OP_LINK: unsafe.Sizeof(raw.EntryOut{}), _OP_LINK: unsafe.Sizeof(raw.EntryOut{}),
_OP_OPEN: unsafe.Sizeof(raw.OpenOut{}), _OP_OPEN: unsafe.Sizeof(raw.OpenOut{}),
_OP_WRITE: unsafe.Sizeof(raw.WriteOut{}), _OP_WRITE: unsafe.Sizeof(raw.WriteOut{}),
_OP_STATFS: unsafe.Sizeof(StatfsOut{}), _OP_STATFS: unsafe.Sizeof(raw.StatfsOut{}),
_OP_GETXATTR: unsafe.Sizeof(raw.GetXAttrOut{}), _OP_GETXATTR: unsafe.Sizeof(raw.GetXAttrOut{}),
_OP_LISTXATTR: unsafe.Sizeof(raw.GetXAttrOut{}), _OP_LISTXATTR: unsafe.Sizeof(raw.GetXAttrOut{}),
_OP_INIT: unsafe.Sizeof(raw.InitOut{}), _OP_INIT: unsafe.Sizeof(raw.InitOut{}),
...@@ -549,7 +549,7 @@ func init() { ...@@ -549,7 +549,7 @@ func init() {
_OP_NOTIFY_ENTRY: func(ptr unsafe.Pointer) interface{} { return (*raw.NotifyInvalEntryOut)(ptr) }, _OP_NOTIFY_ENTRY: func(ptr unsafe.Pointer) interface{} { return (*raw.NotifyInvalEntryOut)(ptr) },
_OP_NOTIFY_INODE: func(ptr unsafe.Pointer) interface{} { return (*raw.NotifyInvalInodeOut)(ptr) }, _OP_NOTIFY_INODE: func(ptr unsafe.Pointer) interface{} { return (*raw.NotifyInvalInodeOut)(ptr) },
_OP_NOTIFY_DELETE: func(ptr unsafe.Pointer) interface{} { return (*raw.NotifyInvalDeleteOut)(ptr) }, _OP_NOTIFY_DELETE: func(ptr unsafe.Pointer) interface{} { return (*raw.NotifyInvalDeleteOut)(ptr) },
_OP_STATFS: func(ptr unsafe.Pointer) interface{} { return (*StatfsOut)(ptr) }, _OP_STATFS: func(ptr unsafe.Pointer) interface{} { return (*raw.StatfsOut)(ptr) },
} { } {
operationHandlers[op].DecodeOut = f operationHandlers[op].DecodeOut = f
} }
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
// A filesystem API that uses paths rather than inodes. A minimal // A filesystem API that uses paths rather than inodes. A minimal
...@@ -54,8 +55,8 @@ type FileSystem interface { ...@@ -54,8 +55,8 @@ type FileSystem interface {
// File handling. If opening for writing, the file's mtime // File handling. If opening for writing, the file's mtime
// should be updated too. // should be updated too.
Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status)
Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status)
// Directory handling // Directory handling
OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, code fuse.Status) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, code fuse.Status)
...@@ -64,7 +65,7 @@ type FileSystem interface { ...@@ -64,7 +65,7 @@ type FileSystem interface {
Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status)
Readlink(name string, context *fuse.Context) (string, fuse.Status) Readlink(name string, context *fuse.Context) (string, fuse.Status)
StatFs(name string) *fuse.StatfsOut StatFs(name string) *nodefs.StatfsOut
} }
type PathNodeFsOptions struct { type PathNodeFsOptions struct {
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
// NewDefaultFileSystem creates a filesystem that responds ENOSYS for // NewDefaultFileSystem creates a filesystem that responds ENOSYS for
...@@ -80,7 +81,7 @@ func (fs *defaultFileSystem) Truncate(name string, offset uint64, context *fuse. ...@@ -80,7 +81,7 @@ func (fs *defaultFileSystem) Truncate(name string, offset uint64, context *fuse.
return fuse.ENOSYS return fuse.ENOSYS
} }
func (fs *defaultFileSystem) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) { func (fs *defaultFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
return nil, fuse.ENOSYS return nil, fuse.ENOSYS
} }
...@@ -98,7 +99,7 @@ func (fs *defaultFileSystem) Access(name string, mode uint32, context *fuse.Cont ...@@ -98,7 +99,7 @@ func (fs *defaultFileSystem) Access(name string, mode uint32, context *fuse.Cont
return fuse.ENOSYS return fuse.ENOSYS
} }
func (fs *defaultFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status) { func (fs *defaultFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
return nil, fuse.ENOSYS return nil, fuse.ENOSYS
} }
...@@ -110,6 +111,6 @@ func (fs *defaultFileSystem) String() string { ...@@ -110,6 +111,6 @@ func (fs *defaultFileSystem) String() string {
return "defaultFileSystem" return "defaultFileSystem"
} }
func (fs *defaultFileSystem) StatFs(name string) *fuse.StatfsOut { func (fs *defaultFileSystem) StatFs(name string) *nodefs.StatfsOut {
return nil return nil
} }
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
type lockingFileSystem struct { type lockingFileSystem struct {
...@@ -29,7 +30,7 @@ func (fs *lockingFileSystem) String() string { ...@@ -29,7 +30,7 @@ func (fs *lockingFileSystem) String() string {
return fs.FS.String() return fs.FS.String()
} }
func (fs *lockingFileSystem) StatFs(name string) *fuse.StatfsOut { func (fs *lockingFileSystem) StatFs(name string) *nodefs.StatfsOut {
defer fs.locked()() defer fs.locked()()
return fs.FS.StatFs(name) return fs.FS.StatFs(name)
} }
...@@ -99,7 +100,7 @@ func (fs *lockingFileSystem) Truncate(name string, offset uint64, context *fuse. ...@@ -99,7 +100,7 @@ func (fs *lockingFileSystem) Truncate(name string, offset uint64, context *fuse.
return fs.FS.Truncate(name, offset, context) return fs.FS.Truncate(name, offset, context)
} }
func (fs *lockingFileSystem) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) { func (fs *lockingFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
return fs.FS.Open(name, flags, context) return fs.FS.Open(name, flags, context)
} }
...@@ -123,7 +124,7 @@ func (fs *lockingFileSystem) Access(name string, mode uint32, context *fuse.Cont ...@@ -123,7 +124,7 @@ func (fs *lockingFileSystem) Access(name string, mode uint32, context *fuse.Cont
return fs.FS.Access(name, mode, context) 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) { func (fs *lockingFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
defer fs.locked()() defer fs.locked()()
return fs.FS.Create(name, flags, mode, context) return fs.FS.Create(name, flags, mode, context)
} }
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
var _ = fmt.Println var _ = fmt.Println
...@@ -98,12 +99,12 @@ func (fs *loopbackFileSystem) OpenDir(name string, context *fuse.Context) (strea ...@@ -98,12 +99,12 @@ func (fs *loopbackFileSystem) OpenDir(name string, context *fuse.Context) (strea
return output, fuse.OK return output, fuse.OK
} }
func (fs *loopbackFileSystem) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) { func (fs *loopbackFileSystem) Open(name string, flags uint32, context *fuse.Context) (fuseFile nodefs.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, fuse.ToStatus(err) return nil, fuse.ToStatus(err)
} }
return fuse.NewLoopbackFile(f), fuse.OK return nodefs.NewLoopbackFile(f), fuse.OK
} }
func (fs *loopbackFileSystem) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.Status) { func (fs *loopbackFileSystem) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
...@@ -170,7 +171,7 @@ func (fs *loopbackFileSystem) Access(name string, mode uint32, context *fuse.Con ...@@ -170,7 +171,7 @@ func (fs *loopbackFileSystem) Access(name string, mode uint32, context *fuse.Con
return fuse.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 *fuse.Context) (fuseFile fuse.File, code fuse.Status) { func (fs *loopbackFileSystem) Create(path string, flags uint32, mode uint32, context *fuse.Context) (fuseFile nodefs.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 fuse.NewLoopbackFile(f), fuse.ToStatus(err) return nodefs.NewLoopbackFile(f), fuse.ToStatus(err)
} }
...@@ -5,13 +5,14 @@ import ( ...@@ -5,13 +5,14 @@ import (
"syscall" "syscall"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut { func (fs *loopbackFileSystem) StatFs(name string) *nodefs.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 &fuse.StatfsOut{ return &nodefs.StatfsOut{
Blocks: s.Blocks, Blocks: s.Blocks,
Bsize: uint32(s.Bsize), Bsize: uint32(s.Bsize),
Bfree: s.Bfree, Bfree: s.Bfree,
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
type ownerFs struct { type ownerFs struct {
...@@ -29,12 +30,12 @@ func (fs *ownerFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse ...@@ -29,12 +30,12 @@ func (fs *ownerFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse
return a, fuse.OK return a, fuse.OK
} }
func setupOwnerTest(t *testing.T, opts *fuse.FileSystemOptions) (workdir string, cleanup func()) { func setupOwnerTest(t *testing.T, opts *nodefs.Options) (workdir string, cleanup func()) {
wd, err := ioutil.TempDir("", "go-fuse-owner_test") wd, err := ioutil.TempDir("", "go-fuse-owner_test")
fs := &ownerFs{NewDefaultFileSystem()} fs := &ownerFs{NewDefaultFileSystem()}
nfs := NewPathNodeFs(fs, nil) nfs := NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(wd, nfs, opts) state, _, err := nodefs.MountFileSystem(wd, nfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
...@@ -46,7 +47,7 @@ func setupOwnerTest(t *testing.T, opts *fuse.FileSystemOptions) (workdir string, ...@@ -46,7 +47,7 @@ func setupOwnerTest(t *testing.T, opts *fuse.FileSystemOptions) (workdir string,
} }
func TestOwnerDefault(t *testing.T) { func TestOwnerDefault(t *testing.T) {
wd, cleanup := setupOwnerTest(t, fuse.NewFileSystemOptions()) wd, cleanup := setupOwnerTest(t, nodefs.NewOptions())
defer cleanup() defer cleanup()
var stat syscall.Stat_t var stat syscall.Stat_t
...@@ -61,7 +62,7 @@ func TestOwnerDefault(t *testing.T) { ...@@ -61,7 +62,7 @@ func TestOwnerDefault(t *testing.T) {
} }
func TestOwnerRoot(t *testing.T) { func TestOwnerRoot(t *testing.T) {
wd, cleanup := setupOwnerTest(t, &fuse.FileSystemOptions{}) wd, cleanup := setupOwnerTest(t, &nodefs.Options{})
defer cleanup() defer cleanup()
var st syscall.Stat_t var st syscall.Stat_t
...@@ -76,7 +77,7 @@ func TestOwnerRoot(t *testing.T) { ...@@ -76,7 +77,7 @@ func TestOwnerRoot(t *testing.T) {
} }
func TestOwnerOverride(t *testing.T) { func TestOwnerOverride(t *testing.T) {
wd, cleanup := setupOwnerTest(t, &fuse.FileSystemOptions{Owner: &fuse.Owner{42, 43}}) wd, cleanup := setupOwnerTest(t, &nodefs.Options{Owner: &fuse.Owner{42, 43}})
defer cleanup() defer cleanup()
var stat syscall.Stat_t var stat syscall.Stat_t
......
This diff is collapsed.
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
// PrefixFileSystem adds a path prefix to incoming calls. // PrefixFileSystem adds a path prefix to incoming calls.
...@@ -70,7 +71,7 @@ func (fs *prefixFileSystem) Truncate(name string, offset uint64, context *fuse.C ...@@ -70,7 +71,7 @@ func (fs *prefixFileSystem) Truncate(name string, offset uint64, context *fuse.C
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 *fuse.Context) (file fuse.File, code fuse.Status) { func (fs *prefixFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
return fs.FileSystem.Open(fs.prefixed(name), flags, context) return fs.FileSystem.Open(fs.prefixed(name), flags, context)
} }
...@@ -90,7 +91,7 @@ func (fs *prefixFileSystem) Access(name string, mode uint32, context *fuse.Conte ...@@ -90,7 +91,7 @@ func (fs *prefixFileSystem) Access(name string, mode uint32, context *fuse.Conte
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 *fuse.Context) (file fuse.File, code fuse.Status) { func (fs *prefixFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
return fs.FileSystem.Create(fs.prefixed(name), flags, mode, context) return fs.FileSystem.Create(fs.prefixed(name), flags, mode, context)
} }
...@@ -118,6 +119,6 @@ func (fs *prefixFileSystem) String() string { ...@@ -118,6 +119,6 @@ func (fs *prefixFileSystem) String() string {
return fmt.Sprintf("prefixFileSystem(%s,%s)", fs.FileSystem.String(), fs.Prefix) return fmt.Sprintf("prefixFileSystem(%s,%s)", fs.FileSystem.String(), fs.Prefix)
} }
func (fs *prefixFileSystem) StatFs(name string) *fuse.StatfsOut { func (fs *prefixFileSystem) StatFs(name string) *nodefs.StatfsOut {
return fs.FileSystem.StatFs(fs.prefixed(name)) return fs.FileSystem.StatFs(fs.prefixed(name))
} }
...@@ -5,9 +5,9 @@ import ( ...@@ -5,9 +5,9 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
// NewReadonlyFileSystem returns a wrapper that only exposes read-only // NewReadonlyFileSystem returns a wrapper that only exposes read-only
// operations. // operations.
func NewReadonlyFileSystem(fs FileSystem) FileSystem { func NewReadonlyFileSystem(fs FileSystem) FileSystem {
...@@ -68,12 +68,12 @@ func (fs *readonlyFileSystem) Truncate(name string, offset uint64, context *fuse ...@@ -68,12 +68,12 @@ func (fs *readonlyFileSystem) Truncate(name string, offset uint64, context *fuse
return fuse.EPERM return fuse.EPERM
} }
func (fs *readonlyFileSystem) Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) { func (fs *readonlyFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM return nil, fuse.EPERM
} }
file, code = fs.FileSystem.Open(name, flags, context) file, code = fs.FileSystem.Open(name, flags, context)
return fuse.NewReadOnlyFile(file), code return nodefs.NewReadOnlyFile(file), code
} }
func (fs *readonlyFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) { func (fs *readonlyFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
...@@ -96,7 +96,7 @@ func (fs *readonlyFileSystem) Access(name string, mode uint32, context *fuse.Con ...@@ -96,7 +96,7 @@ func (fs *readonlyFileSystem) Access(name string, mode uint32, context *fuse.Con
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 *fuse.Context) (file fuse.File, code fuse.Status) { func (fs *readonlyFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
return nil, fuse.EPERM return nil, fuse.EPERM
} }
......
...@@ -40,4 +40,3 @@ func listXAttr(path string) (attributes []string, err error) { ...@@ -40,4 +40,3 @@ func listXAttr(path string) (attributes []string, err error) {
} }
return attributes, err return attributes, err
} }
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"testing" "testing"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
var _ = log.Print var _ = log.Print
...@@ -114,7 +115,7 @@ func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func()) ...@@ -114,7 +115,7 @@ func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func())
} }
nfs := NewPathNodeFs(xfs, nil) nfs := NewPathNodeFs(xfs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, nil) state, _, err := nodefs.MountFileSystem(mountPoint, nfs, nil)
if err != nil { if err != nil {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"testing" "testing"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
...@@ -19,12 +20,12 @@ type cacheFs struct { ...@@ -19,12 +20,12 @@ type cacheFs struct {
pathfs.FileSystem pathfs.FileSystem
} }
func (fs *cacheFs) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) { func (fs *cacheFs) Open(name string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) {
f, c := fs.FileSystem.Open(name, flags, context) f, c := fs.FileSystem.Open(name, flags, context)
if !c.Ok() { if !c.Ok() {
return f, c return f, c
} }
return &fuse.WithFlags{ return &nodefs.WithFlags{
File: f, File: f,
FuseFlags: raw.FOPEN_KEEP_CACHE, FuseFlags: raw.FOPEN_KEEP_CACHE,
}, c }, c
...@@ -43,7 +44,7 @@ func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) { ...@@ -43,7 +44,7 @@ func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
pathfs.NewLoopbackFileSystem(dir + "/orig"), pathfs.NewLoopbackFileSystem(dir + "/orig"),
} }
pfs := pathfs.NewPathNodeFs(fs, nil) pfs := pathfs.NewPathNodeFs(fs, nil)
state, conn, err := fuse.MountNodeFileSystem(dir+"/mnt", pfs, nil) state, conn, err := nodefs.MountFileSystem(dir+"/mnt", pfs, nil)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
...@@ -120,14 +121,14 @@ func (fs *nonseekFs) GetAttr(name string, context *fuse.Context) (fi *fuse.Attr, ...@@ -120,14 +121,14 @@ func (fs *nonseekFs) GetAttr(name string, context *fuse.Context) (fi *fuse.Attr,
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *nonseekFs) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) { func (fs *nonseekFs) Open(name string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) {
if name != "file" { if name != "file" {
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
data := bytes.Repeat([]byte{42}, fs.Length) data := bytes.Repeat([]byte{42}, fs.Length)
f := fuse.NewDataFile(data) f := nodefs.NewDataFile(data)
return &fuse.WithFlags{ return &nodefs.WithFlags{
File: f, File: f,
FuseFlags: raw.FOPEN_NONSEEKABLE, FuseFlags: raw.FOPEN_NONSEEKABLE,
}, fuse.OK }, fuse.OK
...@@ -143,7 +144,7 @@ func TestNonseekable(t *testing.T) { ...@@ -143,7 +144,7 @@ func TestNonseekable(t *testing.T) {
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, nfs, nil) state, _, err := nodefs.MountFileSystem(dir, nfs, nil)
if err != nil { if err != nil {
t.Fatalf("failed: %v", err) t.Fatalf("failed: %v", err)
} }
...@@ -176,8 +177,8 @@ func TestGetAttrRace(t *testing.T) { ...@@ -176,8 +177,8 @@ func TestGetAttrRace(t *testing.T) {
fs := pathfs.NewLoopbackFileSystem(dir + "/orig") fs := pathfs.NewLoopbackFileSystem(dir + "/orig")
pfs := pathfs.NewPathNodeFs(fs, nil) pfs := pathfs.NewPathNodeFs(fs, nil)
state, conn, err := fuse.MountNodeFileSystem(dir+"/mnt", pfs, state, conn, err := nodefs.MountFileSystem(dir+"/mnt", pfs,
&fuse.FileSystemOptions{}) &nodefs.Options{})
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
......
...@@ -6,10 +6,10 @@ import ( ...@@ -6,10 +6,10 @@ import (
"testing" "testing"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
type DefaultReadFS struct { type DefaultReadFS struct {
pathfs.FileSystem pathfs.FileSystem
size uint64 size uint64
...@@ -26,8 +26,8 @@ func (fs *DefaultReadFS) GetAttr(name string, context *fuse.Context) (*fuse.Attr ...@@ -26,8 +26,8 @@ func (fs *DefaultReadFS) GetAttr(name string, context *fuse.Context) (*fuse.Attr
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *DefaultReadFS) Open(name string, f uint32, context *fuse.Context) (fuse.File, fuse.Status) { func (fs *DefaultReadFS) Open(name string, f uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
return fuse.NewDefaultFile(), fuse.OK return nodefs.NewDefaultFile(), fuse.OK
} }
func defaultReadTest(t *testing.T) (root string, cleanup func()) { func defaultReadTest(t *testing.T) (root string, cleanup func()) {
...@@ -41,7 +41,7 @@ func defaultReadTest(t *testing.T) (root string, cleanup func()) { ...@@ -41,7 +41,7 @@ func defaultReadTest(t *testing.T) (root string, cleanup func()) {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
pathfs := pathfs.NewPathNodeFs(fs, nil) pathfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, pathfs, nil) state, _, err := nodefs.MountFileSystem(dir, pathfs, nil)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
......
...@@ -10,21 +10,22 @@ import ( ...@@ -10,21 +10,22 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
type flipNode struct { type flipNode struct {
fuse.FsNode nodefs.Node
ok chan int ok chan int
} }
func (f *flipNode) GetAttr(out *fuse.Attr, file fuse.File, c *fuse.Context) fuse.Status { func (f *flipNode) GetAttr(out *fuse.Attr, file nodefs.File, c *fuse.Context) fuse.Status {
select { select {
case <-f.ok: case <-f.ok:
// use a status that is easily recognizable. // use a status that is easily recognizable.
return fuse.Status(syscall.EXDEV) return fuse.Status(syscall.EXDEV)
default: default:
} }
return f.FsNode.GetAttr(out, file, c) return f.Node.GetAttr(out, file, c)
} }
func TestDeleteNotify(t *testing.T) { func TestDeleteNotify(t *testing.T) {
...@@ -33,9 +34,9 @@ func TestDeleteNotify(t *testing.T) { ...@@ -33,9 +34,9 @@ func TestDeleteNotify(t *testing.T) {
t.Fatalf("TempDir failed %v", err) t.Fatalf("TempDir failed %v", err)
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
fs := fuse.NewMemNodeFs(dir + "/backing") fs := nodefs.NewMemNodeFs(dir + "/backing")
conn := fuse.NewFileSystemConnector(fs, conn := nodefs.NewFileSystemConnector(fs,
&fuse.FileSystemOptions{PortableInodes: true}) &nodefs.Options{PortableInodes: true})
state := fuse.NewMountState(conn.RawFS()) state := fuse.NewMountState(conn.RawFS())
mnt := dir + "/mnt" mnt := dir + "/mnt"
err = os.Mkdir(mnt, 0755) err = os.Mkdir(mnt, 0755)
...@@ -56,9 +57,9 @@ func TestDeleteNotify(t *testing.T) { ...@@ -56,9 +57,9 @@ func TestDeleteNotify(t *testing.T) {
} }
ch := fs.Root().Inode().RmChild("testdir") ch := fs.Root().Inode().RmChild("testdir")
ch.FsNode().SetInode(nil) ch.Node().SetInode(nil)
flip := flipNode{ flip := flipNode{
FsNode: ch.FsNode(), Node: ch.Node(),
ok: make(chan int), ok: make(chan int),
} }
newCh := fs.Root().Inode().New(true, &flip) newCh := fs.Root().Inode().New(true, &flip)
...@@ -100,7 +101,7 @@ func TestDeleteNotify(t *testing.T) { ...@@ -100,7 +101,7 @@ func TestDeleteNotify(t *testing.T) {
// Simulate deletion+mkdir coming from the network // Simulate deletion+mkdir coming from the network
close(flip.ok) close(flip.ok)
oldCh := fs.Root().Inode().RmChild("testdir") oldCh := fs.Root().Inode().RmChild("testdir")
_, code = fs.Root().Inode().FsNode().Mkdir("testdir", 0755, nil) _, code = fs.Root().Inode().Node().Mkdir("testdir", 0755, nil)
if !code.Ok() { if !code.Ok() {
t.Fatal("mkdir status", code) t.Fatal("mkdir status", 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/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
type MutableDataFile struct { type MutableDataFile struct {
fuse.File nodefs.File
data []byte data []byte
fuse.Attr fuse.Attr
...@@ -111,14 +112,14 @@ func (fs *FSetAttrFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, f ...@@ -111,14 +112,14 @@ func (fs *FSetAttrFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, f
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *FSetAttrFs) Open(name string, flags uint32, context *fuse.Context) (fuse.File, fuse.Status) { func (fs *FSetAttrFs) Open(name string, flags uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
if name == "file" { if name == "file" {
return fs.file, fuse.OK return fs.file, fuse.OK
} }
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *FSetAttrFs) Create(name string, flags uint32, mode uint32, context *fuse.Context) (fuse.File, fuse.Status) { func (fs *FSetAttrFs) Create(name string, flags uint32, mode uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
if name == "file" { if name == "file" {
f := NewFile() f := NewFile()
fs.file = f fs.file = f
...@@ -129,7 +130,7 @@ func (fs *FSetAttrFs) Create(name string, flags uint32, mode uint32, context *fu ...@@ -129,7 +130,7 @@ func (fs *FSetAttrFs) Create(name string, flags uint32, mode uint32, context *fu
} }
func NewFile() *MutableDataFile { func NewFile() *MutableDataFile {
return &MutableDataFile{File: fuse.NewDefaultFile()} return &MutableDataFile{File: nodefs.NewDefaultFile()}
} }
func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func(), sync func()) { func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func(), sync func()) {
...@@ -138,7 +139,7 @@ func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func( ...@@ -138,7 +139,7 @@ func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func(
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, nfs, nil) state, _, err := nodefs.MountFileSystem(dir, nfs, nil)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
......
...@@ -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/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -39,7 +40,7 @@ type testCase struct { ...@@ -39,7 +40,7 @@ type testCase struct {
tester *testing.T tester *testing.T
state *fuse.MountState state *fuse.MountState
pathFs *pathfs.PathNodeFs pathFs *pathfs.PathNodeFs
connector *fuse.FileSystemConnector connector *nodefs.FileSystemConnector
} }
const testTtl = 100 * time.Millisecond const testTtl = 100 * time.Millisecond
...@@ -78,8 +79,8 @@ func NewTestCase(t *testing.T) *testCase { ...@@ -78,8 +79,8 @@ func NewTestCase(t *testing.T) *testCase {
var rfs fuse.RawFileSystem var rfs fuse.RawFileSystem
me.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{ me.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{
ClientInodes: true}) ClientInodes: true})
me.connector = fuse.NewFileSystemConnector(me.pathFs, me.connector = nodefs.NewFileSystemConnector(me.pathFs,
&fuse.FileSystemOptions{ &nodefs.Options{
EntryTimeout: testTtl, EntryTimeout: testTtl,
AttrTimeout: testTtl, AttrTimeout: testTtl,
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
...@@ -108,7 +109,7 @@ func (tc *testCase) Cleanup() { ...@@ -108,7 +109,7 @@ func (tc *testCase) Cleanup() {
os.RemoveAll(tc.tmpDir) os.RemoveAll(tc.tmpDir)
} }
func (tc *testCase) rootNode() *fuse.Inode { func (tc *testCase) rootNode() *nodefs.Inode {
return tc.pathFs.Root().Inode() return tc.pathFs.Root().Inode()
} }
...@@ -930,7 +931,7 @@ func TestOriginalIsSymlink(t *testing.T) { ...@@ -930,7 +931,7 @@ func TestOriginalIsSymlink(t *testing.T) {
fs := pathfs.NewLoopbackFileSystem(link) fs := pathfs.NewLoopbackFileSystem(link)
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mnt, nfs, nil) state, _, err := nodefs.MountFileSystem(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/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -19,7 +20,7 @@ func TestMountOnExisting(t *testing.T) { ...@@ -19,7 +20,7 @@ func TestMountOnExisting(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Mkdir failed: %v", err) t.Fatalf("Mkdir failed: %v", err)
} }
nfs := fuse.NewDefaultNodeFileSystem() nfs := nodefs.NewDefaultFileSystem()
code := ts.connector.Mount(ts.rootNode(), "mnt", nfs, nil) code := ts.connector.Mount(ts.rootNode(), "mnt", nfs, nil)
if code != fuse.EBUSY { if code != fuse.EBUSY {
t.Fatal("expect EBUSY:", code) t.Fatal("expect EBUSY:", code)
......
...@@ -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/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -32,14 +33,14 @@ func (fs *NotifyFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fus ...@@ -32,14 +33,14 @@ func (fs *NotifyFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fus
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *NotifyFs) Open(name string, f uint32, context *fuse.Context) (fuse.File, fuse.Status) { func (fs *NotifyFs) Open(name string, f uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
return fuse.NewDataFile([]byte{42}), fuse.OK return nodefs.NewDataFile([]byte{42}), fuse.OK
} }
type NotifyTest struct { type NotifyTest struct {
fs *NotifyFs fs *NotifyFs
pathfs *pathfs.PathNodeFs pathfs *pathfs.PathNodeFs
connector *fuse.FileSystemConnector connector *nodefs.FileSystemConnector
dir string dir string
state *fuse.MountState state *fuse.MountState
} }
...@@ -53,14 +54,14 @@ func NewNotifyTest(t *testing.T) *NotifyTest { ...@@ -53,14 +54,14 @@ func NewNotifyTest(t *testing.T) *NotifyTest {
t.Fatalf("TempDir failed: %v", err) t.Fatalf("TempDir failed: %v", err)
} }
entryTtl := 100 * time.Millisecond entryTtl := 100 * time.Millisecond
opts := &fuse.FileSystemOptions{ opts := &nodefs.Options{
EntryTimeout: entryTtl, EntryTimeout: entryTtl,
AttrTimeout: entryTtl, AttrTimeout: entryTtl,
NegativeTimeout: entryTtl, NegativeTimeout: entryTtl,
} }
me.pathfs = pathfs.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 = nodefs.MountFileSystem(me.dir, me.pathfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
......
package fuse package fuse
import ( import (
"fmt"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
func (me *WithFlags) String() string {
return fmt.Sprintf("File %s (%s) %s %s",
me.File, me.Description, raw.FlagString(raw.OpenFlagNames, int64(me.OpenFlags), "O_RDONLY"),
raw.FlagString(raw.FuseOpenFlagNames, int64(me.FuseFlags), ""))
}
func (a *Attr) String() string { func (a *Attr) String() string {
return ((*raw.Attr)(a)).String() return ((*raw.Attr)(a)).String()
} }
...@@ -51,4 +51,3 @@ type Context struct { ...@@ -51,4 +51,3 @@ type Context struct {
*raw.Context *raw.Context
} }
type StatfsOut raw.StatfsOut
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -38,12 +39,13 @@ type autoUnionFs struct { ...@@ -38,12 +39,13 @@ type autoUnionFs struct {
options *AutoUnionFsOptions options *AutoUnionFsOptions
mountState *fuse.MountState mountState *fuse.MountState
connector *fuse.FileSystemConnector connector *nodefs.FileSystemConnector
} }
type AutoUnionFsOptions struct { type AutoUnionFsOptions struct {
UnionFsOptions UnionFsOptions
fuse.FileSystemOptions
nodefs.Options
pathfs.PathNodeFsOptions pathfs.PathNodeFsOptions
// If set, run updateKnownFses() after mounting. // If set, run updateKnownFses() after mounting.
...@@ -68,7 +70,7 @@ const ( ...@@ -68,7 +70,7 @@ const (
// FileSystemConnector // FileSystemConnector
type RootFileSystem interface { type RootFileSystem interface {
SetMountState(state *fuse.MountState) SetMountState(state *fuse.MountState)
SetFileSystemConnector(conn *fuse.FileSystemConnector) SetFileSystemConnector(conn *nodefs.FileSystemConnector)
pathfs.FileSystem pathfs.FileSystem
} }
...@@ -137,7 +139,7 @@ func (fs *autoUnionFs) createFs(name string, roots []string) fuse.Status { ...@@ -137,7 +139,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 := pathfs.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.Options)
if code.Ok() { if code.Ok() {
fs.knownFileSystems[name] = knownFs{ fs.knownFileSystems[name] = knownFs{
ufs, ufs,
...@@ -395,7 +397,7 @@ func (fs *autoUnionFs) SetMountState(state *fuse.MountState) { ...@@ -395,7 +397,7 @@ func (fs *autoUnionFs) SetMountState(state *fuse.MountState) {
fs.mountState = state fs.mountState = state
} }
func (fs *autoUnionFs) SetFileSystemConnector(conn *fuse.FileSystemConnector) { func (fs *autoUnionFs) SetFileSystemConnector(conn *nodefs.FileSystemConnector) {
fs.connector = conn fs.connector = conn
} }
...@@ -419,25 +421,25 @@ func (fs *autoUnionFs) DebugData() string { ...@@ -419,25 +421,25 @@ func (fs *autoUnionFs) DebugData() string {
return msg return msg
} }
func (fs *autoUnionFs) Open(path string, flags uint32, context *fuse.Context) (fuse.File, fuse.Status) { func (fs *autoUnionFs) Open(path string, flags uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
if path == filepath.Join(_STATUS, _DEBUG) { if path == filepath.Join(_STATUS, _DEBUG) {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM return nil, fuse.EPERM
} }
return fuse.NewDataFile([]byte(fs.DebugData())), fuse.OK return nodefs.NewDataFile([]byte(fs.DebugData())), fuse.OK
} }
if path == filepath.Join(_STATUS, _VERSION) { if path == filepath.Join(_STATUS, _VERSION) {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM return nil, fuse.EPERM
} }
return fuse.NewDataFile([]byte(fuse.Version())), fuse.OK return nodefs.NewDataFile([]byte(fuse.Version())), fuse.OK
} }
if path == filepath.Join(_CONFIG, _SCAN_CONFIG) { if path == filepath.Join(_CONFIG, _SCAN_CONFIG) {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
fs.updateKnownFses() fs.updateKnownFses()
} }
return fuse.NewDevNullFile(), fuse.OK return nodefs.NewDevNullFile(), fuse.OK
} }
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
...@@ -489,6 +491,6 @@ func (fs *autoUnionFs) OpenDir(name string, context *fuse.Context) (stream []fus ...@@ -489,6 +491,6 @@ func (fs *autoUnionFs) OpenDir(name string, context *fuse.Context) (stream []fus
return stream, status return stream, status
} }
func (fs *autoUnionFs) StatFs(name string) *fuse.StatfsOut { func (fs *autoUnionFs) StatFs(name string) *nodefs.StatfsOut {
return &fuse.StatfsOut{} return &nodefs.StatfsOut{}
} }
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -19,7 +20,7 @@ const entryTtl = 100 * time.Millisecond ...@@ -19,7 +20,7 @@ const entryTtl = 100 * time.Millisecond
var testAOpts = AutoUnionFsOptions{ var testAOpts = AutoUnionFsOptions{
UnionFsOptions: testOpts, UnionFsOptions: testOpts,
FileSystemOptions: fuse.FileSystemOptions{ Options: nodefs.Options{
EntryTimeout: entryTtl, EntryTimeout: entryTtl,
AttrTimeout: entryTtl, AttrTimeout: entryTtl,
NegativeTimeout: 0, NegativeTimeout: 0,
...@@ -56,7 +57,7 @@ func setup(t *testing.T) (workdir string, cleanup func()) { ...@@ -56,7 +57,7 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
fs := NewAutoUnionFs(wd+"/store", testAOpts) fs := NewAutoUnionFs(wd+"/store", testAOpts)
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, conn, err := fuse.MountNodeFileSystem(wd+"/mnt", nfs, &testAOpts.FileSystemOptions) state, conn, err := nodefs.MountFileSystem(wd+"/mnt", nfs, &testAOpts.Options)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -139,7 +140,7 @@ func (fs *cachingFileSystem) String() string { ...@@ -139,7 +140,7 @@ func (fs *cachingFileSystem) String() string {
return fmt.Sprintf("cachingFileSystem(%v)", fs.FileSystem) return fmt.Sprintf("cachingFileSystem(%v)", fs.FileSystem)
} }
func (fs *cachingFileSystem) Open(name string, flags uint32, context *fuse.Context) (f fuse.File, status fuse.Status) { func (fs *cachingFileSystem) Open(name string, flags uint32, context *fuse.Context) (f nodefs.File, status fuse.Status) {
if flags&fuse.O_ANYWRITE != 0 && name == _DROP_CACHE { if flags&fuse.O_ANYWRITE != 0 && name == _DROP_CACHE {
log.Println("Dropping cache for", fs) log.Println("Dropping cache for", fs)
fs.DropCache() fs.DropCache()
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
...@@ -247,7 +248,7 @@ func (fs *unionFS) putDeletion(name string) (code fuse.Status) { ...@@ -247,7 +248,7 @@ func (fs *unionFS) putDeletion(name string) (code fuse.Status) {
return fuse.OK return fuse.OK
} }
var f fuse.File var f nodefs.File
if code == fuse.ENOENT { if code == fuse.ENOENT {
f, code = writable.Create(marker, uint32(os.O_TRUNC|os.O_WRONLY), 0644, nil) f, code = writable.Create(marker, uint32(os.O_TRUNC|os.O_WRONLY), 0644, nil)
} else { } else {
...@@ -362,7 +363,7 @@ func (fs *unionFS) Link(orig string, newName string, context *fuse.Context) (cod ...@@ -362,7 +363,7 @@ func (fs *unionFS) Link(orig string, newName string, context *fuse.Context) (cod
fs.branchCache.GetFresh(orig) fs.branchCache.GetFresh(orig)
inode := fs.nodeFs.Node(orig) inode := fs.nodeFs.Node(orig)
var a fuse.Attr var a fuse.Attr
inode.FsNode().GetAttr(&a, nil, nil) inode.Node().GetAttr(&a, nil, nil)
} }
if code.Ok() { if code.Ok() {
code = fs.promoteDirsTo(newName) code = fs.promoteDirsTo(newName)
...@@ -650,7 +651,7 @@ func (fs *unionFS) promoteDirsTo(filename string) fuse.Status { ...@@ -650,7 +651,7 @@ func (fs *unionFS) promoteDirsTo(filename string) fuse.Status {
return fuse.OK return fuse.OK
} }
func (fs *unionFS) Create(name string, flags uint32, mode uint32, context *fuse.Context) (fuseFile fuse.File, code fuse.Status) { func (fs *unionFS) Create(name string, flags uint32, mode uint32, context *fuse.Context) (fuseFile nodefs.File, code fuse.Status) {
writable := fs.fileSystems[0] writable := fs.fileSystems[0]
code = fs.promoteDirsTo(name) code = fs.promoteDirsTo(name)
...@@ -926,7 +927,7 @@ func (fs *unionFS) DropSubFsCaches() { ...@@ -926,7 +927,7 @@ func (fs *unionFS) DropSubFsCaches() {
} }
} }
func (fs *unionFS) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) { func (fs *unionFS) Open(name string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) {
if name == _DROP_CACHE { if name == _DROP_CACHE {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
log.Println("Forced cache drop on", fs) log.Println("Forced cache drop on", fs)
...@@ -935,7 +936,7 @@ func (fs *unionFS) Open(name string, flags uint32, context *fuse.Context) (fuseF ...@@ -935,7 +936,7 @@ func (fs *unionFS) Open(name string, flags uint32, context *fuse.Context) (fuseF
fs.DropSubFsCaches() fs.DropSubFsCaches()
fs.nodeFs.ForgetClientInodes() fs.nodeFs.ForgetClientInodes()
} }
return fuse.NewDevNullFile(), fuse.OK return nodefs.NewDevNullFile(), fuse.OK
} }
r := fs.getBranch(name) r := fs.getBranch(name)
if r.branch < 0 { if r.branch < 0 {
...@@ -969,14 +970,14 @@ func (fs *unionFS) String() string { ...@@ -969,14 +970,14 @@ func (fs *unionFS) String() string {
return fmt.Sprintf("UnionFs(%v)", names) return fmt.Sprintf("UnionFs(%v)", names)
} }
func (fs *unionFS) StatFs(name string) *fuse.StatfsOut { func (fs *unionFS) StatFs(name string) *nodefs.StatfsOut {
return fs.fileSystems[0].StatFs("") return fs.fileSystems[0].StatFs("")
} }
type unionFsFile struct { type unionFsFile struct {
fuse.File nodefs.File
ufs *unionFS ufs *unionFS
node *fuse.Inode node *nodefs.Inode
layer int layer int
} }
...@@ -984,7 +985,7 @@ func (fs *unionFsFile) String() string { ...@@ -984,7 +985,7 @@ func (fs *unionFsFile) String() string {
return fmt.Sprintf("unionFsFile(%s)", fs.File.String()) return fmt.Sprintf("unionFsFile(%s)", fs.File.String())
} }
func (fs *unionFS) newUnionFsFile(f fuse.File, branch int) *unionFsFile { func (fs *unionFS) newUnionFsFile(f nodefs.File, branch int) *unionFsFile {
return &unionFsFile{ return &unionFsFile{
File: f, File: f,
ufs: fs, ufs: fs,
...@@ -992,7 +993,7 @@ func (fs *unionFS) newUnionFsFile(f fuse.File, branch int) *unionFsFile { ...@@ -992,7 +993,7 @@ func (fs *unionFS) newUnionFsFile(f fuse.File, branch int) *unionFsFile {
} }
} }
func (fs *unionFsFile) InnerFile() (file fuse.File) { func (fs *unionFsFile) InnerFile() (file nodefs.File) {
return fs.File return fs.File
} }
...@@ -1005,7 +1006,7 @@ func (fs *unionFsFile) Flush() (code fuse.Status) { ...@@ -1005,7 +1006,7 @@ func (fs *unionFsFile) Flush() (code fuse.Status) {
return code return code
} }
func (fs *unionFsFile) SetInode(node *fuse.Inode) { func (fs *unionFsFile) SetInode(node *nodefs.Inode) {
fs.node = node fs.node = node
} }
......
...@@ -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/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/raw" "github.com/hanwen/go-fuse/raw"
) )
...@@ -85,7 +86,7 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) { ...@@ -85,7 +86,7 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
// We configure timeouts are smaller, so we can check for // We configure timeouts are smaller, so we can check for
// UnionFs's cache consistency. // UnionFs's cache consistency.
opts := &fuse.FileSystemOptions{ opts := &nodefs.Options{
EntryTimeout: entryTtl / 2, EntryTimeout: entryTtl / 2,
AttrTimeout: entryTtl / 2, AttrTimeout: entryTtl / 2,
NegativeTimeout: entryTtl / 2, NegativeTimeout: entryTtl / 2,
...@@ -93,7 +94,7 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) { ...@@ -93,7 +94,7 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
pathfs := pathfs.NewPathNodeFs(ufs, pathfs := pathfs.NewPathNodeFs(ufs,
&pathfs.PathNodeFsOptions{ClientInodes: true}) &pathfs.PathNodeFsOptions{ClientInodes: true})
state, conn, err := fuse.MountNodeFileSystem(wd+"/mnt", pathfs, opts) state, conn, err := nodefs.MountFileSystem(wd+"/mnt", pathfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
...@@ -1106,14 +1107,14 @@ func TestUnionFsDisappearing(t *testing.T) { ...@@ -1106,14 +1107,14 @@ func TestUnionFsDisappearing(t *testing.T) {
fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/ro")) fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/ro"))
ufs := NewUnionFs(fses, testOpts) ufs := NewUnionFs(fses, testOpts)
opts := &fuse.FileSystemOptions{ opts := &nodefs.Options{
EntryTimeout: entryTtl, EntryTimeout: entryTtl,
AttrTimeout: entryTtl, AttrTimeout: entryTtl,
NegativeTimeout: entryTtl, NegativeTimeout: entryTtl,
} }
nfs := pathfs.NewPathNodeFs(ufs, nil) nfs := pathfs.NewPathNodeFs(ufs, nil)
state, _, err := fuse.MountNodeFileSystem(wd+"/mnt", nfs, opts) state, _, err := nodefs.MountFileSystem(wd+"/mnt", nfs, opts)
if err != nil { if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
type MemFile interface { type MemFile interface {
...@@ -13,7 +14,7 @@ type MemFile interface { ...@@ -13,7 +14,7 @@ type MemFile interface {
} }
type memNode struct { type memNode struct {
fuse.FsNode nodefs.Node
file MemFile file MemFile
} }
...@@ -21,7 +22,7 @@ type memNode struct { ...@@ -21,7 +22,7 @@ type memNode struct {
// loaded in memory completely at startup, it does not need to inode // loaded in memory completely at startup, it does not need to inode
// discovery through Lookup() at serve time. // discovery through Lookup() at serve time.
type MemTreeFs struct { type MemTreeFs struct {
fuse.NodeFileSystem nodefs.FileSystem
root memNode root memNode
files map[string]MemFile files map[string]MemFile
Name string Name string
...@@ -29,8 +30,8 @@ type MemTreeFs struct { ...@@ -29,8 +30,8 @@ type MemTreeFs struct {
func NewMemTreeFs() *MemTreeFs { func NewMemTreeFs() *MemTreeFs {
return &MemTreeFs{ return &MemTreeFs{
NodeFileSystem: fuse.NewDefaultNodeFileSystem(), FileSystem: nodefs.NewDefaultFileSystem(),
root: memNode{FsNode: fuse.NewDefaultFsNode()}, root: memNode{Node: nodefs.NewDefaultNode()},
} }
} }
...@@ -38,14 +39,14 @@ func (fs *MemTreeFs) String() string { ...@@ -38,14 +39,14 @@ func (fs *MemTreeFs) String() string {
return fs.Name return fs.Name
} }
func (fs *MemTreeFs) OnMount(conn *fuse.FileSystemConnector) { func (fs *MemTreeFs) OnMount(conn *nodefs.FileSystemConnector) {
for k, v := range fs.files { for k, v := range fs.files {
fs.addFile(k, v) fs.addFile(k, v)
} }
fs.files = nil fs.files = nil
} }
func (fs *MemTreeFs) Root() fuse.FsNode { func (fs *MemTreeFs) Root() nodefs.Node {
return &fs.root return &fs.root
} }
...@@ -59,7 +60,7 @@ func (n *memNode) Print(indent int) { ...@@ -59,7 +60,7 @@ func (n *memNode) Print(indent int) {
for k, v := range children { for k, v := range children {
if v.IsDir() { if v.IsDir() {
fmt.Println(s + k + ":") fmt.Println(s + k + ":")
mn, ok := v.FsNode().(*memNode) mn, ok := v.Node().(*memNode)
if ok { if ok {
mn.Print(indent + 2) mn.Print(indent + 2)
} }
...@@ -85,19 +86,19 @@ func (n *memNode) OpenDir(context *fuse.Context) (stream []fuse.DirEntry, code f ...@@ -85,19 +86,19 @@ func (n *memNode) OpenDir(context *fuse.Context) (stream []fuse.DirEntry, code f
return stream, fuse.OK return stream, fuse.OK
} }
func (n *memNode) Open(flags uint32, context *fuse.Context) (fuseFile fuse.File, code fuse.Status) { func (n *memNode) Open(flags uint32, context *fuse.Context) (fuseFile nodefs.File, code fuse.Status) {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM return nil, fuse.EPERM
} }
return fuse.NewDataFile(n.file.Data()), fuse.OK return nodefs.NewDataFile(n.file.Data()), fuse.OK
} }
func (n *memNode) Deletable() bool { func (n *memNode) Deletable() bool {
return false return false
} }
func (n *memNode) GetAttr(out *fuse.Attr, file fuse.File, context *fuse.Context) fuse.Status { func (n *memNode) GetAttr(out *fuse.Attr, file nodefs.File, context *fuse.Context) fuse.Status {
if n.Inode().IsDir() { if n.Inode().IsDir() {
out.Mode = fuse.S_IFDIR | 0777 out.Mode = fuse.S_IFDIR | 0777
return fuse.OK return fuse.OK
...@@ -113,7 +114,7 @@ func (n *MemTreeFs) addFile(name string, f MemFile) { ...@@ -113,7 +114,7 @@ func (n *MemTreeFs) addFile(name string, f MemFile) {
for i, c := range comps { for i, c := range comps {
child := node.GetChild(c) child := node.GetChild(c)
if child == nil { if child == nil {
fsnode := &memNode{FsNode: fuse.NewDefaultFsNode()} fsnode := &memNode{Node: nodefs.NewDefaultNode()}
if i == len(comps)-1 { if i == len(comps)-1 {
fsnode.file = f fsnode.file = f
} }
......
...@@ -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/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -19,7 +20,7 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) { ...@@ -19,7 +20,7 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
fs := NewMultiZipFs() fs := NewMultiZipFs()
mountPoint, _ = ioutil.TempDir("", "") mountPoint, _ = ioutil.TempDir("", "")
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, &fuse.FileSystemOptions{ state, _, err := nodefs.MountFileSystem(mountPoint, nfs, &nodefs.Options{
EntryTimeout: testTtl, EntryTimeout: testTtl,
AttrTimeout: testTtl, AttrTimeout: testTtl,
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
......
package zipfs package zipfs
import ( import (
"github.com/hanwen/go-fuse/fuse"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
) )
func testZipFile() string { func testZipFile() string {
...@@ -25,7 +27,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) { ...@@ -25,7 +27,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) {
} }
mountPoint, _ = ioutil.TempDir("", "") mountPoint, _ = ioutil.TempDir("", "")
state, _, err := fuse.MountNodeFileSystem(mountPoint, zfs, nil) state, _, err := nodefs.MountFileSystem(mountPoint, zfs, nil)
state.SetDebug(fuse.VerboseTest()) state.SetDebug(fuse.VerboseTest())
go state.Loop() go state.Loop()
......
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