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

nodefs: use syscall.Errno instead of fuse.Status

parent f1ff19a7
...@@ -58,6 +58,7 @@ package nodefs ...@@ -58,6 +58,7 @@ package nodefs
import ( import (
"context" "context"
"syscall"
"time" "time"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
...@@ -72,7 +73,9 @@ func InodeOf(node Operations) *Inode { ...@@ -72,7 +73,9 @@ func InodeOf(node Operations) *Inode {
} }
// Operations is the interface that implements the filesystem inode. // Operations is the interface that implements the filesystem inode.
// Each Operations instance must embed DefaultNode. // Each Operations instance must embed DefaultNode. All error
// reporting must use the syscall.Errno type. The value 0 (`OK`)
// should be used to indicate success.
type Operations interface { type Operations interface {
// setInode and inode are used by nodefs internally to link Inode to a Node. // setInode and inode are used by nodefs internally to link Inode to a Node.
// //
...@@ -91,21 +94,21 @@ type Operations interface { ...@@ -91,21 +94,21 @@ type Operations interface {
// StatFs implements statistics for the filesystem that holds // StatFs implements statistics for the filesystem that holds
// this Inode. DefaultNode implements this, because OSX // this Inode. DefaultNode implements this, because OSX
// filesystem must have a valid StatFs implementation. // filesystem must have a valid StatFs implementation.
StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Status StatFs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno
// Access should return if the caller can access the file with // Access should return if the caller can access the file with
// the given mode. In this case, the context has data about // the given mode. In this case, the context has data about
// the real UID. For example a root-SUID binary called by user // the real UID. For example a root-SUID binary called by user
// susan gets the UID and GID for susan here. // susan gets the UID and GID for susan here.
Access(ctx context.Context, mask uint32) fuse.Status Access(ctx context.Context, mask uint32) syscall.Errno
// GetAttr reads attributes for an Inode. The library will // GetAttr reads attributes for an Inode. The library will
// ensure that Mode and Ino are set correctly. For regular // ensure that Mode and Ino are set correctly. For regular
// files, Size should be set so it can be read correctly. // files, Size should be set so it can be read correctly.
GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno
// SetAttr sets attributes for an Inode. // SetAttr sets attributes for an Inode.
SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno
// OnAdd is called once this Operations object is attached to // OnAdd is called once this Operations object is attached to
// an Inode. // an Inode.
...@@ -119,19 +122,19 @@ type XAttrOperations interface { ...@@ -119,19 +122,19 @@ type XAttrOperations interface {
// GetXAttr should read data for the given attribute into // GetXAttr should read data for the given attribute into
// `dest` and return the number of bytes. If `dest` is too // `dest` and return the number of bytes. If `dest` is too
// small, it should return ERANGE and the size of the attribute. // small, it should return ERANGE and the size of the attribute.
GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, fuse.Status) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno)
// SetXAttr should store data for the given attribute. See // SetXAttr should store data for the given attribute. See
// setxattr(2) for information about flags. // setxattr(2) for information about flags.
SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) fuse.Status SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno
// RemoveXAttr should delete the given attribute. // RemoveXAttr should delete the given attribute.
RemoveXAttr(ctx context.Context, attr string) fuse.Status RemoveXAttr(ctx context.Context, attr string) syscall.Errno
// ListXAttr should read all attributes (null terminated) into // ListXAttr should read all attributes (null terminated) into
// `dest`. If the `dest` buffer is too small, it should return // `dest`. If the `dest` buffer is too small, it should return
// ERANGE and the correct size. // ERANGE and the correct size.
ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status) ListXAttr(ctx context.Context, dest []byte) (uint32, syscall.Errno)
} }
// SymlinkOperations holds operations specific to symlinks. // SymlinkOperations holds operations specific to symlinks.
...@@ -139,7 +142,7 @@ type SymlinkOperations interface { ...@@ -139,7 +142,7 @@ type SymlinkOperations interface {
Operations Operations
// Readlink reads the content of a symlink. // Readlink reads the content of a symlink.
Readlink(ctx context.Context) ([]byte, fuse.Status) Readlink(ctx context.Context) ([]byte, syscall.Errno)
} }
// FileOperations holds operations that apply to regular files. The // FileOperations holds operations that apply to regular files. The
...@@ -150,58 +153,58 @@ type FileOperations interface { ...@@ -150,58 +153,58 @@ type FileOperations interface {
// Open opens an Inode (of regular file type) for reading. It // Open opens an Inode (of regular file type) for reading. It
// is optional but recommended to return a FileHandle. // is optional but recommended to return a FileHandle.
Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno)
// Reads data from a file. The data should be returned as // Reads data from a file. The data should be returned as
// ReadResult, which may be constructed from the incoming // ReadResult, which may be constructed from the incoming
// `dest` buffer. If the file was opened without FileHandle, // `dest` buffer. If the file was opened without FileHandle,
// the FileHandle argument here is nil. The default // the FileHandle argument here is nil. The default
// implementation forwards to the FileHandle. // implementation forwards to the FileHandle.
Read(ctx context.Context, f FileHandle, dest []byte, off int64) (fuse.ReadResult, fuse.Status) Read(ctx context.Context, f FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno)
// Writes the data into the file handle at given offset. After // Writes the data into the file handle at given offset. After
// returning, the data will be reused and may not referenced. // returning, the data will be reused and may not referenced.
// The default implementation forwards to the FileHandle. // The default implementation forwards to the FileHandle.
Write(ctx context.Context, f FileHandle, data []byte, off int64) (written uint32, status fuse.Status) Write(ctx context.Context, f FileHandle, data []byte, off int64) (written uint32, errno syscall.Errno)
// Fsync is a signal to ensure writes to the Inode are flushed // Fsync is a signal to ensure writes to the Inode are flushed
// to stable storage. The default implementation forwards to the // to stable storage. The default implementation forwards to the
// FileHandle. // FileHandle.
Fsync(ctx context.Context, f FileHandle, flags uint32) (status fuse.Status) Fsync(ctx context.Context, f FileHandle, flags uint32) syscall.Errno
// Flush is called for close() call on a file descriptor. In // Flush is called for close() call on a file descriptor. In
// case of duplicated descriptor, it may be called more than // case of duplicated descriptor, it may be called more than
// once for a file. The default implementation forwards to the // once for a file. The default implementation forwards to the
// FileHandle. // FileHandle.
Flush(ctx context.Context, f FileHandle) fuse.Status Flush(ctx context.Context, f FileHandle) syscall.Errno
// This is called to before the file handle is forgotten. The // This is called to before the file handle is forgotten. The
// kernel ingores the return value of this method, // kernel ingores the return value of this method,
// so any cleanup that requires specific synchronization or // so any cleanup that requires specific synchronization or
// could fail with I/O errors should happen in Flush instead. // could fail with I/O errors should happen in Flush instead.
// The default implementation forwards to the FileHandle. // The default implementation forwards to the FileHandle.
Release(ctx context.Context, f FileHandle) fuse.Status Release(ctx context.Context, f FileHandle) syscall.Errno
// Allocate preallocates space for future writes, so they will // Allocate preallocates space for future writes, so they will
// never encounter ESPACE. // never encounter ESPACE.
Allocate(ctx context.Context, f FileHandle, off uint64, size uint64, mode uint32) (status fuse.Status) Allocate(ctx context.Context, f FileHandle, off uint64, size uint64, mode uint32) syscall.Errno
// FGetAttr is like GetAttr but provides a file handle if available. // FGetAttr is like GetAttr but provides a file handle if available.
FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno
// FSetAttr is like SetAttr but provides a file handle if available. // FSetAttr is like SetAttr but provides a file handle if available.
FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno
// CopyFileRange copies data between sections of two files, // CopyFileRange copies data between sections of two files,
// without the data having to pass through the calling process. // without the data having to pass through the calling process.
CopyFileRange(ctx context.Context, fhIn FileHandle, CopyFileRange(ctx context.Context, fhIn FileHandle,
offIn uint64, out *Inode, fhOut FileHandle, offOut uint64, offIn uint64, out *Inode, fhOut FileHandle, offOut uint64,
len uint64, flags uint64) (uint32, fuse.Status) len uint64, flags uint64) (uint32, syscall.Errno)
// Lseek is used to implement holes: it should return the // Lseek is used to implement holes: it should return the
// first offset beyond `off` where there is data (SEEK_DATA) // first offset beyond `off` where there is data (SEEK_DATA)
// or where there is a hole (SEEK_HOLE). // or where there is a hole (SEEK_HOLE).
Lseek(ctx context.Context, f FileHandle, Off uint64, whence uint32) (uint64, fuse.Status) Lseek(ctx context.Context, f FileHandle, Off uint64, whence uint32) (uint64, syscall.Errno)
} }
// LockOperations are operations for locking regions of regular files. // LockOperations are operations for locking regions of regular files.
...@@ -211,15 +214,15 @@ type LockOperations interface { ...@@ -211,15 +214,15 @@ type LockOperations interface {
// GetLk returns locks that would conflict with the given // GetLk returns locks that would conflict with the given
// input lock. If no locks conflict, the output has type // input lock. If no locks conflict, the output has type
// L_UNLCK. See fcntl(2) for more information. // L_UNLCK. See fcntl(2) for more information.
GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) syscall.Errno
// Obtain a lock on a file, or fail if the lock could not // Obtain a lock on a file, or fail if the lock could not
// obtained. See fcntl(2) for more information. // obtained. See fcntl(2) for more information.
SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) syscall.Errno
// Obtain a lock on a file, waiting if necessary. See fcntl(2) // Obtain a lock on a file, waiting if necessary. See fcntl(2)
// for more information. // for more information.
SetLkw(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) SetLkw(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) syscall.Errno
} }
// DirStream lists directory entries. // DirStream lists directory entries.
...@@ -229,9 +232,9 @@ type DirStream interface { ...@@ -229,9 +232,9 @@ type DirStream interface {
HasNext() bool HasNext() bool
// Next retrieves the next entry. It is only called if HasNext // Next retrieves the next entry. It is only called if HasNext
// has previously returned true. The Status may be used to // has previously returned true. The Errno return may be used to
// indicate I/O errors // indicate I/O errors
Next() (fuse.DirEntry, fuse.Status) Next() (fuse.DirEntry, syscall.Errno)
// Close releases resources related to this directory // Close releases resources related to this directory
// stream. // stream.
...@@ -249,16 +252,16 @@ type DirOperations interface { ...@@ -249,16 +252,16 @@ type DirOperations interface {
// the Inode for the child. A new inode can be created using // the Inode for the child. A new inode can be created using
// `Inode.NewInode`. The new Inode will be added to the FS // `Inode.NewInode`. The new Inode will be added to the FS
// tree automatically if the return status is OK. // tree automatically if the return status is OK.
Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno)
// OpenDir opens a directory Inode for reading its // OpenDir opens a directory Inode for reading its
// contents. The actual reading is driven from ReadDir, so // contents. The actual reading is driven from ReadDir, so
// this method is just for performing sanity/permission // this method is just for performing sanity/permission
// checks. // checks.
OpenDir(ctx context.Context) fuse.Status OpenDir(ctx context.Context) syscall.Errno
// ReadDir opens a stream of directory entries. // ReadDir opens a stream of directory entries.
ReadDir(ctx context.Context) (DirStream, fuse.Status) ReadDir(ctx context.Context) (DirStream, syscall.Errno)
} }
// MutableDirOperations are operations that change the hierarchy of a file system. // MutableDirOperations are operations that change the hierarchy of a file system.
...@@ -266,34 +269,34 @@ type MutableDirOperations interface { ...@@ -266,34 +269,34 @@ type MutableDirOperations interface {
DirOperations DirOperations
// Mkdir is similar to Lookup, but must create a directory entry and Inode. // Mkdir is similar to Lookup, but must create a directory entry and Inode.
Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, syscall.Errno)
// Mknod is similar to Lookup, but must create a device entry and Inode. // Mknod is similar to Lookup, but must create a device entry and Inode.
Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (*Inode, fuse.Status) Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (*Inode, syscall.Errno)
// Link is similar to Lookup, but must create a new link to an existing Inode. // Link is similar to Lookup, but must create a new link to an existing Inode.
Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (node *Inode, status fuse.Status) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (node *Inode, errno syscall.Errno)
// Symlink is similar to Lookup, but must create a new symbolic link. // Symlink is similar to Lookup, but must create a new symbolic link.
Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (node *Inode, status fuse.Status) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (node *Inode, errno syscall.Errno)
// Create is similar to Lookup, but should create a new // Create is similar to Lookup, but should create a new
// child. It typically also returns a FileHandle as a // child. It typically also returns a FileHandle as a
// reference for future reads/writes // reference for future reads/writes
Create(ctx context.Context, name string, flags uint32, mode uint32) (node *Inode, fh FileHandle, fuseFlags uint32, status fuse.Status) Create(ctx context.Context, name string, flags uint32, mode uint32) (node *Inode, fh FileHandle, fuseFlags uint32, errno syscall.Errno)
// Unlink should remove a child from this directory. If the // Unlink should remove a child from this directory. If the
// return status is OK, the Inode is removed as child in the // return status is OK, the Inode is removed as child in the
// FS tree automatically. // FS tree automatically.
Unlink(ctx context.Context, name string) fuse.Status Unlink(ctx context.Context, name string) syscall.Errno
// Rmdir is like Unlink but for directories. // Rmdir is like Unlink but for directories.
Rmdir(ctx context.Context, name string) fuse.Status Rmdir(ctx context.Context, name string) syscall.Errno
// Rename should move a child from one directory to a // Rename should move a child from one directory to a
// different one. The changes is effected in the FS tree if // different one. The changes is effected in the FS tree if
// the return status is OK // the return status is OK
Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) fuse.Status Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) syscall.Errno
} }
// FileHandle is a resource identifier for opened files. FileHandles // FileHandle is a resource identifier for opened files. FileHandles
...@@ -311,25 +314,25 @@ type MutableDirOperations interface { ...@@ -311,25 +314,25 @@ type MutableDirOperations interface {
// For a description of individual operations, see the equivalent // For a description of individual operations, see the equivalent
// operations in FileOperations. // operations in FileOperations.
type FileHandle interface { type FileHandle interface {
Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, fuse.Status) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno)
Write(ctx context.Context, data []byte, off int64) (written uint32, status fuse.Status) Write(ctx context.Context, data []byte, off int64) (written uint32, errno syscall.Errno)
GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) syscall.Errno
SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) syscall.Errno
SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) syscall.Errno
Lseek(ctx context.Context, off uint64, whence uint32) (uint64, fuse.Status) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, syscall.Errno)
Flush(ctx context.Context) fuse.Status Flush(ctx context.Context) syscall.Errno
Fsync(ctx context.Context, flags uint32) fuse.Status Fsync(ctx context.Context, flags uint32) syscall.Errno
Release(ctx context.Context) fuse.Status Release(ctx context.Context) syscall.Errno
GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno
SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno
Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (status fuse.Status) Allocate(ctx context.Context, off uint64, size uint64, mode uint32) syscall.Errno
} }
// Options sets options for the entire filesystem // Options sets options for the entire filesystem
......
...@@ -15,6 +15,10 @@ import ( ...@@ -15,6 +15,10 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
func errnoToStatus(errno syscall.Errno) fuse.Status {
return fuse.Status(errno)
}
type fileEntry struct { type fileEntry struct {
file FileHandle file FileHandle
...@@ -208,15 +212,15 @@ func (b *rawBridge) inode(id uint64, fh uint64) (*Inode, *fileEntry) { ...@@ -208,15 +212,15 @@ func (b *rawBridge) inode(id uint64, fh uint64) (*Inode, *fileEntry) {
return n, f return n, f
} }
func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name string, out *fuse.EntryOut) (status fuse.Status) { func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name string, out *fuse.EntryOut) fuse.Status {
parent, _ := b.inode(header.NodeId, 0) parent, _ := b.inode(header.NodeId, 0)
child, status := parent.dirOps().Lookup(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name, out) child, errno := parent.dirOps().Lookup(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name, out)
if !status.Ok() { if errno != 0 {
if b.options.NegativeTimeout != nil { if b.options.NegativeTimeout != nil {
out.SetEntryTimeout(*b.options.NegativeTimeout) out.SetEntryTimeout(*b.options.NegativeTimeout)
} }
return status return errnoToStatus(errno)
} }
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
...@@ -228,42 +232,41 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s ...@@ -228,42 +232,41 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s
func (b *rawBridge) Rmdir(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status { func (b *rawBridge) Rmdir(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status {
parent, _ := b.inode(header.NodeId, 0) parent, _ := b.inode(header.NodeId, 0)
var status fuse.Status var errno syscall.Errno
if mops, ok := parent.ops.(MutableDirOperations); ok { if mops, ok := parent.ops.(MutableDirOperations); ok {
status = mops.Rmdir(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name) errno = mops.Rmdir(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name)
} }
if status.Ok() { if errno == 0 {
parent.RmChild(name) parent.RmChild(name)
} }
return status return errnoToStatus(errno)
} }
func (b *rawBridge) Unlink(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status { func (b *rawBridge) Unlink(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status {
parent, _ := b.inode(header.NodeId, 0) parent, _ := b.inode(header.NodeId, 0)
var status fuse.Status var errno syscall.Errno
if mops, ok := parent.ops.(MutableDirOperations); ok { if mops, ok := parent.ops.(MutableDirOperations); ok {
status = mops.Unlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name) errno = mops.Unlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name)
} }
if status.Ok() { if errno == 0 {
parent.RmChild(name) parent.RmChild(name)
} }
return status return errnoToStatus(errno)
} }
func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name string, out *fuse.EntryOut) fuse.Status { func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name string, out *fuse.EntryOut) fuse.Status {
parent, _ := b.inode(input.NodeId, 0) parent, _ := b.inode(input.NodeId, 0)
var child *Inode var child *Inode
var status fuse.Status var errno syscall.Errno
if mops, ok := parent.ops.(MutableDirOperations); ok { if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status = mops.Mkdir(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, out) child, errno = mops.Mkdir(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, out)
} }
if !status.Ok() { if errno != 0 {
return status return errnoToStatus(errno)
} }
if out.Attr.Mode&^07777 != fuse.S_IFDIR { if out.Attr.Mode&^07777 != fuse.S_IFDIR {
...@@ -279,13 +282,13 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri ...@@ -279,13 +282,13 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
parent, _ := b.inode(input.NodeId, 0) parent, _ := b.inode(input.NodeId, 0)
var child *Inode var child *Inode
var status fuse.Status var errno syscall.Errno
if mops, ok := parent.ops.(MutableDirOperations); ok { if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status = mops.Mknod(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, input.Rdev, out) child, errno = mops.Mknod(&fuse.Context{Caller: input.Caller, Cancel: cancel}, name, input.Mode, input.Rdev, out)
} }
if !status.Ok() { if errno != 0 {
return status return errnoToStatus(errno)
} }
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
...@@ -298,18 +301,18 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st ...@@ -298,18 +301,18 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
parent, _ := b.inode(input.NodeId, 0) parent, _ := b.inode(input.NodeId, 0)
var child *Inode var child *Inode
var status fuse.Status var errno syscall.Errno
var f FileHandle var f FileHandle
var flags uint32 var flags uint32
if mops, ok := parent.ops.(MutableDirOperations); ok { if mops, ok := parent.ops.(MutableDirOperations); ok {
child, f, flags, status = mops.Create(ctx, name, input.Flags, input.Mode) child, f, flags, errno = mops.Create(ctx, name, input.Flags, input.Mode)
} }
if !status.Ok() { if errno != 0 {
if b.options.NegativeTimeout != nil { if b.options.NegativeTimeout != nil {
out.SetEntryTimeout(*b.options.NegativeTimeout) out.SetEntryTimeout(*b.options.NegativeTimeout)
} }
return status return errnoToStatus(errno)
} }
out.Fh = uint64(b.addNewChild(parent, name, child, f, input.Flags|syscall.O_CREAT, &out.EntryOut)) out.Fh = uint64(b.addNewChild(parent, name, child, f, input.Flags|syscall.O_CREAT, &out.EntryOut))
...@@ -358,16 +361,16 @@ func (b *rawBridge) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out * ...@@ -358,16 +361,16 @@ func (b *rawBridge) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out *
b.mu.Unlock() b.mu.Unlock()
} }
status := fops.FGetAttr(ctx, f, out) errno := fops.FGetAttr(ctx, f, out)
b.setAttrTimeout(out) b.setAttrTimeout(out)
out.Ino = input.NodeId out.Ino = input.NodeId
out.Mode = (out.Attr.Mode & 07777) | n.nodeAttr.Mode out.Mode = (out.Attr.Mode & 07777) | n.nodeAttr.Mode
return status return errnoToStatus(errno)
} }
return n.ops.GetAttr(ctx, out) return errnoToStatus(n.ops.GetAttr(ctx, out))
} }
func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fuse.AttrOut) (status fuse.Status) { func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
ctx := &fuse.Context{Caller: in.Caller, Cancel: cancel} ctx := &fuse.Context{Caller: in.Caller, Cancel: cancel}
n, fEntry := b.inode(in.NodeId, in.Fh) n, fEntry := b.inode(in.NodeId, in.Fh)
...@@ -377,10 +380,10 @@ func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fus ...@@ -377,10 +380,10 @@ func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fus
} }
if fops, ok := n.ops.(FileOperations); ok { if fops, ok := n.ops.(FileOperations); ok {
return fops.FSetAttr(ctx, f, in, out) return errnoToStatus(fops.FSetAttr(ctx, f, in, out))
} }
return n.ops.SetAttr(ctx, in, out) return errnoToStatus(n.ops.SetAttr(ctx, in, out))
} }
func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName string, newName string) fuse.Status { func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName string, newName string) fuse.Status {
...@@ -388,28 +391,28 @@ func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName ...@@ -388,28 +391,28 @@ func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName
p2, _ := b.inode(input.Newdir, 0) p2, _ := b.inode(input.Newdir, 0)
if mops, ok := p1.ops.(MutableDirOperations); ok { if mops, ok := p1.ops.(MutableDirOperations); ok {
status := mops.Rename(&fuse.Context{Caller: input.Caller, Cancel: cancel}, oldName, p2.ops, newName, input.Flags) errno := mops.Rename(&fuse.Context{Caller: input.Caller, Cancel: cancel}, oldName, p2.ops, newName, input.Flags)
if status.Ok() { if errno == 0 {
if input.Flags&unix.RENAME_EXCHANGE != 0 { if input.Flags&unix.RENAME_EXCHANGE != 0 {
p1.ExchangeChild(oldName, p2, newName) p1.ExchangeChild(oldName, p2, newName)
} else { } else {
p1.MvChild(oldName, p2, newName, true) p1.MvChild(oldName, p2, newName, true)
} }
return status return errnoToStatus(errno)
} }
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string, out *fuse.EntryOut) (status fuse.Status) { func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string, out *fuse.EntryOut) fuse.Status {
parent, _ := b.inode(input.NodeId, 0) parent, _ := b.inode(input.NodeId, 0)
target, _ := b.inode(input.Oldnodeid, 0) target, _ := b.inode(input.Oldnodeid, 0)
if mops, ok := parent.ops.(MutableDirOperations); ok { if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status := mops.Link(&fuse.Context{Caller: input.Caller, Cancel: cancel}, target.ops, name, out) child, errno := mops.Link(&fuse.Context{Caller: input.Caller, Cancel: cancel}, target.ops, name, out)
if !status.Ok() { if errno != 0 {
return status return errnoToStatus(errno)
} }
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
...@@ -419,13 +422,13 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string ...@@ -419,13 +422,13 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string
return fuse.ENOSYS return fuse.ENOSYS
} }
func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, target string, name string, out *fuse.EntryOut) (status fuse.Status) { func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, target string, name string, out *fuse.EntryOut) fuse.Status {
parent, _ := b.inode(header.NodeId, 0) parent, _ := b.inode(header.NodeId, 0)
if mops, ok := parent.ops.(MutableDirOperations); ok { if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status := mops.Symlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, target, name, out) child, status := mops.Symlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, target, name, out)
if !status.Ok() { if status != 0 {
return status return errnoToStatus(status)
} }
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
...@@ -437,17 +440,17 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe ...@@ -437,17 +440,17 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe
func (b *rawBridge) Readlink(cancel <-chan struct{}, header *fuse.InHeader) (out []byte, status fuse.Status) { func (b *rawBridge) Readlink(cancel <-chan struct{}, header *fuse.InHeader) (out []byte, status fuse.Status) {
n, _ := b.inode(header.NodeId, 0) n, _ := b.inode(header.NodeId, 0)
result, status := n.linkOps().Readlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}) result, errno := n.linkOps().Readlink(&fuse.Context{Caller: header.Caller, Cancel: cancel})
if !status.Ok() { if errno != 0 {
return nil, status return nil, errnoToStatus(errno)
} }
return result, fuse.OK return result, fuse.OK
} }
func (b *rawBridge) Access(cancel <-chan struct{}, input *fuse.AccessIn) (status fuse.Status) { func (b *rawBridge) Access(cancel <-chan struct{}, input *fuse.AccessIn) fuse.Status {
n, _ := b.inode(input.NodeId, 0) n, _ := b.inode(input.NodeId, 0)
return n.ops.Access(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Mask) return errnoToStatus(n.ops.Access(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Mask))
} }
// Extended attributes. // Extended attributes.
...@@ -456,7 +459,8 @@ func (b *rawBridge) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr ...@@ -456,7 +459,8 @@ func (b *rawBridge) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr
n, _ := b.inode(header.NodeId, 0) n, _ := b.inode(header.NodeId, 0)
if xops, ok := n.ops.(XAttrOperations); ok { if xops, ok := n.ops.(XAttrOperations); ok {
return xops.GetXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr, data) nb, errno := xops.GetXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr, data)
return nb, errnoToStatus(errno)
} }
return 0, fuse.ENOSYS return 0, fuse.ENOSYS
...@@ -465,7 +469,8 @@ func (b *rawBridge) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr ...@@ -465,7 +469,8 @@ func (b *rawBridge) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr
func (b *rawBridge) ListXAttr(cancel <-chan struct{}, header *fuse.InHeader, dest []byte) (sz uint32, status fuse.Status) { func (b *rawBridge) ListXAttr(cancel <-chan struct{}, header *fuse.InHeader, dest []byte) (sz uint32, status fuse.Status) {
n, _ := b.inode(header.NodeId, 0) n, _ := b.inode(header.NodeId, 0)
if xops, ok := n.ops.(XAttrOperations); ok { if xops, ok := n.ops.(XAttrOperations); ok {
return xops.ListXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, dest) sz, errno := xops.ListXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, dest)
return sz, errnoToStatus(errno)
} }
return 0, fuse.ENOSYS return 0, fuse.ENOSYS
} }
...@@ -473,25 +478,24 @@ func (b *rawBridge) ListXAttr(cancel <-chan struct{}, header *fuse.InHeader, des ...@@ -473,25 +478,24 @@ func (b *rawBridge) ListXAttr(cancel <-chan struct{}, header *fuse.InHeader, des
func (b *rawBridge) SetXAttr(cancel <-chan struct{}, input *fuse.SetXAttrIn, attr string, data []byte) fuse.Status { func (b *rawBridge) SetXAttr(cancel <-chan struct{}, input *fuse.SetXAttrIn, attr string, data []byte) fuse.Status {
n, _ := b.inode(input.NodeId, 0) n, _ := b.inode(input.NodeId, 0)
if xops, ok := n.ops.(XAttrOperations); ok { if xops, ok := n.ops.(XAttrOperations); ok {
return xops.SetXAttr(&fuse.Context{Caller: input.Caller, Cancel: cancel}, attr, data, input.Flags) return errnoToStatus(xops.SetXAttr(&fuse.Context{Caller: input.Caller, Cancel: cancel}, attr, data, input.Flags))
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
func (b *rawBridge) RemoveXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string) (status fuse.Status) { func (b *rawBridge) RemoveXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string) fuse.Status {
n, _ := b.inode(header.NodeId, 0) n, _ := b.inode(header.NodeId, 0)
if xops, ok := n.ops.(XAttrOperations); ok { if xops, ok := n.ops.(XAttrOperations); ok {
return xops.RemoveXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr) return errnoToStatus(xops.RemoveXAttr(&fuse.Context{Caller: header.Caller, Cancel: cancel}, attr))
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
func (b *rawBridge) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) { func (b *rawBridge) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut) fuse.Status {
n, _ := b.inode(input.NodeId, 0) n, _ := b.inode(input.NodeId, 0)
// NOSUBMIT: what about the mode argument? f, flags, errno := n.fileOps().Open(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Flags)
f, flags, status := n.fileOps().Open(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Flags) if errno != 0 {
if !status.Ok() { return errnoToStatus(errno)
return status
} }
if f != nil { if f != nil {
...@@ -525,29 +529,30 @@ func (b *rawBridge) registerFile(n *Inode, f FileHandle, flags uint32) uint32 { ...@@ -525,29 +529,30 @@ func (b *rawBridge) registerFile(n *Inode, f FileHandle, flags uint32) uint32 {
func (b *rawBridge) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) { func (b *rawBridge) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().Read(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, buf, int64(input.Offset)) res, errno := n.fileOps().Read(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, buf, int64(input.Offset))
return res, errnoToStatus(errno)
} }
func (b *rawBridge) GetLk(cancel <-chan struct{}, input *fuse.LkIn, out *fuse.LkOut) (status fuse.Status) { func (b *rawBridge) GetLk(cancel <-chan struct{}, input *fuse.LkIn, out *fuse.LkOut) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if lops, ok := n.ops.(LockOperations); ok { if lops, ok := n.ops.(LockOperations); ok {
return lops.GetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags, &out.Lk) return errnoToStatus(lops.GetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags, &out.Lk))
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) (status fuse.Status) { func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if lops, ok := n.ops.(LockOperations); ok { if lops, ok := n.ops.(LockOperations); ok {
return lops.SetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags) return errnoToStatus(lops.SetLk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags))
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) (status fuse.Status) { func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if lops, ok := n.ops.(LockOperations); ok { if lops, ok := n.ops.(LockOperations); ok {
return lops.SetLkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags) return errnoToStatus(lops.SetLkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags))
} }
return fuse.ENOSYS return fuse.ENOSYS
} }
...@@ -600,29 +605,31 @@ func (b *rawBridge) releaseFileEntry(nid uint64, fh uint64) (*Inode, *fileEntry) ...@@ -600,29 +605,31 @@ func (b *rawBridge) releaseFileEntry(nid uint64, fh uint64) (*Inode, *fileEntry)
func (b *rawBridge) Write(cancel <-chan struct{}, input *fuse.WriteIn, data []byte) (written uint32, status fuse.Status) { func (b *rawBridge) Write(cancel <-chan struct{}, input *fuse.WriteIn, data []byte) (written uint32, status fuse.Status) {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().Write(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, data, int64(input.Offset))
w, errno := n.fileOps().Write(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, data, int64(input.Offset))
return w, errnoToStatus(errno)
} }
func (b *rawBridge) Flush(cancel <-chan struct{}, input *fuse.FlushIn) fuse.Status { func (b *rawBridge) Flush(cancel <-chan struct{}, input *fuse.FlushIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().Flush(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file) return errnoToStatus(n.fileOps().Flush(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file))
} }
func (b *rawBridge) Fsync(cancel <-chan struct{}, input *fuse.FsyncIn) (status fuse.Status) { func (b *rawBridge) Fsync(cancel <-chan struct{}, input *fuse.FsyncIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.FsyncFlags) return errnoToStatus(n.fileOps().Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.FsyncFlags))
} }
func (b *rawBridge) Fallocate(cancel <-chan struct{}, input *fuse.FallocateIn) (status fuse.Status) { func (b *rawBridge) Fallocate(cancel <-chan struct{}, input *fuse.FallocateIn) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
return n.fileOps().Allocate(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Offset, input.Length, input.Mode) return errnoToStatus(n.fileOps().Allocate(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Offset, input.Length, input.Mode))
} }
func (b *rawBridge) OpenDir(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut) fuse.Status { func (b *rawBridge) OpenDir(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut) fuse.Status {
n, _ := b.inode(input.NodeId, 0) n, _ := b.inode(input.NodeId, 0)
status := n.dirOps().OpenDir(&fuse.Context{Caller: input.Caller, Cancel: cancel}) errno := n.dirOps().OpenDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if !status.Ok() { if errno != 0 {
return status return errnoToStatus(errno)
} }
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
...@@ -630,29 +637,29 @@ func (b *rawBridge) OpenDir(cancel <-chan struct{}, input *fuse.OpenIn, out *fus ...@@ -630,29 +637,29 @@ func (b *rawBridge) OpenDir(cancel <-chan struct{}, input *fuse.OpenIn, out *fus
return fuse.OK return fuse.OK
} }
func (b *rawBridge) getStream(cancel <-chan struct{}, input *fuse.ReadIn, inode *Inode, f *fileEntry) fuse.Status { func (b *rawBridge) getStream(cancel <-chan struct{}, input *fuse.ReadIn, inode *Inode, f *fileEntry) syscall.Errno {
if f.dirStream == nil || input.Offset == 0 { if f.dirStream == nil || input.Offset == 0 {
if f.dirStream != nil { if f.dirStream != nil {
f.dirStream.Close() f.dirStream.Close()
f.dirStream = nil f.dirStream = nil
} }
str, status := inode.dirOps().ReadDir(&fuse.Context{Caller: input.Caller, Cancel: cancel}) str, errno := inode.dirOps().ReadDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if !status.Ok() { if errno != 0 {
return status return errno
} }
f.hasOverflow = false f.hasOverflow = false
f.dirStream = str f.dirStream = str
} }
return fuse.OK return 0
} }
func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fuse.DirEntryList) fuse.Status { func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fuse.DirEntryList) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if status := b.getStream(cancel, input, n, f); !status.Ok() { if errno := b.getStream(cancel, input, n, f); errno != 0 {
return status return errnoToStatus(errno)
} }
if f.hasOverflow { if f.hasOverflow {
...@@ -662,15 +669,15 @@ func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fus ...@@ -662,15 +669,15 @@ func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fus
} }
for f.dirStream.HasNext() { for f.dirStream.HasNext() {
e, status := f.dirStream.Next() e, errno := f.dirStream.Next()
if !status.Ok() { if errno != 0 {
return status return errnoToStatus(errno)
} }
if !out.AddDirEntry(e) { if !out.AddDirEntry(e) {
f.overflow = e f.overflow = e
f.hasOverflow = true f.hasOverflow = true
return status return errnoToStatus(errno)
} }
} }
...@@ -680,22 +687,22 @@ func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fus ...@@ -680,22 +687,22 @@ func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fus
func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out *fuse.DirEntryList) fuse.Status { func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out *fuse.DirEntryList) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh) n, f := b.inode(input.NodeId, input.Fh)
if status := b.getStream(cancel, input, n, f); !status.Ok() { if errno := b.getStream(cancel, input, n, f); errno != 0 {
return status return errnoToStatus(errno)
} }
for f.dirStream.HasNext() { for f.dirStream.HasNext() {
var e fuse.DirEntry var e fuse.DirEntry
var status fuse.Status var errno syscall.Errno
if f.hasOverflow { if f.hasOverflow {
e = f.overflow e = f.overflow
f.hasOverflow = false f.hasOverflow = false
} else { } else {
e, status = f.dirStream.Next() e, errno = f.dirStream.Next()
} }
if !status.Ok() { if errno != 0 {
return status return errnoToStatus(errno)
} }
entryOut := out.AddDirLookupEntry(e) entryOut := out.AddDirLookupEntry(e)
...@@ -705,8 +712,8 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out ...@@ -705,8 +712,8 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
return fuse.OK return fuse.OK
} }
child, status := n.dirOps().Lookup(&fuse.Context{Caller: input.Caller, Cancel: cancel}, e.Name, entryOut) child, errno := n.dirOps().Lookup(&fuse.Context{Caller: input.Caller, Cancel: cancel}, e.Name, entryOut)
if !status.Ok() { if errno != 0 {
if b.options.NegativeTimeout != nil { if b.options.NegativeTimeout != nil {
entryOut.SetEntryTimeout(*b.options.NegativeTimeout) entryOut.SetEntryTimeout(*b.options.NegativeTimeout)
} }
...@@ -725,14 +732,14 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out ...@@ -725,14 +732,14 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
return fuse.OK return fuse.OK
} }
func (b *rawBridge) FsyncDir(cancel <-chan struct{}, input *fuse.FsyncIn) (status fuse.Status) { func (b *rawBridge) FsyncDir(cancel <-chan struct{}, input *fuse.FsyncIn) fuse.Status {
n, _ := b.inode(input.NodeId, input.Fh) n, _ := b.inode(input.NodeId, input.Fh)
return n.fileOps().Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, nil, input.FsyncFlags) return errnoToStatus(n.fileOps().Fsync(&fuse.Context{Caller: input.Caller, Cancel: cancel}, nil, input.FsyncFlags))
} }
func (b *rawBridge) StatFs(cancel <-chan struct{}, input *fuse.InHeader, out *fuse.StatfsOut) (status fuse.Status) { func (b *rawBridge) StatFs(cancel <-chan struct{}, input *fuse.InHeader, out *fuse.StatfsOut) fuse.Status {
n, _ := b.inode(input.NodeId, 0) n, _ := b.inode(input.NodeId, 0)
return n.ops.StatFs(&fuse.Context{Caller: input.Caller, Cancel: cancel}, out) return errnoToStatus(n.ops.StatFs(&fuse.Context{Caller: input.Caller, Cancel: cancel}, out))
} }
func (b *rawBridge) Init(s *fuse.Server) { func (b *rawBridge) Init(s *fuse.Server) {
...@@ -743,15 +750,16 @@ func (b *rawBridge) CopyFileRange(cancel <-chan struct{}, in *fuse.CopyFileRange ...@@ -743,15 +750,16 @@ func (b *rawBridge) CopyFileRange(cancel <-chan struct{}, in *fuse.CopyFileRange
n1, f1 := b.inode(in.NodeId, in.FhIn) n1, f1 := b.inode(in.NodeId, in.FhIn)
n2, f2 := b.inode(in.NodeIdOut, in.FhOut) n2, f2 := b.inode(in.NodeIdOut, in.FhOut)
return n1.fileOps().CopyFileRange(&fuse.Context{Caller: in.Caller, Cancel: cancel}, sz, errno := n1.fileOps().CopyFileRange(&fuse.Context{Caller: in.Caller, Cancel: cancel},
f1.file, in.OffIn, n2, f2.file, in.OffOut, in.Len, in.Flags) f1.file, in.OffIn, n2, f2.file, in.OffOut, in.Len, in.Flags)
return sz, errnoToStatus(errno)
} }
func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status { func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status {
n, f := b.inode(in.NodeId, in.Fh) n, f := b.inode(in.NodeId, in.Fh)
off, status := n.fileOps().Lseek(&fuse.Context{Caller: in.Caller, Cancel: cancel}, off, errno := n.fileOps().Lseek(&fuse.Context{Caller: in.Caller, Cancel: cancel},
f.file, in.Offset, in.Whence) f.file, in.Offset, in.Whence)
out.Offset = off out.Offset = off
return status return errnoToStatus(errno)
} }
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"sync" "sync"
"syscall"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
...@@ -33,31 +34,31 @@ func (f *keepCacheFile) setContent(delta int) { ...@@ -33,31 +34,31 @@ func (f *keepCacheFile) setContent(delta int) {
f.content = []byte(fmt.Sprintf("%010x", f.count)) f.content = []byte(fmt.Sprintf("%010x", f.count))
} }
func (f *keepCacheFile) Open(ctx context.Context, flags uint32) (FileHandle, uint32, fuse.Status) { func (f *keepCacheFile) Open(ctx context.Context, flags uint32) (FileHandle, uint32, syscall.Errno) {
var fl uint32 var fl uint32
if f.keepCache { if f.keepCache {
fl = fuse.FOPEN_KEEP_CACHE fl = fuse.FOPEN_KEEP_CACHE
} }
f.setContent(0) f.setContent(0)
return nil, fl, fuse.OK return nil, fl, OK
} }
func (f *keepCacheFile) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status { func (f *keepCacheFile) GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
f.mu.Lock() f.mu.Lock()
defer f.mu.Unlock() defer f.mu.Unlock()
out.Size = uint64(len(f.content)) out.Size = uint64(len(f.content))
return fuse.OK return OK
} }
func (f *keepCacheFile) Read(ctx context.Context, fh FileHandle, dest []byte, off int64) (fuse.ReadResult, fuse.Status) { func (f *keepCacheFile) Read(ctx context.Context, fh FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
f.setContent(1) f.setContent(1)
f.mu.Lock() f.mu.Lock()
defer f.mu.Unlock() defer f.mu.Unlock()
return fuse.ReadResultData(f.content[off:]), fuse.OK return fuse.ReadResultData(f.content[off:]), OK
} }
type keepCacheRoot struct { type keepCacheRoot struct {
...@@ -112,7 +113,7 @@ func TestKeepCache(t *testing.T) { ...@@ -112,7 +113,7 @@ func TestKeepCache(t *testing.T) {
t.Errorf("keep read 2 got %q want read 1 %q", c2, c1) t.Errorf("keep read 2 got %q want read 1 %q", c2, c1)
} }
if s := InodeOf(root.keep).NotifyContent(0, 100); !s.Ok() { if s := InodeOf(root.keep).NotifyContent(0, 100); s != OK {
t.Errorf("NotifyContent: %v", s) t.Errorf("NotifyContent: %v", s)
} }
......
// Copyright 2019 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nodefs
import (
"syscall"
"github.com/hanwen/go-fuse/fuse"
)
// OK is the Errno return value to indicate absense of errors.
var OK = syscall.Errno(0)
func ToErrno(err error) syscall.Errno {
s := fuse.ToStatus(err)
return syscall.Errno(s)
}
// Copyright 2019 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nodefs
import "syscall"
// ENOATTR indicates that an extended attribute was not present.
var ENOATTR = syscall.ENOATTR
// Copyright 2019 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nodefs
import "syscall"
// ENOATTR indicates that an extended attribute was not present.
var ENOATTR = syscall.ENODATA
...@@ -7,6 +7,7 @@ package nodefs ...@@ -7,6 +7,7 @@ package nodefs
import ( import (
"context" "context"
"sync/atomic" "sync/atomic"
"syscall"
"unsafe" "unsafe"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
...@@ -62,10 +63,10 @@ func (n *DefaultOperations) Inode() *Inode { ...@@ -62,10 +63,10 @@ func (n *DefaultOperations) Inode() *Inode {
// StatFs zeroes the out argument and returns OK. This is because OSX // StatFs zeroes the out argument and returns OK. This is because OSX
// filesystems must define this, or the mount will not work. // filesystems must define this, or the mount will not work.
func (n *DefaultOperations) StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Status { func (n *DefaultOperations) StatFs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
// this should be defined on OSX, or the FS won't mount // this should be defined on OSX, or the FS won't mount
*out = fuse.StatfsOut{} *out = fuse.StatfsOut{}
return fuse.OK return OK
} }
// The default OnAdd does nothing. // The default OnAdd does nothing.
...@@ -73,37 +74,37 @@ func (n *DefaultOperations) OnAdd(ctx context.Context) { ...@@ -73,37 +74,37 @@ func (n *DefaultOperations) OnAdd(ctx context.Context) {
} }
// GetAttr zeroes out argument and returns OK. // GetAttr zeroes out argument and returns OK.
func (n *DefaultOperations) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status { func (n *DefaultOperations) GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
*out = fuse.AttrOut{} *out = fuse.AttrOut{}
return fuse.OK return OK
} }
func (n *DefaultOperations) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status { func (n *DefaultOperations) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
return fuse.EROFS return syscall.EROFS
} }
// The Access default implementation checks traditional unix // The Access default implementation checks traditional unix
// permissions of the GetAttr result agains the caller. // permissions of the GetAttr result agains the caller.
func (n *DefaultOperations) Access(ctx context.Context, mask uint32) fuse.Status { func (n *DefaultOperations) Access(ctx context.Context, mask uint32) syscall.Errno {
caller, ok := fuse.FromContext(ctx) caller, ok := fuse.FromContext(ctx)
if !ok { if !ok {
return fuse.EINVAL return syscall.EINVAL
} }
var out fuse.AttrOut var out fuse.AttrOut
if s := InodeOf(n).Operations().GetAttr(ctx, &out); !s.Ok() { if s := InodeOf(n).Operations().GetAttr(ctx, &out); s != 0 {
return s return s
} }
if !internal.HasAccess(caller.Uid, caller.Gid, out.Uid, out.Gid, out.Mode, mask) { if !internal.HasAccess(caller.Uid, caller.Gid, out.Uid, out.Gid, out.Mode, mask) {
return fuse.EACCES return syscall.EACCES
} }
return fuse.OK return OK
} }
// FSetAttr delegates to the FileHandle's if f is not nil, or else to the // FSetAttr delegates to the FileHandle's if f is not nil, or else to the
// Inode's SetAttr method. // Inode's SetAttr method.
func (n *DefaultOperations) FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status { func (n *DefaultOperations) FSetAttr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
if f != nil { if f != nil {
return f.SetAttr(ctx, in, out) return f.SetAttr(ctx, in, out)
} }
...@@ -113,163 +114,163 @@ func (n *DefaultOperations) FSetAttr(ctx context.Context, f FileHandle, in *fuse ...@@ -113,163 +114,163 @@ func (n *DefaultOperations) FSetAttr(ctx context.Context, f FileHandle, in *fuse
// The Lookup method on the DefaultOperations type looks for an // The Lookup method on the DefaultOperations type looks for an
// existing child with the given name, or returns ENOENT. // existing child with the given name, or returns ENOENT.
func (n *DefaultOperations) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *DefaultOperations) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
ch := InodeOf(n).GetChild(name) ch := InodeOf(n).GetChild(name)
if ch == nil { if ch == nil {
return nil, fuse.ENOENT return nil, syscall.ENOENT
} }
var a fuse.AttrOut var a fuse.AttrOut
status := ch.Operations().GetAttr(ctx, &a) errno := ch.Operations().GetAttr(ctx, &a)
out.Attr = a.Attr out.Attr = a.Attr
return ch, status return ch, errno
} }
// Mkdir returns EROFS // Mkdir returns EROFS
func (n *DefaultOperations) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *DefaultOperations) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) {
return nil, fuse.EROFS return nil, syscall.EROFS
} }
// Mknod returns EROFS // Mknod returns EROFS
func (n *DefaultOperations) Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *DefaultOperations) Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) {
return nil, fuse.EROFS return nil, syscall.EROFS
} }
// Rmdir returns EROFS // Rmdir returns EROFS
func (n *DefaultOperations) Rmdir(ctx context.Context, name string) fuse.Status { func (n *DefaultOperations) Rmdir(ctx context.Context, name string) syscall.Errno {
return fuse.EROFS return syscall.EROFS
} }
// Unlink returns EROFS // Unlink returns EROFS
func (n *DefaultOperations) Unlink(ctx context.Context, name string) fuse.Status { func (n *DefaultOperations) Unlink(ctx context.Context, name string) syscall.Errno {
return fuse.EROFS return syscall.EROFS
} }
// The default OpenDir always succeeds // The default OpenDir always succeeds
func (n *DefaultOperations) OpenDir(ctx context.Context) fuse.Status { func (n *DefaultOperations) OpenDir(ctx context.Context) syscall.Errno {
return fuse.OK return OK
} }
// The default ReadDir returns the list of children from the tree // The default ReadDir returns the list of children from the tree
func (n *DefaultOperations) ReadDir(ctx context.Context) (DirStream, fuse.Status) { func (n *DefaultOperations) ReadDir(ctx context.Context) (DirStream, syscall.Errno) {
r := []fuse.DirEntry{} r := []fuse.DirEntry{}
for k, ch := range InodeOf(n).Children() { for k, ch := range InodeOf(n).Children() {
r = append(r, fuse.DirEntry{Mode: ch.Mode(), r = append(r, fuse.DirEntry{Mode: ch.Mode(),
Name: k, Name: k,
Ino: ch.NodeAttr().Ino}) Ino: ch.NodeAttr().Ino})
} }
return NewListDirStream(r), fuse.OK return NewListDirStream(r), 0
} }
// Rename returns EROFS // Rename returns EROFS
func (n *DefaultOperations) Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) fuse.Status { func (n *DefaultOperations) Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) syscall.Errno {
return fuse.EROFS return syscall.EROFS
} }
// Read delegates to the FileHandle argument. // Read delegates to the FileHandle argument.
func (n *DefaultOperations) Read(ctx context.Context, f FileHandle, dest []byte, off int64) (fuse.ReadResult, fuse.Status) { func (n *DefaultOperations) Read(ctx context.Context, f FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
if f != nil { if f != nil {
return f.Read(ctx, dest, off) return f.Read(ctx, dest, off)
} }
return nil, fuse.ENOTSUP return nil, syscall.ENOTSUP
} }
// Symlink returns EROFS // Symlink returns EROFS
func (n *DefaultOperations) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (node *Inode, status fuse.Status) { func (n *DefaultOperations) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (node *Inode, errno syscall.Errno) {
return nil, fuse.EROFS return nil, syscall.EROFS
} }
// Readlink return ENOTSUP // Readlink return ENOTSUP
func (n *DefaultOperations) Readlink(ctx context.Context) ([]byte, fuse.Status) { func (n *DefaultOperations) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
return nil, fuse.ENOTSUP return nil, syscall.ENOTSUP
} }
// Fsync delegates to the FileHandle // Fsync delegates to the FileHandle
func (n *DefaultOperations) Fsync(ctx context.Context, f FileHandle, flags uint32) fuse.Status { func (n *DefaultOperations) Fsync(ctx context.Context, f FileHandle, flags uint32) syscall.Errno {
if f != nil { if f != nil {
return f.Fsync(ctx, flags) return f.Fsync(ctx, flags)
} }
return fuse.ENOTSUP return syscall.ENOTSUP
} }
// Write delegates to the FileHandle // Write delegates to the FileHandle
func (n *DefaultOperations) Write(ctx context.Context, f FileHandle, data []byte, off int64) (written uint32, status fuse.Status) { func (n *DefaultOperations) Write(ctx context.Context, f FileHandle, data []byte, off int64) (written uint32, errno syscall.Errno) {
if f != nil { if f != nil {
return f.Write(ctx, data, off) return f.Write(ctx, data, off)
} }
return 0, fuse.EROFS return 0, syscall.EROFS
} }
func (n *DefaultOperations) CopyFileRange(ctx context.Context, fhIn FileHandle, func (n *DefaultOperations) CopyFileRange(ctx context.Context, fhIn FileHandle,
offIn uint64, out *Inode, fhOut FileHandle, offOut uint64, offIn uint64, out *Inode, fhOut FileHandle, offOut uint64,
len uint64, flags uint64) (uint32, fuse.Status) { len uint64, flags uint64) (uint32, syscall.Errno) {
return 0, fuse.EROFS return 0, syscall.EROFS
} }
func (n *DefaultOperations) Lseek(ctx context.Context, f FileHandle, off uint64, whence uint32) (uint64, fuse.Status) { func (n *DefaultOperations) Lseek(ctx context.Context, f FileHandle, off uint64, whence uint32) (uint64, syscall.Errno) {
if f != nil { if f != nil {
return f.Lseek(ctx, off, whence) return f.Lseek(ctx, off, whence)
} }
return 0, fuse.ENOTSUP return 0, syscall.ENOTSUP
} }
// GetLk delegates to the FileHandlef // GetLk delegates to the FileHandlef
func (n *DefaultOperations) GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) { func (n *DefaultOperations) GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (errno syscall.Errno) {
if f != nil { if f != nil {
return f.GetLk(ctx, owner, lk, flags, out) return f.GetLk(ctx, owner, lk, flags, out)
} }
return fuse.ENOTSUP return syscall.ENOTSUP
} }
// SetLk delegates to the FileHandle // SetLk delegates to the FileHandle
func (n *DefaultOperations) SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) { func (n *DefaultOperations) SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
if f != nil { if f != nil {
return f.SetLk(ctx, owner, lk, flags) return f.SetLk(ctx, owner, lk, flags)
} }
return fuse.ENOTSUP return syscall.ENOTSUP
} }
// SetLkw delegates to the FileHandle // SetLkw delegates to the FileHandle
func (n *DefaultOperations) SetLkw(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) { func (n *DefaultOperations) SetLkw(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
if f != nil { if f != nil {
return f.SetLkw(ctx, owner, lk, flags) return f.SetLkw(ctx, owner, lk, flags)
} }
return fuse.ENOTSUP return syscall.ENOTSUP
} }
// Flush delegates to the FileHandle // Flush delegates to the FileHandle
func (n *DefaultOperations) Flush(ctx context.Context, f FileHandle) fuse.Status { func (n *DefaultOperations) Flush(ctx context.Context, f FileHandle) syscall.Errno {
if f != nil { if f != nil {
return f.Flush(ctx) return f.Flush(ctx)
} }
return fuse.ENOTSUP return syscall.ENOTSUP
} }
// Release delegates to the FileHandle // Release delegates to the FileHandle
func (n *DefaultOperations) Release(ctx context.Context, f FileHandle) fuse.Status { func (n *DefaultOperations) Release(ctx context.Context, f FileHandle) syscall.Errno {
if f != nil { if f != nil {
return f.Release(ctx) return f.Release(ctx)
} }
return fuse.OK return OK
} }
// Allocate delegates to the FileHandle // Allocate delegates to the FileHandle
func (n *DefaultOperations) Allocate(ctx context.Context, f FileHandle, off uint64, size uint64, mode uint32) (status fuse.Status) { func (n *DefaultOperations) Allocate(ctx context.Context, f FileHandle, off uint64, size uint64, mode uint32) (errno syscall.Errno) {
if f != nil { if f != nil {
return f.Allocate(ctx, off, size, mode) return f.Allocate(ctx, off, size, mode)
} }
return fuse.ENOTSUP return syscall.ENOTSUP
} }
// FGetAttr delegates to the FileHandle's if f is not nil, or else to the // FGetAttr delegates to the FileHandle's if f is not nil, or else to the
// Inode's GetAttr method. // Inode's GetAttr method.
func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status { func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno {
if f != nil { if f != nil {
f.GetAttr(ctx, out) f.GetAttr(ctx, out)
} }
...@@ -277,38 +278,38 @@ func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fus ...@@ -277,38 +278,38 @@ func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fus
} }
// Open returns ENOTSUP // Open returns ENOTSUP
func (n *DefaultOperations) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) { func (n *DefaultOperations) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
return nil, 0, fuse.ENOTSUP return nil, 0, syscall.ENOTSUP
} }
// Create returns ENOTSUP // Create returns ENOTSUP
func (n *DefaultOperations) Create(ctx context.Context, name string, flags uint32, mode uint32) (node *Inode, fh FileHandle, fuseFlags uint32, status fuse.Status) { func (n *DefaultOperations) Create(ctx context.Context, name string, flags uint32, mode uint32) (node *Inode, fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
return nil, nil, 0, fuse.EROFS return nil, nil, 0, syscall.EROFS
} }
// Link returns ENOTSUP // Link returns ENOTSUP
func (n *DefaultOperations) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (node *Inode, status fuse.Status) { func (n *DefaultOperations) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (node *Inode, errno syscall.Errno) {
return nil, fuse.EROFS return nil, syscall.EROFS
} }
// The default GetXAttr returns ENOATTR // The default GetXAttr returns ENOATTR
func (n *DefaultOperations) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, fuse.Status) { func (n *DefaultOperations) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
return 0, fuse.ENOATTR return 0, ENOATTR
} }
// The default SetXAttr returns ENOATTR // The default SetXAttr returns ENOATTR
func (n *DefaultOperations) SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) fuse.Status { func (n *DefaultOperations) SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
return fuse.EROFS return syscall.EROFS
} }
// The default RemoveXAttr returns ENOATTR // The default RemoveXAttr returns ENOATTR
func (n *DefaultOperations) RemoveXAttr(ctx context.Context, attr string) fuse.Status { func (n *DefaultOperations) RemoveXAttr(ctx context.Context, attr string) syscall.Errno {
return fuse.ENOATTR return ENOATTR
} }
// The default RemoveXAttr returns an empty list // The default RemoveXAttr returns an empty list
func (n *DefaultOperations) ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status) { func (n *DefaultOperations) ListXAttr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
return 0, fuse.OK return 0, OK
} }
// DefaultFileHandle satisfies the FileHandle interface, and provides // DefaultFileHandle satisfies the FileHandle interface, and provides
...@@ -318,50 +319,50 @@ type DefaultFileHandle struct { ...@@ -318,50 +319,50 @@ type DefaultFileHandle struct {
var _ = FileHandle((*DefaultFileHandle)(nil)) var _ = FileHandle((*DefaultFileHandle)(nil))
func (f *DefaultFileHandle) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, fuse.Status) { func (f *DefaultFileHandle) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
return nil, fuse.ENOTSUP return nil, syscall.ENOTSUP
} }
func (f *DefaultFileHandle) Write(ctx context.Context, data []byte, off int64) (written uint32, status fuse.Status) { func (f *DefaultFileHandle) Write(ctx context.Context, data []byte, off int64) (written uint32, errno syscall.Errno) {
return 0, fuse.ENOTSUP return 0, syscall.ENOTSUP
} }
func (f *DefaultFileHandle) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) { func (f *DefaultFileHandle) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (errno syscall.Errno) {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) { func (f *DefaultFileHandle) SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) { func (f *DefaultFileHandle) SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) Flush(ctx context.Context) fuse.Status { func (f *DefaultFileHandle) Flush(ctx context.Context) syscall.Errno {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) Release(ctx context.Context) fuse.Status { func (f *DefaultFileHandle) Release(ctx context.Context) syscall.Errno {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status { func (f *DefaultFileHandle) GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status { func (f *DefaultFileHandle) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (status fuse.Status) { func (f *DefaultFileHandle) Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (errno syscall.Errno) {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) Fsync(ctx context.Context, flags uint32) (status fuse.Status) { func (f *DefaultFileHandle) Fsync(ctx context.Context, flags uint32) (errno syscall.Errno) {
return fuse.ENOTSUP return syscall.ENOTSUP
} }
func (f *DefaultFileHandle) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, fuse.Status) { func (f *DefaultFileHandle) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, syscall.Errno) {
return 0, fuse.ENOTSUP return 0, syscall.ENOTSUP
} }
...@@ -30,14 +30,14 @@ type dioFH struct { ...@@ -30,14 +30,14 @@ type dioFH struct {
DefaultFileHandle DefaultFileHandle
} }
func (f *dioFH) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, fuse.Status) { func (f *dioFH) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, syscall.Errno) {
next := (off + 1023) & (^uint64(1023)) next := (off + 1023) & (^uint64(1023))
return next, fuse.OK return next, OK
} }
func (fh *dioFH) Read(ctx context.Context, data []byte, off int64) (fuse.ReadResult, fuse.Status) { func (fh *dioFH) Read(ctx context.Context, data []byte, off int64) (fuse.ReadResult, syscall.Errno) {
r := bytes.Repeat([]byte(fmt.Sprintf("%010d", off)), 1+len(data)/10) r := bytes.Repeat([]byte(fmt.Sprintf("%010d", off)), 1+len(data)/10)
return fuse.ReadResultData(r[:len(data)]), fuse.OK return fuse.ReadResultData(r[:len(data)]), OK
} }
// overrides Open so it can return a dioFH file handle // overrides Open so it can return a dioFH file handle
...@@ -45,8 +45,8 @@ type dioFile struct { ...@@ -45,8 +45,8 @@ type dioFile struct {
DefaultOperations DefaultOperations
} }
func (f *dioFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) { func (f *dioFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
return &dioFH{}, fuse.FOPEN_DIRECT_IO, fuse.OK return &dioFH{}, fuse.FOPEN_DIRECT_IO, OK
} }
func TestDirectIO(t *testing.T) { func TestDirectIO(t *testing.T) {
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package nodefs package nodefs
import ( import (
"syscall"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
) )
...@@ -16,10 +18,10 @@ func (a *dirArray) HasNext() bool { ...@@ -16,10 +18,10 @@ func (a *dirArray) HasNext() bool {
return len(a.entries) > 0 return len(a.entries) > 0
} }
func (a *dirArray) Next() (fuse.DirEntry, fuse.Status) { func (a *dirArray) Next() (fuse.DirEntry, syscall.Errno) {
e := a.entries[0] e := a.entries[0]
a.entries = a.entries[1:] a.entries = a.entries[1:]
return e, fuse.OK return e, 0
} }
func (a *dirArray) Close() { func (a *dirArray) Close() {
......
...@@ -7,14 +7,15 @@ package nodefs ...@@ -7,14 +7,15 @@ package nodefs
import ( import (
"io" "io"
"os" "os"
"syscall"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
) )
func NewLoopbackDirStream(nm string) (DirStream, fuse.Status) { func NewLoopbackDirStream(nm string) (DirStream, syscall.Errno) {
f, err := os.Open(nm) f, err := os.Open(nm)
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
defer f.Close() defer f.Close()
...@@ -39,9 +40,9 @@ func NewLoopbackDirStream(nm string) (DirStream, fuse.Status) { ...@@ -39,9 +40,9 @@ func NewLoopbackDirStream(nm string) (DirStream, fuse.Status) {
} }
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
} }
return &dirArray{entries}, fuse.OK return &dirArray{entries}, OK
} }
...@@ -18,10 +18,10 @@ type loopbackDirStream struct { ...@@ -18,10 +18,10 @@ type loopbackDirStream struct {
} }
// NewLoopbackDirStream open a directory for reading as a DirStream // NewLoopbackDirStream open a directory for reading as a DirStream
func NewLoopbackDirStream(name string) (DirStream, fuse.Status) { func NewLoopbackDirStream(name string) (DirStream, syscall.Errno) {
fd, err := syscall.Open(name, syscall.O_DIRECTORY, 0755) fd, err := syscall.Open(name, syscall.O_DIRECTORY, 0755)
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
ds := &loopbackDirStream{ ds := &loopbackDirStream{
...@@ -29,11 +29,11 @@ func NewLoopbackDirStream(name string) (DirStream, fuse.Status) { ...@@ -29,11 +29,11 @@ func NewLoopbackDirStream(name string) (DirStream, fuse.Status) {
fd: fd, fd: fd,
} }
if err := ds.load(); !err.Ok() { if err := ds.load(); err != 0 {
ds.Close() ds.Close()
return nil, err return nil, err
} }
return ds, fuse.OK return ds, OK
} }
func (ds *loopbackDirStream) Close() { func (ds *loopbackDirStream) Close() {
...@@ -44,7 +44,7 @@ func (ds *loopbackDirStream) HasNext() bool { ...@@ -44,7 +44,7 @@ func (ds *loopbackDirStream) HasNext() bool {
return len(ds.todo) > 0 return len(ds.todo) > 0
} }
func (ds *loopbackDirStream) Next() (fuse.DirEntry, fuse.Status) { func (ds *loopbackDirStream) Next() (fuse.DirEntry, syscall.Errno) {
de := (*syscall.Dirent)(unsafe.Pointer(&ds.todo[0])) de := (*syscall.Dirent)(unsafe.Pointer(&ds.todo[0]))
nameBytes := ds.todo[unsafe.Offsetof(syscall.Dirent{}.Name):de.Reclen] nameBytes := ds.todo[unsafe.Offsetof(syscall.Dirent{}.Name):de.Reclen]
...@@ -64,15 +64,15 @@ func (ds *loopbackDirStream) Next() (fuse.DirEntry, fuse.Status) { ...@@ -64,15 +64,15 @@ func (ds *loopbackDirStream) Next() (fuse.DirEntry, fuse.Status) {
return result, ds.load() return result, ds.load()
} }
func (ds *loopbackDirStream) load() fuse.Status { func (ds *loopbackDirStream) load() syscall.Errno {
if len(ds.todo) > 0 { if len(ds.todo) > 0 {
return fuse.OK return OK
} }
n, err := syscall.Getdents(ds.fd, ds.buf) n, err := syscall.Getdents(ds.fd, ds.buf)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
ds.todo = ds.buf[:n] ds.todo = ds.buf[:n]
return fuse.OK return OK
} }
...@@ -24,36 +24,36 @@ type loopbackFile struct { ...@@ -24,36 +24,36 @@ type loopbackFile struct {
fd int fd int
} }
func (f *loopbackFile) Read(ctx context.Context, buf []byte, off int64) (res fuse.ReadResult, status fuse.Status) { func (f *loopbackFile) Read(ctx context.Context, buf []byte, off int64) (res fuse.ReadResult, errno syscall.Errno) {
r := fuse.ReadResultFd(uintptr(f.fd), off, len(buf)) r := fuse.ReadResultFd(uintptr(f.fd), off, len(buf))
return r, fuse.OK return r, OK
} }
func (f *loopbackFile) Write(ctx context.Context, data []byte, off int64) (uint32, fuse.Status) { func (f *loopbackFile) Write(ctx context.Context, data []byte, off int64) (uint32, syscall.Errno) {
n, err := syscall.Pwrite(f.fd, data, off) n, err := syscall.Pwrite(f.fd, data, off)
return uint32(n), fuse.ToStatus(err) return uint32(n), ToErrno(err)
} }
func (f *loopbackFile) Release(ctx context.Context) fuse.Status { func (f *loopbackFile) Release(ctx context.Context) syscall.Errno {
err := syscall.Close(f.fd) err := syscall.Close(f.fd)
return fuse.ToStatus(err) return ToErrno(err)
} }
func (f *loopbackFile) Flush(ctx context.Context) fuse.Status { func (f *loopbackFile) Flush(ctx context.Context) syscall.Errno {
// Since Flush() may be called for each dup'd fd, we don't // Since Flush() may be called for each dup'd fd, we don't
// want to really close the file, we just want to flush. This // want to really close the file, we just want to flush. This
// is achieved by closing a dup'd fd. // is achieved by closing a dup'd fd.
newFd, err := syscall.Dup(f.fd) newFd, err := syscall.Dup(f.fd)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
err = syscall.Close(newFd) err = syscall.Close(newFd)
return fuse.ToStatus(err) return ToErrno(err)
} }
func (f *loopbackFile) Fsync(ctx context.Context, flags uint32) (status fuse.Status) { func (f *loopbackFile) Fsync(ctx context.Context, flags uint32) (errno syscall.Errno) {
r := fuse.ToStatus(syscall.Fsync(f.fd)) r := ToErrno(syscall.Fsync(f.fd))
return r return r
} }
...@@ -64,23 +64,23 @@ const ( ...@@ -64,23 +64,23 @@ const (
_OFD_SETLKW = 38 _OFD_SETLKW = 38
) )
func (f *loopbackFile) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) { func (f *loopbackFile) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (errno syscall.Errno) {
flk := syscall.Flock_t{} flk := syscall.Flock_t{}
lk.ToFlockT(&flk) lk.ToFlockT(&flk)
status = fuse.ToStatus(syscall.FcntlFlock(uintptr(f.fd), _OFD_GETLK, &flk)) errno = ToErrno(syscall.FcntlFlock(uintptr(f.fd), _OFD_GETLK, &flk))
out.FromFlockT(&flk) out.FromFlockT(&flk)
return return
} }
func (f *loopbackFile) SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) { func (f *loopbackFile) SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
return f.setLock(ctx, owner, lk, flags, false) return f.setLock(ctx, owner, lk, flags, false)
} }
func (f *loopbackFile) SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) { func (f *loopbackFile) SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
return f.setLock(ctx, owner, lk, flags, true) return f.setLock(ctx, owner, lk, flags, true)
} }
func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, blocking bool) (status fuse.Status) { func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, blocking bool) (errno syscall.Errno) {
if (flags & fuse.FUSE_LK_FLOCK) != 0 { if (flags & fuse.FUSE_LK_FLOCK) != 0 {
var op int var op int
switch lk.Typ { switch lk.Typ {
...@@ -91,12 +91,12 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL ...@@ -91,12 +91,12 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
case syscall.F_UNLCK: case syscall.F_UNLCK:
op = syscall.LOCK_UN op = syscall.LOCK_UN
default: default:
return fuse.EINVAL return syscall.EINVAL
} }
if !blocking { if !blocking {
op |= syscall.LOCK_NB op |= syscall.LOCK_NB
} }
return fuse.ToStatus(syscall.Flock(f.fd, op)) return ToErrno(syscall.Flock(f.fd, op))
} else { } else {
flk := syscall.Flock_t{} flk := syscall.Flock_t{}
lk.ToFlockT(&flk) lk.ToFlockT(&flk)
...@@ -106,24 +106,24 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL ...@@ -106,24 +106,24 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
} else { } else {
op = _OFD_SETLK op = _OFD_SETLK
} }
return fuse.ToStatus(syscall.FcntlFlock(uintptr(f.fd), op, &flk)) return ToErrno(syscall.FcntlFlock(uintptr(f.fd), op, &flk))
} }
} }
func (f *loopbackFile) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status { func (f *loopbackFile) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
if status := f.setAttr(ctx, in); !status.Ok() { if errno := f.setAttr(ctx, in); errno != 0 {
return status return errno
} }
return f.GetAttr(ctx, out) return f.GetAttr(ctx, out)
} }
func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Status { func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) syscall.Errno {
var status fuse.Status var errno syscall.Errno
if mode, ok := in.GetMode(); ok { if mode, ok := in.GetMode(); ok {
status = fuse.ToStatus(syscall.Fchmod(f.fd, mode)) errno = ToErrno(syscall.Fchmod(f.fd, mode))
if !status.Ok() { if errno != 0 {
return status return errno
} }
} }
...@@ -139,9 +139,9 @@ func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Sta ...@@ -139,9 +139,9 @@ func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Sta
if gOk { if gOk {
gid = int(gid32) gid = int(gid32)
} }
status = fuse.ToStatus(syscall.Fchown(f.fd, uid, gid)) errno = ToErrno(syscall.Fchown(f.fd, uid, gid))
if !status.Ok() { if errno != 0 {
return status return errno
} }
} }
...@@ -157,33 +157,33 @@ func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Sta ...@@ -157,33 +157,33 @@ func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Sta
if !mok { if !mok {
mp = nil mp = nil
} }
status = f.utimens(ap, mp) errno = f.utimens(ap, mp)
if !status.Ok() { if errno != 0 {
return status return errno
} }
} }
if sz, ok := in.GetSize(); ok { if sz, ok := in.GetSize(); ok {
status = fuse.ToStatus(syscall.Ftruncate(f.fd, int64(sz))) errno = ToErrno(syscall.Ftruncate(f.fd, int64(sz)))
if !status.Ok() { if errno != 0 {
return status return errno
} }
} }
return fuse.OK return OK
} }
func (f *loopbackFile) GetAttr(ctx context.Context, a *fuse.AttrOut) fuse.Status { func (f *loopbackFile) GetAttr(ctx context.Context, a *fuse.AttrOut) syscall.Errno {
st := syscall.Stat_t{} st := syscall.Stat_t{}
err := syscall.Fstat(f.fd, &st) err := syscall.Fstat(f.fd, &st)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
a.FromStat(&st) a.FromStat(&st)
return fuse.OK return OK
} }
func (f *loopbackFile) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, fuse.Status) { func (f *loopbackFile) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, syscall.Errno) {
n, err := unix.Seek(f.fd, int64(off), int(whence)) n, err := unix.Seek(f.fd, int64(off), int(whence))
return uint64(n), fuse.ToStatus(err) return uint64(n), ToErrno(err)
} }
...@@ -6,15 +6,14 @@ package nodefs ...@@ -6,15 +6,14 @@ package nodefs
import ( import (
"context" "context"
"syscall"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
) )
func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) fuse.Status { func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) syscall.Errno {
return fuse.ENOSYS return syscall.ENOSYS
} }
func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time) fuse.Status { func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time) syscall.Errno {
return fuse.ENOSYS return syscall.ENOSYS
} }
...@@ -12,19 +12,19 @@ import ( ...@@ -12,19 +12,19 @@ import (
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
) )
func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) fuse.Status { func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) syscall.Errno {
err := syscall.Fallocate(f.fd, mode, int64(off), int64(sz)) err := syscall.Fallocate(f.fd, mode, int64(off), int64(sz))
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
return fuse.OK return OK
} }
// Utimens - file handle based version of loopbackFileSystem.Utimens() // Utimens - file handle based version of loopbackFileSystem.Utimens()
func (f *loopbackFile) utimens(a *time.Time, m *time.Time) fuse.Status { func (f *loopbackFile) utimens(a *time.Time, m *time.Time) syscall.Errno {
var ts [2]syscall.Timespec var ts [2]syscall.Timespec
ts[0] = fuse.UtimeToTimespec(a) ts[0] = fuse.UtimeToTimespec(a)
ts[1] = fuse.UtimeToTimespec(m) ts[1] = fuse.UtimeToTimespec(m)
err := futimens(int(f.fd), &ts) err := futimens(int(f.fd), &ts)
return fuse.ToStatus(err) return ToErrno(err)
} }
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"sort" "sort"
"strings" "strings"
"sync" "sync"
"syscall"
"unsafe" "unsafe"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
...@@ -631,33 +632,34 @@ retry: ...@@ -631,33 +632,34 @@ retry:
// NotifyEntry notifies the kernel that data for a (directory, name) // NotifyEntry notifies the kernel that data for a (directory, name)
// tuple should be invalidated. On next access, a LOOKUP operation // tuple should be invalidated. On next access, a LOOKUP operation
// will be started. // will be started.
func (n *Inode) NotifyEntry(name string) fuse.Status { func (n *Inode) NotifyEntry(name string) syscall.Errno {
return n.bridge.server.EntryNotify(n.nodeAttr.Ino, name) status := n.bridge.server.EntryNotify(n.nodeAttr.Ino, name)
return syscall.Errno(status)
} }
// NotifyDelete notifies the kernel that the given inode was removed // NotifyDelete notifies the kernel that the given inode was removed
// from this directory as entry under the given name. It is equivalent // from this directory as entry under the given name. It is equivalent
// to NotifyEntry, but also sends an event to inotify watchers. // to NotifyEntry, but also sends an event to inotify watchers.
func (n *Inode) NotifyDelete(name string, child *Inode) fuse.Status { func (n *Inode) NotifyDelete(name string, child *Inode) syscall.Errno {
// XXX arg ordering? // XXX arg ordering?
return n.bridge.server.DeleteNotify(n.nodeAttr.Ino, child.nodeAttr.Ino, name) return syscall.Errno(n.bridge.server.DeleteNotify(n.nodeAttr.Ino, child.nodeAttr.Ino, name))
} }
// NotifyContent notifies the kernel that content under the given // NotifyContent notifies the kernel that content under the given
// inode should be flushed from buffers. // inode should be flushed from buffers.
func (n *Inode) NotifyContent(off, sz int64) fuse.Status { func (n *Inode) NotifyContent(off, sz int64) syscall.Errno {
// XXX how does this work for directories? // XXX how does this work for directories?
return n.bridge.server.InodeNotify(n.nodeAttr.Ino, off, sz) return syscall.Errno(n.bridge.server.InodeNotify(n.nodeAttr.Ino, off, sz))
} }
// WriteCache stores data in the kernel cache. // WriteCache stores data in the kernel cache.
func (n *Inode) WriteCache(offset int64, data []byte) fuse.Status { func (n *Inode) WriteCache(offset int64, data []byte) syscall.Errno {
return n.bridge.server.InodeNotifyStoreCache(n.nodeAttr.Ino, offset, data) return syscall.Errno(n.bridge.server.InodeNotifyStoreCache(n.nodeAttr.Ino, offset, data))
} }
// ReadCache reads data from the kernel cache. // ReadCache reads data from the kernel cache.
func (n *Inode) ReadCache(offset int64, dest []byte) (count int, status fuse.Status) { func (n *Inode) ReadCache(offset int64, dest []byte) (count int, errno syscall.Errno) {
return n.bridge.server.InodeRetrieveCache(n.nodeAttr.Ino, offset, dest) c, s := n.bridge.server.InodeRetrieveCache(n.nodeAttr.Ino, offset, dest)
return c, syscall.Errno(s)
} }
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"context" "context"
"os" "os"
"os/exec" "os/exec"
"syscall"
"testing" "testing"
"time" "time"
...@@ -25,24 +26,24 @@ type interruptOps struct { ...@@ -25,24 +26,24 @@ type interruptOps struct {
interrupted bool interrupted bool
} }
func (r *interruptRoot) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) { func (r *interruptRoot) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
if name != "file" { if name != "file" {
return nil, fuse.ENOENT return nil, syscall.ENOENT
} }
ch := InodeOf(r).NewInode(ctx, &r.child, NodeAttr{ ch := InodeOf(r).NewInode(ctx, &r.child, NodeAttr{
Ino: 2, Ino: 2,
Gen: 1}) Gen: 1})
return ch, fuse.OK return ch, OK
} }
func (o *interruptOps) Open(ctx context.Context, flags uint32) (FileHandle, uint32, fuse.Status) { func (o *interruptOps) Open(ctx context.Context, flags uint32) (FileHandle, uint32, syscall.Errno) {
select { select {
case <-time.After(100 * time.Millisecond): case <-time.After(100 * time.Millisecond):
return nil, 0, fuse.EIO return nil, 0, syscall.EIO
case <-ctx.Done(): case <-ctx.Done():
o.interrupted = true o.interrupted = true
return nil, 0, fuse.EINTR return nil, 0, syscall.EINTR
} }
} }
......
...@@ -27,25 +27,25 @@ func (n *loopbackRoot) newLoopbackNode() *loopbackNode { ...@@ -27,25 +27,25 @@ func (n *loopbackRoot) newLoopbackNode() *loopbackNode {
} }
} }
func (n *loopbackNode) StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Status { func (n *loopbackNode) StatFs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
s := syscall.Statfs_t{} s := syscall.Statfs_t{}
err := syscall.Statfs(n.path(), &s) err := syscall.Statfs(n.path(), &s)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
out.FromStatfsT(&s) out.FromStatfsT(&s)
return fuse.OK return OK
} }
func (n *loopbackRoot) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status { func (n *loopbackRoot) GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
var err error = nil var err error = nil
st := syscall.Stat_t{} st := syscall.Stat_t{}
err = syscall.Stat(n.root, &st) err = syscall.Stat(n.root, &st)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
out.FromStat(&st) out.FromStat(&st)
return fuse.OK return OK
} }
type loopbackNode struct { type loopbackNode struct {
...@@ -59,31 +59,31 @@ func (n *loopbackNode) path() string { ...@@ -59,31 +59,31 @@ func (n *loopbackNode) path() string {
return filepath.Join(n.rootNode.root, path) return filepath.Join(n.rootNode.root, path)
} }
func (n *loopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *loopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
st := syscall.Stat_t{} st := syscall.Stat_t{}
err := syscall.Lstat(p, &st) err := syscall.Lstat(p, &st)
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
out.Attr.FromStat(&st) out.Attr.FromStat(&st)
node := n.rootNode.newLoopbackNode() node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st)) ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st))
return ch, fuse.OK return ch, 0
} }
func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
err := syscall.Mknod(p, mode, int(rdev)) err := syscall.Mknod(p, mode, int(rdev))
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
st := syscall.Stat_t{} st := syscall.Stat_t{}
if err := syscall.Lstat(p, &st); err != nil { if err := syscall.Lstat(p, &st); err != nil {
syscall.Rmdir(p) syscall.Rmdir(p)
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
out.Attr.FromStat(&st) out.Attr.FromStat(&st)
...@@ -91,19 +91,19 @@ func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32 ...@@ -91,19 +91,19 @@ func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32
node := n.rootNode.newLoopbackNode() node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st)) ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st))
return ch, fuse.OK return ch, 0
} }
func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
err := os.Mkdir(p, os.FileMode(mode)) err := os.Mkdir(p, os.FileMode(mode))
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
st := syscall.Stat_t{} st := syscall.Stat_t{}
if err := syscall.Lstat(p, &st); err != nil { if err := syscall.Lstat(p, &st); err != nil {
syscall.Rmdir(p) syscall.Rmdir(p)
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
out.Attr.FromStat(&st) out.Attr.FromStat(&st)
...@@ -111,19 +111,19 @@ func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out ...@@ -111,19 +111,19 @@ func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out
node := n.rootNode.newLoopbackNode() node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st)) ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st))
return ch, fuse.OK return ch, 0
} }
func (n *loopbackNode) Rmdir(ctx context.Context, name string) fuse.Status { func (n *loopbackNode) Rmdir(ctx context.Context, name string) syscall.Errno {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
err := syscall.Rmdir(p) err := syscall.Rmdir(p)
return fuse.ToStatus(err) return ToErrno(err)
} }
func (n *loopbackNode) Unlink(ctx context.Context, name string) fuse.Status { func (n *loopbackNode) Unlink(ctx context.Context, name string) syscall.Errno {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
err := syscall.Unlink(p) err := syscall.Unlink(p)
return fuse.ToStatus(err) return ToErrno(err)
} }
func toLoopbackNode(op Operations) *loopbackNode { func toLoopbackNode(op Operations) *loopbackNode {
...@@ -133,7 +133,7 @@ func toLoopbackNode(op Operations) *loopbackNode { ...@@ -133,7 +133,7 @@ func toLoopbackNode(op Operations) *loopbackNode {
return op.(*loopbackNode) return op.(*loopbackNode)
} }
func (n *loopbackNode) Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) fuse.Status { func (n *loopbackNode) Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) syscall.Errno {
newParentLoopback := toLoopbackNode(newParent) newParentLoopback := toLoopbackNode(newParent)
if flags&unix.RENAME_EXCHANGE != 0 { if flags&unix.RENAME_EXCHANGE != 0 {
return n.renameExchange(name, newParentLoopback, newName) return n.renameExchange(name, newParentLoopback, newName)
...@@ -143,7 +143,7 @@ func (n *loopbackNode) Rename(ctx context.Context, name string, newParent Operat ...@@ -143,7 +143,7 @@ func (n *loopbackNode) Rename(ctx context.Context, name string, newParent Operat
p2 := filepath.Join(newParentLoopback.path(), newName) p2 := filepath.Join(newParentLoopback.path(), newName)
err := os.Rename(p1, p2) err := os.Rename(p1, p2)
return fuse.ToStatus(err) return ToErrno(err)
} }
func (r *loopbackRoot) idFromStat(st *syscall.Stat_t) NodeAttr { func (r *loopbackRoot) idFromStat(st *syscall.Stat_t) NodeAttr {
...@@ -165,104 +165,104 @@ func (r *loopbackRoot) idFromStat(st *syscall.Stat_t) NodeAttr { ...@@ -165,104 +165,104 @@ func (r *loopbackRoot) idFromStat(st *syscall.Stat_t) NodeAttr {
} }
} }
func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mode uint32) (inode *Inode, fh FileHandle, fuseFlags uint32, status fuse.Status) { func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mode uint32) (inode *Inode, fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode) fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode)
if err != nil { if err != nil {
return nil, nil, 0, fuse.ToStatus(err) return nil, nil, 0, ToErrno(err)
} }
st := syscall.Stat_t{} st := syscall.Stat_t{}
if err := syscall.Fstat(fd, &st); err != nil { if err := syscall.Fstat(fd, &st); err != nil {
syscall.Close(fd) syscall.Close(fd)
return nil, nil, 0, fuse.ToStatus(err) return nil, nil, 0, ToErrno(err)
} }
node := n.rootNode.newLoopbackNode() node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st)) ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st))
lf := NewLoopbackFile(fd) lf := NewLoopbackFile(fd)
return ch, lf, 0, fuse.OK return ch, lf, 0, 0
} }
func (n *loopbackNode) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *loopbackNode) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
err := syscall.Symlink(target, p) err := syscall.Symlink(target, p)
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
st := syscall.Stat_t{} st := syscall.Stat_t{}
if syscall.Lstat(p, &st); err != nil { if syscall.Lstat(p, &st); err != nil {
syscall.Unlink(p) syscall.Unlink(p)
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
node := n.rootNode.newLoopbackNode() node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st)) ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st))
out.Attr.FromStat(&st) out.Attr.FromStat(&st)
return ch, fuse.OK return ch, 0
} }
func (n *loopbackNode) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (*Inode, fuse.Status) { func (n *loopbackNode) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
targetNode := toLoopbackNode(target) targetNode := toLoopbackNode(target)
err := syscall.Link(targetNode.path(), p) err := syscall.Link(targetNode.path(), p)
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
st := syscall.Stat_t{} st := syscall.Stat_t{}
if syscall.Lstat(p, &st); err != nil { if syscall.Lstat(p, &st); err != nil {
syscall.Unlink(p) syscall.Unlink(p)
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
node := n.rootNode.newLoopbackNode() node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st)) ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st))
out.Attr.FromStat(&st) out.Attr.FromStat(&st)
return ch, fuse.OK return ch, 0
} }
func (n *loopbackNode) Readlink(ctx context.Context) ([]byte, fuse.Status) { func (n *loopbackNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
p := n.path() p := n.path()
for l := 256; ; l *= 2 { for l := 256; ; l *= 2 {
buf := make([]byte, l) buf := make([]byte, l)
sz, err := syscall.Readlink(p, buf) sz, err := syscall.Readlink(p, buf)
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, ToErrno(err)
} }
if sz < len(buf) { if sz < len(buf) {
return buf[:sz], fuse.OK return buf[:sz], 0
} }
} }
} }
func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) { func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
p := n.path() p := n.path()
f, err := syscall.Open(p, int(flags), 0) f, err := syscall.Open(p, int(flags), 0)
if err != nil { if err != nil {
return nil, 0, fuse.ToStatus(err) return nil, 0, ToErrno(err)
} }
lf := NewLoopbackFile(f) lf := NewLoopbackFile(f)
return lf, 0, fuse.OK return lf, 0, 0
} }
func (n *loopbackNode) OpenDir(ctx context.Context) fuse.Status { func (n *loopbackNode) OpenDir(ctx context.Context) syscall.Errno {
fd, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0755) fd, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0755)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
syscall.Close(fd) syscall.Close(fd)
return fuse.OK return OK
} }
func (n *loopbackNode) ReadDir(ctx context.Context) (DirStream, fuse.Status) { func (n *loopbackNode) ReadDir(ctx context.Context) (DirStream, syscall.Errno) {
return NewLoopbackDirStream(n.path()) return NewLoopbackDirStream(n.path())
} }
func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) fuse.Status { func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno {
if f != nil { if f != nil {
return f.GetAttr(ctx, out) return f.GetAttr(ctx, out)
} }
...@@ -273,28 +273,28 @@ func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.Att ...@@ -273,28 +273,28 @@ func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.Att
st := syscall.Stat_t{} st := syscall.Stat_t{}
err = syscall.Lstat(p, &st) err = syscall.Lstat(p, &st)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
out.FromStat(&st) out.FromStat(&st)
return fuse.OK return OK
} }
func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle, func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle,
offIn uint64, out *Inode, fhOut FileHandle, offOut uint64, offIn uint64, out *Inode, fhOut FileHandle, offOut uint64,
len uint64, flags uint64) (uint32, fuse.Status) { len uint64, flags uint64) (uint32, syscall.Errno) {
lfIn, ok := fhIn.(*loopbackFile) lfIn, ok := fhIn.(*loopbackFile)
if !ok { if !ok {
return 0, fuse.ENOTSUP return 0, syscall.ENOTSUP
} }
lfOut, ok := fhOut.(*loopbackFile) lfOut, ok := fhOut.(*loopbackFile)
if !ok { if !ok {
return 0, fuse.ENOTSUP return 0, syscall.ENOTSUP
} }
signedOffIn := int64(offIn) signedOffIn := int64(offIn)
signedOffOut := int64(offOut) signedOffOut := int64(offOut)
count, err := unix.CopyFileRange(lfIn.fd, &signedOffIn, lfOut.fd, &signedOffOut, int(len), int(flags)) count, err := unix.CopyFileRange(lfIn.fd, &signedOffIn, lfOut.fd, &signedOffOut, int(len), int(flags))
return uint32(count), fuse.ToStatus(err) return uint32(count), ToErrno(err)
} }
// NewLoopback returns a root node for a loopback file system whose // NewLoopback returns a root node for a loopback file system whose
......
...@@ -8,55 +8,54 @@ import ( ...@@ -8,55 +8,54 @@ import (
"context" "context"
"syscall" "syscall"
"github.com/hanwen/go-fuse/fuse"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
func (n *loopbackNode) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, fuse.Status) { func (n *loopbackNode) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
sz, err := syscall.Getxattr(n.path(), attr, dest) sz, err := syscall.Getxattr(n.path(), attr, dest)
return uint32(sz), fuse.ToStatus(err) return uint32(sz), ToErrno(err)
} }
func (n *loopbackNode) SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) fuse.Status { func (n *loopbackNode) SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
err := syscall.Setxattr(n.path(), attr, data, int(flags)) err := syscall.Setxattr(n.path(), attr, data, int(flags))
return fuse.ToStatus(err) return ToErrno(err)
} }
func (n *loopbackNode) RemoveXAttr(ctx context.Context, attr string) fuse.Status { func (n *loopbackNode) RemoveXAttr(ctx context.Context, attr string) syscall.Errno {
err := syscall.Removexattr(n.path(), attr) err := syscall.Removexattr(n.path(), attr)
return fuse.ToStatus(err) return ToErrno(err)
} }
func (n *loopbackNode) ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status) { func (n *loopbackNode) ListXAttr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
sz, err := syscall.Listxattr(n.path(), dest) sz, err := syscall.Listxattr(n.path(), dest)
return uint32(sz), fuse.ToStatus(err) return uint32(sz), ToErrno(err)
} }
func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newName string) fuse.Status { func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newName string) syscall.Errno {
fd1, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0) fd1, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
defer syscall.Close(fd1) defer syscall.Close(fd1)
fd2, err := syscall.Open(newparent.path(), syscall.O_DIRECTORY, 0) fd2, err := syscall.Open(newparent.path(), syscall.O_DIRECTORY, 0)
defer syscall.Close(fd2) defer syscall.Close(fd2)
if err != nil { if err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
var st syscall.Stat_t var st syscall.Stat_t
if err := syscall.Fstat(fd1, &st); err != nil { if err := syscall.Fstat(fd1, &st); err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
if !n.Inode().IsRoot() && InodeOf(n).NodeAttr().Ino != n.rootNode.idFromStat(&st).Ino { if !n.Inode().IsRoot() && InodeOf(n).NodeAttr().Ino != n.rootNode.idFromStat(&st).Ino {
return fuse.EBUSY return syscall.EBUSY
} }
if err := syscall.Fstat(fd2, &st); err != nil { if err := syscall.Fstat(fd2, &st); err != nil {
return fuse.ToStatus(err) return ToErrno(err)
} }
if !newparent.Inode().IsRoot() && InodeOf(newparent).NodeAttr().Ino != n.rootNode.idFromStat(&st).Ino { if !newparent.Inode().IsRoot() && InodeOf(newparent).NodeAttr().Ino != n.rootNode.idFromStat(&st).Ino {
return fuse.EBUSY return syscall.EBUSY
} }
return fuse.ToStatus(unix.Renameat2(fd1, name, fd2, newName, unix.RENAME_EXCHANGE)) return ToErrno(unix.Renameat2(fd1, name, fd2, newName, unix.RENAME_EXCHANGE))
} }
...@@ -525,8 +525,8 @@ func TestNotifyEntry(t *testing.T) { ...@@ -525,8 +525,8 @@ func TestNotifyEntry(t *testing.T) {
t.Fatalf("got after %#v, want %#v", after, st) t.Fatalf("got after %#v, want %#v", after, st)
} }
if code := tc.loopback.Inode().NotifyEntry("file"); !code.Ok() { if errno := tc.loopback.Inode().NotifyEntry("file"); errno != 0 {
t.Errorf("notify failed: %v", code) t.Errorf("notify failed: %v", errno)
} }
if err := syscall.Lstat(fn, &after); err != syscall.ENOENT { if err := syscall.Lstat(fn, &after); err != syscall.ENOENT {
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
"syscall"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
...@@ -116,23 +117,23 @@ var _ = (FileOperations)((*zipFile)(nil)) ...@@ -116,23 +117,23 @@ var _ = (FileOperations)((*zipFile)(nil))
// GetAttr sets the minimum, which is the size. A more full-featured // GetAttr sets the minimum, which is the size. A more full-featured
// FS would also set timestamps and permissions. // FS would also set timestamps and permissions.
func (zf *zipFile) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status { func (zf *zipFile) GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
out.Size = zf.file.UncompressedSize64 out.Size = zf.file.UncompressedSize64
return fuse.OK return OK
} }
// Open lazily unpacks zip data // Open lazily unpacks zip data
func (zf *zipFile) Open(ctx context.Context, flags uint32) (FileHandle, uint32, fuse.Status) { func (zf *zipFile) Open(ctx context.Context, flags uint32) (FileHandle, uint32, syscall.Errno) {
zf.mu.Lock() zf.mu.Lock()
defer zf.mu.Unlock() defer zf.mu.Unlock()
if zf.data == nil { if zf.data == nil {
rc, err := zf.file.Open() rc, err := zf.file.Open()
if err != nil { if err != nil {
return nil, 0, fuse.EIO return nil, 0, syscall.EIO
} }
content, err := ioutil.ReadAll(rc) content, err := ioutil.ReadAll(rc)
if err != nil { if err != nil {
return nil, 0, fuse.EIO return nil, 0, syscall.EIO
} }
zf.data = content zf.data = content
...@@ -141,16 +142,16 @@ func (zf *zipFile) Open(ctx context.Context, flags uint32) (FileHandle, uint32, ...@@ -141,16 +142,16 @@ func (zf *zipFile) Open(ctx context.Context, flags uint32) (FileHandle, uint32,
// We don't return a filehandle since we don't really need // We don't return a filehandle since we don't really need
// one. The file content is immutable, so hint the kernel to // one. The file content is immutable, so hint the kernel to
// cache the data. // cache the data.
return nil, fuse.FOPEN_KEEP_CACHE, fuse.OK return nil, fuse.FOPEN_KEEP_CACHE, OK
} }
// Read simply returns the data that was already unpacked in the Open call // Read simply returns the data that was already unpacked in the Open call
func (zf *zipFile) Read(ctx context.Context, f FileHandle, dest []byte, off int64) (fuse.ReadResult, fuse.Status) { func (zf *zipFile) Read(ctx context.Context, f FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
end := int(off) + len(dest) end := int(off) + len(dest)
if end > len(zf.data) { if end > len(zf.data) {
end = len(zf.data) end = len(zf.data)
} }
return fuse.ReadResultData(zf.data[off:end]), fuse.OK return fuse.ReadResultData(zf.data[off:end]), OK
} }
// zipRoot is the root of the Zip filesystem. Its only functionality // zipRoot is the root of the Zip filesystem. Its only functionality
......
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