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,24 +12,24 @@ import (
"testing"
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
func setupFs(fs pathfs.FileSystem) (string, func()) {
opts := &fuse.FileSystemOptions{
opts := &nodefs.Options{
EntryTimeout: 0.0,
AttrTimeout: 0.0,
NegativeTimeout: 0.0,
}
mountPoint, _ := ioutil.TempDir("", "stat_test")
nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, opts)
state, _, err := nodefs.MountFileSystem(mountPoint, nfs, opts)
if err != nil {
panic(fmt.Sprintf("cannot mount %v", err)) // ugh - benchmark has no error methods.
}
lmap := NewLatencyMap()
state.RecordLatencies(lmap)
// state.SetDebug(true)
go state.Loop()
......
......@@ -7,6 +7,7 @@ import (
"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/unionfs"
)
......@@ -43,7 +44,7 @@ func main() {
}
options := unionfs.AutoUnionFsOptions{
UnionFsOptions: ufsOptions,
FileSystemOptions: fuse.FileSystemOptions{
Options: nodefs.Options{
EntryTimeout: time.Second,
AttrTimeout: time.Second,
NegativeTimeout: time.Second,
......@@ -55,13 +56,13 @@ func main() {
},
HideReadonly: *hide_readonly_link,
}
fsOpts := fuse.FileSystemOptions{
fsOpts := nodefs.Options{
PortableInodes: *portableInodes,
}
fmt.Printf("AutoUnionFs - Go-FUSE Version %v.\n", fuse.Version())
gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options)
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 {
fmt.Printf("Mount fail: %v\n", err)
os.Exit(1)
......
......@@ -7,6 +7,7 @@ import (
"log"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -36,14 +37,14 @@ func (me *HelloFs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntr
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" {
return nil, fuse.ENOENT
}
if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM
}
return fuse.NewDataFile([]byte(name)), fuse.OK
return nodefs.NewDataFile([]byte(name)), fuse.OK
}
func main() {
......@@ -52,7 +53,7 @@ func main() {
log.Fatal("Usage:\n hello MOUNTPOINT")
}
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 {
log.Fatal("Mount fail: %v\n", err)
}
......
......@@ -12,6 +12,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -34,7 +35,7 @@ func main() {
loopbackfs := pathfs.NewLoopbackFileSystem(orig)
finalFs = loopbackfs
opts := &fuse.FileSystemOptions{
opts := &nodefs.Options{
// These options are to be compatible with libfuse defaults,
// making benchmarking easier.
NegativeTimeout: time.Second,
......@@ -42,7 +43,7 @@ func main() {
EntryTimeout: time.Second,
}
pathFs := pathfs.NewPathNodeFs(finalFs, nil)
conn := fuse.NewFileSystemConnector(pathFs, opts)
conn := nodefs.NewFileSystemConnector(pathFs, opts)
state := fuse.NewMountState(conn.RawFS())
state.SetDebug(*debug)
......
......@@ -5,14 +5,11 @@ package main
import (
"flag"
"fmt"
"github.com/hanwen/go-fuse/fuse"
"log"
"os"
"runtime"
)
var _ = runtime.GOMAXPROCS
var _ = log.Print
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
func main() {
// Scans the arg list and sets up flags
......@@ -26,9 +23,9 @@ func main() {
mountPoint := flag.Arg(0)
prefix := flag.Arg(1)
fs := fuse.NewMemNodeFs(prefix)
conn := fuse.NewFileSystemConnector(fs, nil)
state := fuse.NewMountState(conn)
fs := nodefs.NewMemNodeFs(prefix)
conn := nodefs.NewFileSystemConnector(fs, nil)
state := fuse.NewMountState(conn.RawFS())
state.SetDebug(*debug)
fmt.Println("Mounting")
......
......@@ -7,7 +7,7 @@ import (
"os"
"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/zipfs"
)
......@@ -26,7 +26,7 @@ func main() {
fs := zipfs.NewMultiZipFs()
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 {
fmt.Printf("Mount fail: %v\n", err)
os.Exit(1)
......
......@@ -7,7 +7,7 @@ import (
"os"
"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/unionfs"
)
......@@ -42,13 +42,13 @@ func main() {
os.Exit(1)
}
nodeFs := pathfs.NewPathNodeFs(ufs, &pathfs.PathNodeFsOptions{ClientInodes: true})
mOpts := fuse.FileSystemOptions{
mOpts := nodefs.Options{
EntryTimeout: time.Duration(*entry_ttl * float64(time.Second)),
AttrTimeout: time.Duration(*entry_ttl * float64(time.Second)),
NegativeTimeout: time.Duration(*negative_ttl * float64(time.Second)),
PortableInodes: *portable,
}
mountState, _, err := fuse.MountNodeFileSystem(flag.Arg(0), nodeFs, &mOpts)
mountState, _, err := nodefs.MountFileSystem(flag.Arg(0), nodeFs, &mOpts)
if err != nil {
log.Fatal("Mount fail:", err)
}
......
......@@ -3,8 +3,6 @@ package main
import (
"flag"
"fmt"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/zipfs"
"io"
"log"
"os"
......@@ -13,9 +11,10 @@ import (
"runtime/pprof"
"strings"
"time"
)
var _ = log.Printf
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/zipfs"
)
func main() {
// Scans the arg list and sets up flags
......@@ -45,18 +44,18 @@ func main() {
}
}
var fs fuse.NodeFileSystem
var fs nodefs.FileSystem
fs, err = zipfs.NewArchiveFileSystem(flag.Arg(1))
if err != nil {
fmt.Fprintf(os.Stderr, "NewArchiveFileSystem failed: %v\n", err)
os.Exit(1)
}
opts := &fuse.FileSystemOptions{
opts := &nodefs.Options{
AttrTimeout: 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 {
fmt.Printf("Mount fail: %v\n", err)
os.Exit(1)
......
// The fuse package provides APIs to implement filesystems in
// userspace. Typically, each call of the API happens in its own
// goroutine, so take care to make the file system thread-safe.
package fuse
import (
"time"
"github.com/hanwen/go-fuse/raw"
)
// 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
// reasons, we can also return data as a file-descriptor/offset/size
// tuple. If the backing store for a file is another filesystem, this
......@@ -148,41 +28,6 @@ type ReadResult interface {
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 {
AllowOther bool
......@@ -275,7 +120,7 @@ type RawFileSystem interface {
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.
Init(params *RawFsInit)
......
......@@ -2,13 +2,13 @@ package fuse
import (
"fmt"
"log"
"strings"
"sync"
"unsafe"
)
var _ = log.Println
var paranoia bool
type BufferPool interface {
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 {
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
}
......
......@@ -24,17 +24,20 @@ type DirEntry struct {
type DirEntryList struct {
buf []byte
size int
offset uint64
// TODO - hide this again.
Offset uint64
}
func NewDirEntryList(data []byte, off uint64) *DirEntryList {
return &DirEntryList{
buf: data[:0],
size: len(data),
offset: off,
Offset: off,
}
}
// AddDirEntry tries to add an entry.
func (l *DirEntryList) AddDirEntry(e DirEntry) bool {
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 {
}
l.buf = l.buf[:newLen]
dirent := (*raw.Dirent)(unsafe.Pointer(&l.buf[oldLen]))
dirent.Off = l.offset + 1
dirent.Off = l.Offset + 1
dirent.Ino = inode
dirent.NameLen = uint32(len(name))
dirent.Typ = ModeToType(mode)
......@@ -62,7 +65,7 @@ func (l *DirEntryList) Add(name string, inode uint64, mode uint32) bool {
copy(l.buf[oldLen:], eightPadding[:padding])
}
l.offset = dirent.Off
l.Offset = dirent.Off
return true
}
......@@ -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) {
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()()
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 (
"os"
"reflect"
"syscall"
"time"
"unsafe"
)
......@@ -61,12 +60,6 @@ func ToStatus(err error) Status {
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 {
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 (
"time"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
)
type defaultFile struct{}
......@@ -25,50 +26,50 @@ func (f *defaultFile) String() string {
return "defaultFile"
}
func (f *defaultFile) Read(buf []byte, off int64) (ReadResult, Status) {
return nil, ENOSYS
func (f *defaultFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
return nil, fuse.ENOSYS
}
func (f *defaultFile) Write(data []byte, off int64) (uint32, Status) {
return 0, ENOSYS
func (f *defaultFile) Write(data []byte, off int64) (uint32, fuse.Status) {
return 0, fuse.ENOSYS
}
func (f *defaultFile) Flush() Status {
return OK
func (f *defaultFile) Flush() fuse.Status {
return fuse.OK
}
func (f *defaultFile) Release() {
}
func (f *defaultFile) GetAttr(*Attr) Status {
return ENOSYS
func (f *defaultFile) GetAttr(*fuse.Attr) fuse.Status {
return fuse.ENOSYS
}
func (f *defaultFile) Fsync(flags int) (code Status) {
return ENOSYS
func (f *defaultFile) Fsync(flags int) (code fuse.Status) {
return fuse.ENOSYS
}
func (f *defaultFile) Utimens(atime *time.Time, mtime *time.Time) Status {
return ENOSYS
func (f *defaultFile) Utimens(atime *time.Time, mtime *time.Time) fuse.Status {
return fuse.ENOSYS
}
func (f *defaultFile) Truncate(size uint64) Status {
return ENOSYS
func (f *defaultFile) Truncate(size uint64) fuse.Status {
return fuse.ENOSYS
}
func (f *defaultFile) Chown(uid uint32, gid uint32) Status {
return ENOSYS
func (f *defaultFile) Chown(uid uint32, gid uint32) fuse.Status {
return fuse.ENOSYS
}
func (f *defaultFile) Chmod(perms uint32) Status {
return ENOSYS
func (f *defaultFile) Chmod(perms uint32) fuse.Status {
return fuse.ENOSYS
}
func (f *defaultFile) Ioctl(input *raw.IoctlIn) (output *raw.IoctlOut, data []byte, code Status) {
return nil, nil, ENOSYS
func (f *defaultFile) Ioctl(input *raw.IoctlIn) (output *raw.IoctlOut, data []byte, code fuse.Status) {
return nil, nil, fuse.ENOSYS
}
func (f *defaultFile) Allocate(off uint64, size uint64, mode uint32) (code Status) {
return ENOSYS
func (f *defaultFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) {
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 (
"fmt"
"os"
"sync"
"syscall"
"github.com/hanwen/go-fuse/fuse"
)
var _ = fmt.Println
......@@ -28,10 +30,10 @@ func (f *dataFile) String() string {
return fmt.Sprintf("dataFile(%x)", f.data[:l])
}
func (f *dataFile) GetAttr(out *Attr) Status {
out.Mode = S_IFREG | 0644
func (f *dataFile) GetAttr(out *fuse.Attr) fuse.Status {
out.Mode = fuse.S_IFREG | 0644
out.Size = uint64(len(f.data))
return OK
return fuse.OK
}
func NewDataFile(data []byte) File {
......@@ -41,13 +43,13 @@ func NewDataFile(data []byte) File {
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))
if 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 {
}
}
func (f *devNullFile) Allocate(off uint64, size uint64, mode uint32) (code Status) {
return OK
func (f *devNullFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) {
return fuse.OK
}
func (f *devNullFile) String() string {
return "devNullFile"
}
func (f *devNullFile) Read(buf []byte, off int64) (ReadResult, Status) {
return &ReadResultData{}, OK
func (f *devNullFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
return &fuse.ReadResultData{}, fuse.OK
}
func (f *devNullFile) Write(content []byte, off int64) (uint32, Status) {
return uint32(len(content)), OK
func (f *devNullFile) Write(content []byte, off int64) (uint32, fuse.Status) {
return uint32(len(content)), fuse.OK
}
func (f *devNullFile) Flush() Status {
return OK
func (f *devNullFile) Flush() fuse.Status {
return fuse.OK
}
func (f *devNullFile) Fsync(flags int) (code Status) {
return OK
func (f *devNullFile) Fsync(flags int) (code fuse.Status) {
return fuse.OK
}
func (f *devNullFile) Truncate(size uint64) (code Status) {
return OK
func (f *devNullFile) Truncate(size uint64) (code fuse.Status) {
return fuse.OK
}
////////////////
......@@ -124,22 +126,22 @@ func (f *loopbackFile) String() string {
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()
r := &ReadResultFd{
r := &fuse.ReadResultFd{
Fd: f.File.Fd(),
Off: off,
Sz: len(buf),
}
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()
n, err := f.File.WriteAt(data, off)
f.lock.Unlock()
return uint32(n), ToStatus(err)
return uint32(n), fuse.ToStatus(err)
}
func (f *loopbackFile) Release() {
......@@ -148,7 +150,7 @@ func (f *loopbackFile) Release() {
f.lock.Unlock()
}
func (f *loopbackFile) Flush() Status {
func (f *loopbackFile) Flush() fuse.Status {
f.lock.Lock()
// Since Flush() may be called for each dup'd fd, we don't
......@@ -158,55 +160,55 @@ func (f *loopbackFile) Flush() Status {
f.lock.Unlock()
if err != nil {
return ToStatus(err)
return fuse.ToStatus(err)
}
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()
r := ToStatus(syscall.Fsync(int(f.File.Fd())))
r := fuse.ToStatus(syscall.Fsync(int(f.File.Fd())))
f.lock.Unlock()
return r
}
func (f *loopbackFile) Truncate(size uint64) Status {
func (f *loopbackFile) Truncate(size uint64) fuse.Status {
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()
return r
}
func (f *loopbackFile) Chmod(mode uint32) Status {
func (f *loopbackFile) Chmod(mode uint32) fuse.Status {
f.lock.Lock()
r := ToStatus(f.File.Chmod(os.FileMode(mode)))
r := fuse.ToStatus(f.File.Chmod(os.FileMode(mode)))
f.lock.Unlock()
return r
}
func (f *loopbackFile) Chown(uid uint32, gid uint32) Status {
func (f *loopbackFile) Chown(uid uint32, gid uint32) fuse.Status {
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()
return r
}
func (f *loopbackFile) GetAttr(a *Attr) Status {
func (f *loopbackFile) GetAttr(a *fuse.Attr) fuse.Status {
st := syscall.Stat_t{}
f.lock.Lock()
err := syscall.Fstat(int(f.File.Fd()), &st)
f.lock.Unlock()
if err != nil {
return ToStatus(err)
return fuse.ToStatus(err)
}
a.FromStat(&st)
return OK
return fuse.OK
}
// Allocate, Utimens implemented in files_linux.go
......@@ -228,26 +230,26 @@ func (f *readOnlyFile) String() string {
return fmt.Sprintf("readOnlyFile(%s)", f.File.String())
}
func (f *readOnlyFile) Write(data []byte, off int64) (uint32, Status) {
return 0, EPERM
func (f *readOnlyFile) Write(data []byte, off int64) (uint32, fuse.Status) {
return 0, fuse.EPERM
}
func (f *readOnlyFile) Fsync(flag int) (code Status) {
return OK
func (f *readOnlyFile) Fsync(flag int) (code fuse.Status) {
return fuse.OK
}
func (f *readOnlyFile) Truncate(size uint64) Status {
return EPERM
func (f *readOnlyFile) Truncate(size uint64) fuse.Status {
return fuse.EPERM
}
func (f *readOnlyFile) Chmod(mode uint32) Status {
return EPERM
func (f *readOnlyFile) Chmod(mode uint32) fuse.Status {
return fuse.EPERM
}
func (f *readOnlyFile) Chown(uid uint32, gid uint32) Status {
return EPERM
func (f *readOnlyFile) Chown(uid uint32, gid uint32) fuse.Status {
return fuse.EPERM
}
func (f *readOnlyFile) Allocate(off uint64, sz uint64, mode uint32) Status {
return EPERM
func (f *readOnlyFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status {
return fuse.EPERM
}
package fuse
package nodefs
import (
"time"
"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()
err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz))
f.lock.Unlock()
if err != nil {
return ToStatus(err)
return fuse.ToStatus(err)
}
return OK
return fuse.OK
}
const _UTIME_NOW = ((1 << 30) - 1)
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)
if a == nil {
tv[0].Usec = _UTIME_OMIT
......@@ -35,5 +37,5 @@ func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) Status {
}
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
// FileSystemConnector. The functions for satisfying the raw interface
......@@ -13,6 +13,7 @@ import (
"unsafe"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
)
// Tests should set to true.
......@@ -35,9 +36,9 @@ type FileSystemConnector struct {
debug bool
// Callbacks for talking back to the kernel.
fsInit RawFsInit
fsInit fuse.RawFsInit
nodeFs NodeFileSystem
nodeFs FileSystem
// Translate between uint64 handles and *Inode.
inodeMap handleMap
......@@ -46,19 +47,19 @@ type FileSystemConnector struct {
rootNode *Inode
}
func NewFileSystemOptions() *FileSystemOptions {
return &FileSystemOptions{
func NewOptions() *Options {
return &Options{
NegativeTimeout: 0,
AttrTimeout: 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)
if opts == nil {
opts = NewFileSystemOptions()
opts = NewOptions()
}
c.nodeFs = nodeFs
c.inodeMap = newHandleMap(opts.PortableInodes)
......@@ -95,9 +96,9 @@ func (c *FileSystemConnector) verify() {
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()
fsi.GetAttr((*Attr)(&out.Attr), nil, nil)
fsi.GetAttr((*fuse.Attr)(&out.Attr), nil, nil)
n.mount.fillEntry(out)
out.Ino = c.fsConn().lookupUpdate(n)
out.NodeId = out.Ino
......@@ -167,7 +168,7 @@ func (c *FileSystemConnector) recursiveConsiderDropInode(n *Inode) (drop bool) {
ch.fsInode.OnForget()
}
if len(n.children) > 0 || !n.FsNode().Deletable() {
if len(n.children) > 0 || !n.Node().Deletable() {
return false
}
if n == c.rootNode || n.mountPoint != nil {
......@@ -228,7 +229,7 @@ func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode {
}
components := strings.Split(path, "/")
for _, r := range components {
var a Attr
var a fuse.Attr
child, _ := c.internalLookup(&a, parent, r, nil)
if child == nil {
return nil
......@@ -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.mount.connector = c
nodeFs.OnMount(c)
......@@ -260,13 +261,13 @@ func (c *FileSystemConnector) MountRoot(nodeFs NodeFileSystem, opts *FileSystemO
// ENOENT: the directory containing the mount point does not exist.
//
// 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()
parent.mount.treeLock.Lock()
defer parent.mount.treeLock.Unlock()
node := parent.children[name]
if node != nil {
return EBUSY
return fuse.EBUSY
}
node = newInode(true, nodeFs.Root())
......@@ -284,7 +285,7 @@ func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFileS
"parent", c.inodeMap.Handle(&parent.handled))
}
nodeFs.OnMount(c)
return OK
return fuse.OK
}
// Unmount() tries to unmount the given inode.
......@@ -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.
//
// 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.
if node.mountPoint == nil {
log.Println("not a mountpoint:", c.inodeMap.Handle(&node.handled))
return EINVAL
return fuse.EINVAL
}
nodeId := c.inodeMap.Handle(&node.handled)
......@@ -311,7 +312,7 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
mount := node.mountPoint
name := node.mountPoint.mountName()
if mount.openFiles.Count() > 0 {
return EBUSY
return fuse.EBUSY
}
node.mount.treeLock.Lock()
......@@ -324,7 +325,7 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
}
if !node.canUnmount() {
return EBUSY
return fuse.EBUSY
}
delete(parentNode.children, name)
......@@ -360,10 +361,10 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
mount.mountInode = 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
if node == c.rootNode {
nId = raw.FUSE_ROOT_ID
......@@ -372,7 +373,7 @@ func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) S
}
if nId == 0 {
return OK
return fuse.OK
}
out := raw.NotifyInvalInodeOut{
Length: length,
......@@ -382,7 +383,7 @@ func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) S
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
if node == c.rootNode {
nId = raw.FUSE_ROOT_ID
......@@ -391,12 +392,12 @@ func (c *FileSystemConnector) EntryNotify(node *Inode, name string) Status {
}
if nId == 0 {
return OK
return fuse.OK
}
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
if dir == c.rootNode {
......@@ -406,7 +407,7 @@ func (c *FileSystemConnector) DeleteNotify(dir *Inode, child *Inode, name string
}
if nId == 0 {
return OK
return fuse.OK
}
chId := c.inodeMap.Handle(&child.handled)
......
package fuse
package nodefs
import (
"log"
"sync"
"unsafe"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw"
)
......@@ -21,7 +22,7 @@ type openedFile struct {
type fileSystemMount struct {
// The file system we mounted here.
fs NodeFileSystem
fs FileSystem
// Node that we were mounted on.
mountInode *Inode
......@@ -30,7 +31,7 @@ type fileSystemMount struct {
parentInode *Inode
// Options for the mount.
options *FileSystemOptions
options *Options
// Protects Children hashmaps within the mount. treeLock
// should be acquired before openFilesLock.
......@@ -68,7 +69,7 @@ func (m *fileSystemMount) fillEntry(out *raw.EntryOut) {
splitDuration(m.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec)
splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
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
}
}
......
This diff is collapsed.
package fuse
package nodefs
import "log"
var _ = log.Println
func MountNodeFileSystem(mountpoint string, nodeFs NodeFileSystem, opts *FileSystemOptions) (*MountState, *FileSystemConnector, error) {
import (
"github.com/hanwen/go-fuse/fuse"
)
func MountFileSystem(mountpoint string, nodeFs FileSystem, opts *Options) (*fuse.MountState, *FileSystemConnector, error) {
conn := NewFileSystemConnector(nodeFs, opts)
mountState := NewMountState(conn.RawFS())
mountState := fuse.NewMountState(conn.RawFS())
err := mountState.Mount(mountpoint, nil)
if err != nil {
return nil, nil, err
......
package fuse
package nodefs
import (
"fmt"
......
package fuse
package nodefs
import (
"log"
......
package fuse
package nodefs
import (
"log"
"sync"
"github.com/hanwen/go-fuse/fuse"
)
var _ = log.Println
// The inode reflects the kernel's idea of the inode. Inodes may be
// created automatically when the kernel does lookups inode, or by
......@@ -21,7 +22,7 @@ type Inode struct {
openFilesMutex sync.Mutex
openFiles []*openedFile
fsInode FsNode
fsInode Node
// Each inode belongs to exactly one fileSystemMount. This
// pointer is constant during the lifetime, except upon
......@@ -36,7 +37,7 @@ type Inode struct {
mountPoint *fileSystemMount
}
func newInode(isDir bool, fsNode FsNode) *Inode {
func newInode(isDir bool, fsNode Node) *Inode {
me := new(Inode)
if isDir {
me.children = make(map[string]*Inode, initDirSize)
......@@ -52,7 +53,7 @@ func newInode(isDir bool, fsNode FsNode) *Inode {
func (n *Inode) AnyFile() (file File) {
n.openFilesMutex.Lock()
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
}
}
......@@ -87,7 +88,7 @@ func (n *Inode) FsChildren() (out map[string]*Inode) {
return out
}
func (n *Inode) FsNode() FsNode {
func (n *Inode) Node() Node {
return n.fsInode
}
......@@ -108,7 +109,7 @@ func (n *Inode) IsDir() bool {
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.mount = n.mount
n.generation = ch.mount.connector.nextGeneration()
......@@ -163,7 +164,7 @@ func (n *Inode) rmChild(name string) (ch *Inode) {
}
// 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{
fs: fs,
openFiles: newHandleMap(false),
......@@ -192,13 +193,13 @@ func (n *Inode) canUnmount() bool {
return ok
}
func (n *Inode) getMountDirEntries() (out []DirEntry) {
func (n *Inode) getMountDirEntries() (out []fuse.DirEntry) {
n.mount.treeLock.RLock()
for k, v := range n.children {
if v.mountPoint != nil {
out = append(out, DirEntry{
out = append(out, fuse.DirEntry{
Name: k,
Mode: S_IFDIR,
Mode: fuse.S_IFDIR,
})
}
}
......
package fuse
package nodefs
import (
"fmt"
......@@ -7,6 +7,8 @@ import (
"sync"
"syscall"
"time"
"github.com/hanwen/go-fuse/fuse"
)
var _ = log.Println
......@@ -23,7 +25,7 @@ func (fs *MemNodeFs) String() string {
return fmt.Sprintf("MemNodeFs(%s)", fs.backingStorePrefix)
}
func (fs *MemNodeFs) Root() FsNode {
func (fs *MemNodeFs) Root() Node {
return fs.root
}
......@@ -39,13 +41,13 @@ func (fs *MemNodeFs) OnUnmount() {
func (fs *MemNodeFs) newNode() *memNode {
fs.mutex.Lock()
n := &memNode{
FsNode: NewDefaultFsNode(),
Node: NewDefaultNode(),
fs: fs,
id: fs.nextFree,
}
now := time.Now()
n.info.SetTimes(&now, &now, &now)
n.info.Mode = S_IFDIR | 0777
n.info.Mode = fuse.S_IFDIR | 0777
fs.nextFree++
fs.mutex.Unlock()
return n
......@@ -60,17 +62,17 @@ func NewMemNodeFs(prefix string) *MemNodeFs {
}
func (fs *MemNodeFs) Filename(n *Inode) string {
mn := n.FsNode().(*memNode)
mn := n.Node().(*memNode)
return mn.filename()
}
type memNode struct {
FsNode
Node
fs *MemNodeFs
id int
link string
info Attr
info fuse.Attr
}
func (n *memNode) newNode(isdir bool) *memNode {
......@@ -87,60 +89,60 @@ func (n *memNode) Deletable() bool {
return false
}
func (n *memNode) Readlink(c *Context) ([]byte, Status) {
return []byte(n.link), OK
func (n *memNode) Readlink(c *fuse.Context) ([]byte, fuse.Status) {
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.info.Mode = mode | S_IFDIR
ch.info.Mode = mode | fuse.S_IFDIR
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)
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)
}
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.info.Mode = S_IFLNK | 0777
ch.info.Mode = fuse.S_IFLNK | 0777
ch.link = content
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)
newParent.Inode().RmChild(newName)
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())
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.info.Mode = mode | S_IFREG
ch.info.Mode = mode | fuse.S_IFREG
f, err := os.Create(ch.filename())
if err != nil {
return nil, nil, ToStatus(err)
return nil, nil, fuse.ToStatus(err)
}
n.Inode().AddChild(name, ch.Inode())
return ch.newFile(f), ch, OK
return ch.newFile(f), ch, fuse.OK
}
type memNodeFile struct {
......@@ -156,7 +158,7 @@ func (n *memNodeFile) InnerFile() File {
return n.File
}
func (n *memNodeFile) Flush() Status {
func (n *memNodeFile) Flush() fuse.Status {
code := n.File.Flush()
if !code.Ok() {
......@@ -167,7 +169,7 @@ func (n *memNodeFile) Flush() Status {
err := syscall.Stat(n.node.filename(), &st)
n.node.info.Size = uint64(st.Size)
n.node.info.Blocks = uint64(st.Blocks)
return ToStatus(err)
return fuse.ToStatus(err)
}
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)
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
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 {
code = file.Truncate(size)
} else {
err := os.Truncate(n.filename(), int64(size))
code = ToStatus(err)
code = fuse.ToStatus(err)
}
if code.Ok() {
now := time.Now()
......@@ -207,23 +209,23 @@ func (n *memNode) Truncate(file File, size uint64, context *Context) (code Statu
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()
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
now := time.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.Gid = gid
now := time.Now()
n.info.SetTimes(nil, nil, &now)
return OK
return fuse.OK
}
package fuse
package nodefs
import (
"io/ioutil"
......@@ -6,6 +6,8 @@ import (
"os"
"testing"
"time"
"github.com/hanwen/go-fuse/fuse"
)
var _ = log.Println
......@@ -24,17 +26,17 @@ func setupMemNodeTest(t *testing.T) (wd string, fs *MemNodeFs, clean func()) {
os.Mkdir(mnt, 0700)
connector := NewFileSystemConnector(fs,
&FileSystemOptions{
&Options{
EntryTimeout: testTtl,
AttrTimeout: testTtl,
NegativeTimeout: 0.0,
})
connector.SetDebug(VerboseTest())
state := NewMountState(connector.RawFS())
connector.SetDebug(fuse.VerboseTest())
state := fuse.NewMountState(connector.RawFS())
state.Mount(mnt, nil)
//me.state.SetDebug(false)
state.SetDebug(VerboseTest())
state.SetDebug(fuse.VerboseTest())
// Unthreaded, but in background.
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) {
}
func doStatFs(state *MountState, req *request) {
stat := (*StatfsOut)(req.outData)
stat := (*raw.StatfsOut)(req.outData)
req.status = state.fileSystem.StatFs(stat, &req.context)
}
......@@ -431,7 +431,7 @@ func init() {
_OP_LINK: unsafe.Sizeof(raw.EntryOut{}),
_OP_OPEN: unsafe.Sizeof(raw.OpenOut{}),
_OP_WRITE: unsafe.Sizeof(raw.WriteOut{}),
_OP_STATFS: unsafe.Sizeof(StatfsOut{}),
_OP_STATFS: unsafe.Sizeof(raw.StatfsOut{}),
_OP_GETXATTR: unsafe.Sizeof(raw.GetXAttrOut{}),
_OP_LISTXATTR: unsafe.Sizeof(raw.GetXAttrOut{}),
_OP_INIT: unsafe.Sizeof(raw.InitOut{}),
......@@ -549,7 +549,7 @@ func init() {
_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_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
}
......
......@@ -4,6 +4,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
// A filesystem API that uses paths rather than inodes. A minimal
......@@ -54,8 +55,8 @@ type FileSystem interface {
// File handling. If opening for writing, the file's mtime
// should be updated too.
Open(name string, flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status)
Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, code fuse.Status)
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 nodefs.File, code fuse.Status)
// Directory handling
OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, code fuse.Status)
......@@ -64,7 +65,7 @@ type FileSystem interface {
Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status)
Readlink(name string, context *fuse.Context) (string, fuse.Status)
StatFs(name string) *fuse.StatfsOut
StatFs(name string) *nodefs.StatfsOut
}
type PathNodeFsOptions struct {
......
......@@ -4,6 +4,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
// NewDefaultFileSystem creates a filesystem that responds ENOSYS for
......@@ -80,7 +81,7 @@ func (fs *defaultFileSystem) Truncate(name string, offset uint64, context *fuse.
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
}
......@@ -98,7 +99,7 @@ func (fs *defaultFileSystem) Access(name string, mode uint32, context *fuse.Cont
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
}
......@@ -110,6 +111,6 @@ func (fs *defaultFileSystem) String() string {
return "defaultFileSystem"
}
func (fs *defaultFileSystem) StatFs(name string) *fuse.StatfsOut {
func (fs *defaultFileSystem) StatFs(name string) *nodefs.StatfsOut {
return nil
}
......@@ -5,6 +5,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
type lockingFileSystem struct {
......@@ -29,7 +30,7 @@ func (fs *lockingFileSystem) String() string {
return fs.FS.String()
}
func (fs *lockingFileSystem) StatFs(name string) *fuse.StatfsOut {
func (fs *lockingFileSystem) StatFs(name string) *nodefs.StatfsOut {
defer fs.locked()()
return fs.FS.StatFs(name)
}
......@@ -99,7 +100,7 @@ func (fs *lockingFileSystem) Truncate(name string, offset uint64, context *fuse.
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)
}
......@@ -123,7 +124,7 @@ func (fs *lockingFileSystem) Access(name string, mode uint32, context *fuse.Cont
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()()
return fs.FS.Create(name, flags, mode, context)
}
......
......@@ -10,6 +10,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
var _ = fmt.Println
......@@ -27,7 +28,7 @@ type loopbackFileSystem struct {
func NewLoopbackFileSystem(root string) FileSystem {
return &loopbackFileSystem{
FileSystem: NewDefaultFileSystem(),
Root: root,
Root: root,
}
}
......@@ -98,12 +99,12 @@ func (fs *loopbackFileSystem) OpenDir(name string, context *fuse.Context) (strea
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)
if err != nil {
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) {
......@@ -170,7 +171,7 @@ func (fs *loopbackFileSystem) Access(name string, mode uint32, context *fuse.Con
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))
return fuse.NewLoopbackFile(f), fuse.ToStatus(err)
return nodefs.NewLoopbackFile(f), fuse.ToStatus(err)
}
......@@ -5,13 +5,14 @@ import (
"syscall"
"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{}
err := syscall.Statfs(fs.GetPath(name), &s)
if err == nil {
return &fuse.StatfsOut{
return &nodefs.StatfsOut{
Blocks: s.Blocks,
Bsize: uint32(s.Bsize),
Bfree: s.Bfree,
......
......@@ -7,6 +7,7 @@ import (
"testing"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
type ownerFs struct {
......@@ -29,12 +30,12 @@ func (fs *ownerFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse
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")
fs := &ownerFs{NewDefaultFileSystem()}
nfs := NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(wd, nfs, opts)
state, _, err := nodefs.MountFileSystem(wd, nfs, opts)
if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......@@ -46,7 +47,7 @@ func setupOwnerTest(t *testing.T, opts *fuse.FileSystemOptions) (workdir string,
}
func TestOwnerDefault(t *testing.T) {
wd, cleanup := setupOwnerTest(t, fuse.NewFileSystemOptions())
wd, cleanup := setupOwnerTest(t, nodefs.NewOptions())
defer cleanup()
var stat syscall.Stat_t
......@@ -61,7 +62,7 @@ func TestOwnerDefault(t *testing.T) {
}
func TestOwnerRoot(t *testing.T) {
wd, cleanup := setupOwnerTest(t, &fuse.FileSystemOptions{})
wd, cleanup := setupOwnerTest(t, &nodefs.Options{})
defer cleanup()
var st syscall.Stat_t
......@@ -76,7 +77,7 @@ func TestOwnerRoot(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()
var stat syscall.Stat_t
......
This diff is collapsed.
......@@ -6,12 +6,13 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
// PrefixFileSystem adds a path prefix to incoming calls.
type prefixFileSystem struct {
FileSystem FileSystem
Prefix string
Prefix string
}
func NewPrefixFileSystem(fs FileSystem, prefix string) FileSystem {
......@@ -70,7 +71,7 @@ func (fs *prefixFileSystem) Truncate(name string, offset uint64, context *fuse.C
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)
}
......@@ -90,7 +91,7 @@ func (fs *prefixFileSystem) Access(name string, mode uint32, context *fuse.Conte
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)
}
......@@ -118,6 +119,6 @@ func (fs *prefixFileSystem) String() string {
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))
}
......@@ -5,9 +5,9 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
// NewReadonlyFileSystem returns a wrapper that only exposes read-only
// operations.
func NewReadonlyFileSystem(fs FileSystem) FileSystem {
......@@ -68,12 +68,12 @@ func (fs *readonlyFileSystem) Truncate(name string, offset uint64, context *fuse
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 {
return nil, fuse.EPERM
}
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) {
......@@ -96,7 +96,7 @@ func (fs *readonlyFileSystem) Access(name string, mode uint32, context *fuse.Con
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
}
......
......@@ -40,4 +40,3 @@ func listXAttr(path string) (attributes []string, err error) {
}
return attributes, err
}
......@@ -10,6 +10,7 @@ import (
"testing"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
var _ = log.Print
......@@ -29,11 +30,11 @@ type XAttrTestFs struct {
func NewXAttrFs(nm string, m map[string][]byte) *XAttrTestFs {
x := &XAttrTestFs{
filename: nm,
attrs: make(map[string][]byte, len(m)),
filename: nm,
attrs: make(map[string][]byte, len(m)),
FileSystem: NewDefaultFileSystem(),
}
for k, v := range m {
x.attrs[k] = v
}
......@@ -114,7 +115,7 @@ func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func())
}
nfs := NewPathNodeFs(xfs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, nil)
state, _, err := nodefs.MountFileSystem(mountPoint, nfs, nil)
if err != nil {
t.Fatalf("TempDir failed: %v", err)
}
......
......@@ -9,6 +9,7 @@ import (
"testing"
"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/raw"
)
......@@ -19,12 +20,12 @@ type cacheFs struct {
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)
if !c.Ok() {
return f, c
}
return &fuse.WithFlags{
return &nodefs.WithFlags{
File: f,
FuseFlags: raw.FOPEN_KEEP_CACHE,
}, c
......@@ -43,7 +44,7 @@ func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
pathfs.NewLoopbackFileSystem(dir + "/orig"),
}
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 {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......@@ -120,14 +121,14 @@ func (fs *nonseekFs) GetAttr(name string, context *fuse.Context) (fi *fuse.Attr,
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" {
return nil, fuse.ENOENT
}
data := bytes.Repeat([]byte{42}, fs.Length)
f := fuse.NewDataFile(data)
return &fuse.WithFlags{
f := nodefs.NewDataFile(data)
return &nodefs.WithFlags{
File: f,
FuseFlags: raw.FOPEN_NONSEEKABLE,
}, fuse.OK
......@@ -143,7 +144,7 @@ func TestNonseekable(t *testing.T) {
}
defer os.RemoveAll(dir)
nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, nfs, nil)
state, _, err := nodefs.MountFileSystem(dir, nfs, nil)
if err != nil {
t.Fatalf("failed: %v", err)
}
......@@ -176,8 +177,8 @@ func TestGetAttrRace(t *testing.T) {
fs := pathfs.NewLoopbackFileSystem(dir + "/orig")
pfs := pathfs.NewPathNodeFs(fs, nil)
state, conn, err := fuse.MountNodeFileSystem(dir+"/mnt", pfs,
&fuse.FileSystemOptions{})
state, conn, err := nodefs.MountFileSystem(dir+"/mnt", pfs,
&nodefs.Options{})
if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......
......@@ -6,10 +6,10 @@ import (
"testing"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
type DefaultReadFS struct {
pathfs.FileSystem
size uint64
......@@ -26,8 +26,8 @@ func (fs *DefaultReadFS) GetAttr(name string, context *fuse.Context) (*fuse.Attr
return nil, fuse.ENOENT
}
func (fs *DefaultReadFS) Open(name string, f uint32, context *fuse.Context) (fuse.File, fuse.Status) {
return fuse.NewDefaultFile(), fuse.OK
func (fs *DefaultReadFS) Open(name string, f uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
return nodefs.NewDefaultFile(), fuse.OK
}
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)
}
pathfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, pathfs, nil)
state, _, err := nodefs.MountFileSystem(dir, pathfs, nil)
if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......
......@@ -10,21 +10,22 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
type flipNode struct {
fuse.FsNode
nodefs.Node
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 {
case <-f.ok:
// use a status that is easily recognizable.
return fuse.Status(syscall.EXDEV)
default:
}
return f.FsNode.GetAttr(out, file, c)
return f.Node.GetAttr(out, file, c)
}
func TestDeleteNotify(t *testing.T) {
......@@ -33,9 +34,9 @@ func TestDeleteNotify(t *testing.T) {
t.Fatalf("TempDir failed %v", err)
}
defer os.RemoveAll(dir)
fs := fuse.NewMemNodeFs(dir + "/backing")
conn := fuse.NewFileSystemConnector(fs,
&fuse.FileSystemOptions{PortableInodes: true})
fs := nodefs.NewMemNodeFs(dir + "/backing")
conn := nodefs.NewFileSystemConnector(fs,
&nodefs.Options{PortableInodes: true})
state := fuse.NewMountState(conn.RawFS())
mnt := dir + "/mnt"
err = os.Mkdir(mnt, 0755)
......@@ -56,10 +57,10 @@ func TestDeleteNotify(t *testing.T) {
}
ch := fs.Root().Inode().RmChild("testdir")
ch.FsNode().SetInode(nil)
ch.Node().SetInode(nil)
flip := flipNode{
FsNode: ch.FsNode(),
ok: make(chan int),
Node: ch.Node(),
ok: make(chan int),
}
newCh := fs.Root().Inode().New(true, &flip)
fs.Root().Inode().AddChild("testdir", newCh)
......@@ -100,7 +101,7 @@ func TestDeleteNotify(t *testing.T) {
// Simulate deletion+mkdir coming from the network
close(flip.ok)
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() {
t.Fatal("mkdir status", code)
}
......
......@@ -8,12 +8,13 @@ import (
"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/raw"
)
type MutableDataFile struct {
fuse.File
nodefs.File
data []byte
fuse.Attr
......@@ -111,14 +112,14 @@ func (fs *FSetAttrFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, f
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" {
return fs.file, fuse.OK
}
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" {
f := NewFile()
fs.file = f
......@@ -129,7 +130,7 @@ func (fs *FSetAttrFs) Create(name string, flags uint32, mode uint32, context *fu
}
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()) {
......@@ -138,7 +139,7 @@ func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func(
t.Fatalf("TempDir failed: %v", err)
}
nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(dir, nfs, nil)
state, _, err := nodefs.MountFileSystem(dir, nfs, nil)
if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......
......@@ -16,6 +16,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -39,7 +40,7 @@ type testCase struct {
tester *testing.T
state *fuse.MountState
pathFs *pathfs.PathNodeFs
connector *fuse.FileSystemConnector
connector *nodefs.FileSystemConnector
}
const testTtl = 100 * time.Millisecond
......@@ -78,8 +79,8 @@ func NewTestCase(t *testing.T) *testCase {
var rfs fuse.RawFileSystem
me.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{
ClientInodes: true})
me.connector = fuse.NewFileSystemConnector(me.pathFs,
&fuse.FileSystemOptions{
me.connector = nodefs.NewFileSystemConnector(me.pathFs,
&nodefs.Options{
EntryTimeout: testTtl,
AttrTimeout: testTtl,
NegativeTimeout: 0.0,
......@@ -108,7 +109,7 @@ func (tc *testCase) Cleanup() {
os.RemoveAll(tc.tmpDir)
}
func (tc *testCase) rootNode() *fuse.Inode {
func (tc *testCase) rootNode() *nodefs.Inode {
return tc.pathFs.Root().Inode()
}
......@@ -930,7 +931,7 @@ func TestOriginalIsSymlink(t *testing.T) {
fs := pathfs.NewLoopbackFileSystem(link)
nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mnt, nfs, nil)
state, _, err := nodefs.MountFileSystem(mnt, nfs, nil)
if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......
......@@ -8,6 +8,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -19,7 +20,7 @@ func TestMountOnExisting(t *testing.T) {
if err != nil {
t.Fatalf("Mkdir failed: %v", err)
}
nfs := fuse.NewDefaultNodeFileSystem()
nfs := nodefs.NewDefaultFileSystem()
code := ts.connector.Mount(ts.rootNode(), "mnt", nfs, nil)
if code != fuse.EBUSY {
t.Fatal("expect EBUSY:", code)
......
......@@ -8,6 +8,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -32,14 +33,14 @@ func (fs *NotifyFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fus
return nil, fuse.ENOENT
}
func (fs *NotifyFs) Open(name string, f uint32, context *fuse.Context) (fuse.File, fuse.Status) {
return fuse.NewDataFile([]byte{42}), fuse.OK
func (fs *NotifyFs) Open(name string, f uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
return nodefs.NewDataFile([]byte{42}), fuse.OK
}
type NotifyTest struct {
fs *NotifyFs
pathfs *pathfs.PathNodeFs
connector *fuse.FileSystemConnector
connector *nodefs.FileSystemConnector
dir string
state *fuse.MountState
}
......@@ -53,14 +54,14 @@ func NewNotifyTest(t *testing.T) *NotifyTest {
t.Fatalf("TempDir failed: %v", err)
}
entryTtl := 100 * time.Millisecond
opts := &fuse.FileSystemOptions{
opts := &nodefs.Options{
EntryTimeout: entryTtl,
AttrTimeout: entryTtl,
NegativeTimeout: entryTtl,
}
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 {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......
package fuse
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), ""))
}
func (a *Attr) String() string {
return ((*raw.Attr)(a)).String()
}
......@@ -51,4 +51,3 @@ type Context struct {
*raw.Context
}
type StatfsOut raw.StatfsOut
......@@ -12,12 +12,13 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
type knownFs struct {
unionFS pathfs.FileSystem
nodeFS *pathfs.PathNodeFs
nodeFS *pathfs.PathNodeFs
}
// Creates unions for all files under a given directory,
......@@ -28,7 +29,7 @@ type knownFs struct {
type autoUnionFs struct {
pathfs.FileSystem
debug bool
lock sync.RWMutex
knownFileSystems map[string]knownFs
nameRootMap map[string]string
......@@ -38,12 +39,13 @@ type autoUnionFs struct {
options *AutoUnionFsOptions
mountState *fuse.MountState
connector *fuse.FileSystemConnector
connector *nodefs.FileSystemConnector
}
type AutoUnionFsOptions struct {
UnionFsOptions
fuse.FileSystemOptions
nodefs.Options
pathfs.PathNodeFsOptions
// If set, run updateKnownFses() after mounting.
......@@ -68,21 +70,21 @@ const (
// FileSystemConnector
type RootFileSystem interface {
SetMountState(state *fuse.MountState)
SetFileSystemConnector(conn *fuse.FileSystemConnector)
SetFileSystemConnector(conn *nodefs.FileSystemConnector)
pathfs.FileSystem
}
func NewAutoUnionFs(directory string, options AutoUnionFsOptions) RootFileSystem {
if options.HideReadonly {
options.HiddenFiles = append(options.HiddenFiles, _READONLY)
}
a := &autoUnionFs{
knownFileSystems: make(map[string]knownFs),
nameRootMap: make(map[string]string),
options: &options,
FileSystem: pathfs.NewDefaultFileSystem(),
nameRootMap: make(map[string]string),
options: &options,
FileSystem: pathfs.NewDefaultFileSystem(),
}
directory, err := filepath.Abs(directory)
if err != nil {
panic("filepath.Abs returned err")
......@@ -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())
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() {
fs.knownFileSystems[name] = knownFs{
ufs,
......@@ -395,7 +397,7 @@ func (fs *autoUnionFs) SetMountState(state *fuse.MountState) {
fs.mountState = state
}
func (fs *autoUnionFs) SetFileSystemConnector(conn *fuse.FileSystemConnector) {
func (fs *autoUnionFs) SetFileSystemConnector(conn *nodefs.FileSystemConnector) {
fs.connector = conn
}
......@@ -419,25 +421,25 @@ func (fs *autoUnionFs) DebugData() string {
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 flags&fuse.O_ANYWRITE != 0 {
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 flags&fuse.O_ANYWRITE != 0 {
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 flags&fuse.O_ANYWRITE != 0 {
fs.updateKnownFses()
}
return fuse.NewDevNullFile(), fuse.OK
return nodefs.NewDevNullFile(), fuse.OK
}
return nil, fuse.ENOENT
}
......@@ -489,6 +491,6 @@ func (fs *autoUnionFs) OpenDir(name string, context *fuse.Context) (stream []fus
return stream, status
}
func (fs *autoUnionFs) StatFs(name string) *fuse.StatfsOut {
return &fuse.StatfsOut{}
func (fs *autoUnionFs) StatFs(name string) *nodefs.StatfsOut {
return &nodefs.StatfsOut{}
}
......@@ -9,6 +9,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -19,7 +20,7 @@ const entryTtl = 100 * time.Millisecond
var testAOpts = AutoUnionFsOptions{
UnionFsOptions: testOpts,
FileSystemOptions: fuse.FileSystemOptions{
Options: nodefs.Options{
EntryTimeout: entryTtl,
AttrTimeout: entryTtl,
NegativeTimeout: 0,
......@@ -56,7 +57,7 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
fs := NewAutoUnionFs(wd+"/store", testAOpts)
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 {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......
......@@ -7,6 +7,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -139,7 +140,7 @@ func (fs *cachingFileSystem) String() string {
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 {
log.Println("Dropping cache for", fs)
fs.DropCache()
......
......@@ -13,6 +13,7 @@ import (
"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/raw"
)
......@@ -88,9 +89,9 @@ const (
func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) pathfs.FileSystem {
g := &unionFS{
options: &options,
options: &options,
fileSystems: fileSystems,
FileSystem: pathfs.NewDefaultFileSystem(),
FileSystem: pathfs.NewDefaultFileSystem(),
}
writable := g.fileSystems[0]
......@@ -247,7 +248,7 @@ func (fs *unionFS) putDeletion(name string) (code fuse.Status) {
return fuse.OK
}
var f fuse.File
var f nodefs.File
if code == fuse.ENOENT {
f, code = writable.Create(marker, uint32(os.O_TRUNC|os.O_WRONLY), 0644, nil)
} else {
......@@ -362,7 +363,7 @@ func (fs *unionFS) Link(orig string, newName string, context *fuse.Context) (cod
fs.branchCache.GetFresh(orig)
inode := fs.nodeFs.Node(orig)
var a fuse.Attr
inode.FsNode().GetAttr(&a, nil, nil)
inode.Node().GetAttr(&a, nil, nil)
}
if code.Ok() {
code = fs.promoteDirsTo(newName)
......@@ -650,7 +651,7 @@ func (fs *unionFS) promoteDirsTo(filename string) fuse.Status {
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]
code = fs.promoteDirsTo(name)
......@@ -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 flags&fuse.O_ANYWRITE != 0 {
log.Println("Forced cache drop on", fs)
......@@ -935,7 +936,7 @@ func (fs *unionFS) Open(name string, flags uint32, context *fuse.Context) (fuseF
fs.DropSubFsCaches()
fs.nodeFs.ForgetClientInodes()
}
return fuse.NewDevNullFile(), fuse.OK
return nodefs.NewDevNullFile(), fuse.OK
}
r := fs.getBranch(name)
if r.branch < 0 {
......@@ -969,14 +970,14 @@ func (fs *unionFS) String() string {
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("")
}
type unionFsFile struct {
fuse.File
nodefs.File
ufs *unionFS
node *fuse.Inode
node *nodefs.Inode
layer int
}
......@@ -984,7 +985,7 @@ func (fs *unionFsFile) String() 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{
File: f,
ufs: fs,
......@@ -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
}
......@@ -1005,7 +1006,7 @@ func (fs *unionFsFile) Flush() (code fuse.Status) {
return code
}
func (fs *unionFsFile) SetInode(node *fuse.Inode) {
func (fs *unionFsFile) SetInode(node *nodefs.Inode) {
fs.node = node
}
......
......@@ -16,6 +16,7 @@ import (
"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/raw"
)
......@@ -85,7 +86,7 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
// We configure timeouts are smaller, so we can check for
// UnionFs's cache consistency.
opts := &fuse.FileSystemOptions{
opts := &nodefs.Options{
EntryTimeout: entryTtl / 2,
AttrTimeout: entryTtl / 2,
NegativeTimeout: entryTtl / 2,
......@@ -93,7 +94,7 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
pathfs := pathfs.NewPathNodeFs(ufs,
&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 {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......@@ -1106,14 +1107,14 @@ func TestUnionFsDisappearing(t *testing.T) {
fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/ro"))
ufs := NewUnionFs(fses, testOpts)
opts := &fuse.FileSystemOptions{
opts := &nodefs.Options{
EntryTimeout: entryTtl,
AttrTimeout: entryTtl,
NegativeTimeout: entryTtl,
}
nfs := pathfs.NewPathNodeFs(ufs, nil)
state, _, err := fuse.MountNodeFileSystem(wd+"/mnt", nfs, opts)
state, _, err := nodefs.MountFileSystem(wd+"/mnt", nfs, opts)
if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
......
......@@ -5,6 +5,7 @@ import (
"strings"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
type MemFile interface {
......@@ -13,7 +14,7 @@ type MemFile interface {
}
type memNode struct {
fuse.FsNode
nodefs.Node
file MemFile
}
......@@ -21,7 +22,7 @@ type memNode struct {
// loaded in memory completely at startup, it does not need to inode
// discovery through Lookup() at serve time.
type MemTreeFs struct {
fuse.NodeFileSystem
nodefs.FileSystem
root memNode
files map[string]MemFile
Name string
......@@ -29,8 +30,8 @@ type MemTreeFs struct {
func NewMemTreeFs() *MemTreeFs {
return &MemTreeFs{
NodeFileSystem: fuse.NewDefaultNodeFileSystem(),
root: memNode{FsNode: fuse.NewDefaultFsNode()},
FileSystem: nodefs.NewDefaultFileSystem(),
root: memNode{Node: nodefs.NewDefaultNode()},
}
}
......@@ -38,14 +39,14 @@ func (fs *MemTreeFs) String() string {
return fs.Name
}
func (fs *MemTreeFs) OnMount(conn *fuse.FileSystemConnector) {
func (fs *MemTreeFs) OnMount(conn *nodefs.FileSystemConnector) {
for k, v := range fs.files {
fs.addFile(k, v)
}
fs.files = nil
}
func (fs *MemTreeFs) Root() fuse.FsNode {
func (fs *MemTreeFs) Root() nodefs.Node {
return &fs.root
}
......@@ -59,7 +60,7 @@ func (n *memNode) Print(indent int) {
for k, v := range children {
if v.IsDir() {
fmt.Println(s + k + ":")
mn, ok := v.FsNode().(*memNode)
mn, ok := v.Node().(*memNode)
if ok {
mn.Print(indent + 2)
}
......@@ -85,19 +86,19 @@ func (n *memNode) OpenDir(context *fuse.Context) (stream []fuse.DirEntry, code f
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 {
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 {
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() {
out.Mode = fuse.S_IFDIR | 0777
return fuse.OK
......@@ -113,7 +114,7 @@ func (n *MemTreeFs) addFile(name string, f MemFile) {
for i, c := range comps {
child := node.GetChild(c)
if child == nil {
fsnode := &memNode{FsNode: fuse.NewDefaultFsNode()}
fsnode := &memNode{Node: nodefs.NewDefaultNode()}
if i == len(comps)-1 {
fsnode.file = f
}
......
......@@ -40,9 +40,9 @@ type MultiZipFs struct {
func NewMultiZipFs() *MultiZipFs {
m := &MultiZipFs{
zips: make(map[string]*MemTreeFs),
zips: make(map[string]*MemTreeFs),
dirZipFileMap: make(map[string]string),
FileSystem: pathfs.NewDefaultFileSystem(),
FileSystem: pathfs.NewDefaultFileSystem(),
}
return m
}
......
......@@ -8,6 +8,7 @@ import (
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
)
......@@ -19,7 +20,7 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
fs := NewMultiZipFs()
mountPoint, _ = ioutil.TempDir("", "")
nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, &fuse.FileSystemOptions{
state, _, err := nodefs.MountFileSystem(mountPoint, nfs, &nodefs.Options{
EntryTimeout: testTtl,
AttrTimeout: testTtl,
NegativeTimeout: 0.0,
......
package zipfs
import (
"github.com/hanwen/go-fuse/fuse"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"testing"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
func testZipFile() string {
......@@ -25,7 +27,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) {
}
mountPoint, _ = ioutil.TempDir("", "")
state, _, err := fuse.MountNodeFileSystem(mountPoint, zfs, nil)
state, _, err := nodefs.MountFileSystem(mountPoint, zfs, nil)
state.SetDebug(fuse.VerboseTest())
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