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
import (
"context"
"syscall"
"time"
"github.com/hanwen/go-fuse/fuse"
......@@ -72,7 +73,9 @@ func InodeOf(node Operations) *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 {
// setInode and inode are used by nodefs internally to link Inode to a Node.
//
......@@ -91,21 +94,21 @@ type Operations interface {
// StatFs implements statistics for the filesystem that holds
// this Inode. DefaultNode implements this, because OSX
// 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
// the given mode. In this case, the context has data about
// the real UID. For example a root-SUID binary called by user
// 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
// ensure that Mode and Ino are set correctly. For regular
// 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(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
// an Inode.
......@@ -119,19 +122,19 @@ type XAttrOperations interface {
// GetXAttr should read data for the given attribute into
// `dest` and return the number of bytes. If `dest` is too
// 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(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(ctx context.Context, attr string) fuse.Status
RemoveXAttr(ctx context.Context, attr string) syscall.Errno
// ListXAttr should read all attributes (null terminated) into
// `dest`. If the `dest` buffer is too small, it should return
// 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.
......@@ -139,7 +142,7 @@ type SymlinkOperations interface {
Operations
// 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
......@@ -150,58 +153,58 @@ type FileOperations interface {
// Open opens an Inode (of regular file type) for reading. It
// 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
// ReadResult, which may be constructed from the incoming
// `dest` buffer. If the file was opened without FileHandle,
// the FileHandle argument here is nil. The default
// 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
// returning, the data will be reused and may not referenced.
// 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
// to stable storage. The default implementation forwards to the
// 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
// case of duplicated descriptor, it may be called more than
// once for a file. The default implementation forwards to the
// 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
// kernel ingores the return value of this method,
// so any cleanup that requires specific synchronization or
// could fail with I/O errors should happen in Flush instead.
// 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
// 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(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(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,
// without the data having to pass through the calling process.
CopyFileRange(ctx context.Context, fhIn FileHandle,
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
// first offset beyond `off` where there is data (SEEK_DATA)
// 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.
......@@ -211,15 +214,15 @@ type LockOperations interface {
// GetLk returns locks that would conflict with the given
// input lock. If no locks conflict, the output has type
// 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
// 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)
// 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.
......@@ -229,9 +232,9 @@ type DirStream interface {
HasNext() bool
// 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
Next() (fuse.DirEntry, fuse.Status)
Next() (fuse.DirEntry, syscall.Errno)
// Close releases resources related to this directory
// stream.
......@@ -249,16 +252,16 @@ type DirOperations interface {
// the Inode for the child. A new inode can be created using
// `Inode.NewInode`. The new Inode will be added to the FS
// 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
// contents. The actual reading is driven from ReadDir, so
// this method is just for performing sanity/permission
// checks.
OpenDir(ctx context.Context) fuse.Status
OpenDir(ctx context.Context) syscall.Errno
// 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.
......@@ -266,34 +269,34 @@ type MutableDirOperations interface {
DirOperations
// 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(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(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(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
// child. It typically also returns a FileHandle as a
// 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
// return status is OK, the Inode is removed as child in the
// 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(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
// different one. The changes is effected in the FS tree if
// 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
......@@ -311,25 +314,25 @@ type MutableDirOperations interface {
// For a description of individual operations, see the equivalent
// operations in FileOperations.
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)
SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status)
SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (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) syscall.Errno
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
SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status
Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (status fuse.Status)
GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno
SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno
Allocate(ctx context.Context, off uint64, size uint64, mode uint32) syscall.Errno
}
// Options sets options for the entire filesystem
......
......@@ -15,6 +15,10 @@ import (
"golang.org/x/sys/unix"
)
func errnoToStatus(errno syscall.Errno) fuse.Status {
return fuse.Status(errno)
}
type fileEntry struct {
file FileHandle
......@@ -208,15 +212,15 @@ func (b *rawBridge) inode(id uint64, fh uint64) (*Inode, *fileEntry) {
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)
child, status := parent.dirOps().Lookup(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name, out)
if !status.Ok() {
child, errno := parent.dirOps().Lookup(&fuse.Context{Caller: header.Caller, Cancel: cancel}, name, out)
if errno != 0 {
if b.options.NegativeTimeout != nil {
out.SetEntryTimeout(*b.options.NegativeTimeout)
}
return status
return errnoToStatus(errno)
}
b.addNewChild(parent, name, child, nil, 0, out)
......@@ -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 {
parent, _ := b.inode(header.NodeId, 0)
var status fuse.Status
var errno syscall.Errno
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)
}
return status
return errnoToStatus(errno)
}
func (b *rawBridge) Unlink(cancel <-chan struct{}, header *fuse.InHeader, name string) fuse.Status {
parent, _ := b.inode(header.NodeId, 0)
var status fuse.Status
var errno syscall.Errno
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)
}
return status
return errnoToStatus(errno)
}
func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name string, out *fuse.EntryOut) fuse.Status {
parent, _ := b.inode(input.NodeId, 0)
var child *Inode
var status fuse.Status
var errno syscall.Errno
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() {
return status
if errno != 0 {
return errnoToStatus(errno)
}
if out.Attr.Mode&^07777 != fuse.S_IFDIR {
......@@ -279,13 +282,13 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
parent, _ := b.inode(input.NodeId, 0)
var child *Inode
var status fuse.Status
var errno syscall.Errno
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() {
return status
if errno != 0 {
return errnoToStatus(errno)
}
b.addNewChild(parent, name, child, nil, 0, out)
......@@ -298,18 +301,18 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
parent, _ := b.inode(input.NodeId, 0)
var child *Inode
var status fuse.Status
var errno syscall.Errno
var f FileHandle
var flags uint32
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 {
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))
......@@ -358,16 +361,16 @@ func (b *rawBridge) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out *
b.mu.Unlock()
}
status := fops.FGetAttr(ctx, f, out)
errno := fops.FGetAttr(ctx, f, out)
b.setAttrTimeout(out)
out.Ino = input.NodeId
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}
n, fEntry := b.inode(in.NodeId, in.Fh)
......@@ -377,10 +380,10 @@ func (b *rawBridge) SetAttr(cancel <-chan struct{}, in *fuse.SetAttrIn, out *fus
}
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 {
......@@ -388,28 +391,28 @@ func (b *rawBridge) Rename(cancel <-chan struct{}, input *fuse.RenameIn, oldName
p2, _ := b.inode(input.Newdir, 0)
if mops, ok := p1.ops.(MutableDirOperations); ok {
status := mops.Rename(&fuse.Context{Caller: input.Caller, Cancel: cancel}, oldName, p2.ops, newName, input.Flags)
if status.Ok() {
errno := mops.Rename(&fuse.Context{Caller: input.Caller, Cancel: cancel}, oldName, p2.ops, newName, input.Flags)
if errno == 0 {
if input.Flags&unix.RENAME_EXCHANGE != 0 {
p1.ExchangeChild(oldName, p2, newName)
} else {
p1.MvChild(oldName, p2, newName, true)
}
return status
return errnoToStatus(errno)
}
}
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)
target, _ := b.inode(input.Oldnodeid, 0)
if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status := mops.Link(&fuse.Context{Caller: input.Caller, Cancel: cancel}, target.ops, name, out)
if !status.Ok() {
return status
child, errno := mops.Link(&fuse.Context{Caller: input.Caller, Cancel: cancel}, target.ops, name, out)
if errno != 0 {
return errnoToStatus(errno)
}
b.addNewChild(parent, name, child, nil, 0, out)
......@@ -419,13 +422,13 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string
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)
if mops, ok := parent.ops.(MutableDirOperations); ok {
child, status := mops.Symlink(&fuse.Context{Caller: header.Caller, Cancel: cancel}, target, name, out)
if !status.Ok() {
return status
if status != 0 {
return errnoToStatus(status)
}
b.addNewChild(parent, name, child, nil, 0, out)
......@@ -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) {
n, _ := b.inode(header.NodeId, 0)
result, status := n.linkOps().Readlink(&fuse.Context{Caller: header.Caller, Cancel: cancel})
if !status.Ok() {
return nil, status
result, errno := n.linkOps().Readlink(&fuse.Context{Caller: header.Caller, Cancel: cancel})
if errno != 0 {
return nil, errnoToStatus(errno)
}
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)
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.
......@@ -456,7 +459,8 @@ func (b *rawBridge) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr
n, _ := b.inode(header.NodeId, 0)
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
......@@ -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) {
n, _ := b.inode(header.NodeId, 0)
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
}
......@@ -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 {
n, _ := b.inode(input.NodeId, 0)
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
}
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)
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
}
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)
// NOSUBMIT: what about the mode argument?
f, flags, status := n.fileOps().Open(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Flags)
if !status.Ok() {
return status
f, flags, errno := n.fileOps().Open(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Flags)
if errno != 0 {
return errnoToStatus(errno)
}
if f != nil {
......@@ -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) {
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)
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
}
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)
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
}
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)
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
}
......@@ -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) {
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 {
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)
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)
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 {
n, _ := b.inode(input.NodeId, 0)
status := n.dirOps().OpenDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if !status.Ok() {
return status
errno := n.dirOps().OpenDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if errno != 0 {
return errnoToStatus(errno)
}
b.mu.Lock()
defer b.mu.Unlock()
......@@ -630,29 +637,29 @@ func (b *rawBridge) OpenDir(cancel <-chan struct{}, input *fuse.OpenIn, out *fus
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 {
f.dirStream.Close()
f.dirStream = nil
}
str, status := inode.dirOps().ReadDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if !status.Ok() {
return status
str, errno := inode.dirOps().ReadDir(&fuse.Context{Caller: input.Caller, Cancel: cancel})
if errno != 0 {
return errno
}
f.hasOverflow = false
f.dirStream = str
}
return fuse.OK
return 0
}
func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fuse.DirEntryList) fuse.Status {
n, f := b.inode(input.NodeId, input.Fh)
if status := b.getStream(cancel, input, n, f); !status.Ok() {
return status
if errno := b.getStream(cancel, input, n, f); errno != 0 {
return errnoToStatus(errno)
}
if f.hasOverflow {
......@@ -662,15 +669,15 @@ func (b *rawBridge) ReadDir(cancel <-chan struct{}, input *fuse.ReadIn, out *fus
}
for f.dirStream.HasNext() {
e, status := f.dirStream.Next()
e, errno := f.dirStream.Next()
if !status.Ok() {
return status
if errno != 0 {
return errnoToStatus(errno)
}
if !out.AddDirEntry(e) {
f.overflow = e
f.hasOverflow = true
return status
return errnoToStatus(errno)
}
}
......@@ -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 {
n, f := b.inode(input.NodeId, input.Fh)
if status := b.getStream(cancel, input, n, f); !status.Ok() {
return status
if errno := b.getStream(cancel, input, n, f); errno != 0 {
return errnoToStatus(errno)
}
for f.dirStream.HasNext() {
var e fuse.DirEntry
var status fuse.Status
var errno syscall.Errno
if f.hasOverflow {
e = f.overflow
f.hasOverflow = false
} else {
e, status = f.dirStream.Next()
e, errno = f.dirStream.Next()
}
if !status.Ok() {
return status
if errno != 0 {
return errnoToStatus(errno)
}
entryOut := out.AddDirLookupEntry(e)
......@@ -705,8 +712,8 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
return fuse.OK
}
child, status := n.dirOps().Lookup(&fuse.Context{Caller: input.Caller, Cancel: cancel}, e.Name, entryOut)
if !status.Ok() {
child, errno := n.dirOps().Lookup(&fuse.Context{Caller: input.Caller, Cancel: cancel}, e.Name, entryOut)
if errno != 0 {
if b.options.NegativeTimeout != nil {
entryOut.SetEntryTimeout(*b.options.NegativeTimeout)
}
......@@ -725,14 +732,14 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
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)
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)
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) {
......@@ -743,15 +750,16 @@ func (b *rawBridge) CopyFileRange(cancel <-chan struct{}, in *fuse.CopyFileRange
n1, f1 := b.inode(in.NodeId, in.FhIn)
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)
return sz, errnoToStatus(errno)
}
func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status {
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)
out.Offset = off
return status
return errnoToStatus(errno)
}
......@@ -11,6 +11,7 @@ import (
"io/ioutil"
"os"
"sync"
"syscall"
"testing"
"github.com/hanwen/go-fuse/fuse"
......@@ -33,31 +34,31 @@ func (f *keepCacheFile) setContent(delta int) {
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
if f.keepCache {
fl = fuse.FOPEN_KEEP_CACHE
}
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()
defer f.mu.Unlock()
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.mu.Lock()
defer f.mu.Unlock()
return fuse.ReadResultData(f.content[off:]), fuse.OK
return fuse.ReadResultData(f.content[off:]), OK
}
type keepCacheRoot struct {
......@@ -112,7 +113,7 @@ func TestKeepCache(t *testing.T) {
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)
}
......
// 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
import (
"context"
"sync/atomic"
"syscall"
"unsafe"
"github.com/hanwen/go-fuse/fuse"
......@@ -62,10 +63,10 @@ func (n *DefaultOperations) Inode() *Inode {
// StatFs zeroes the out argument and returns OK. This is because OSX
// 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
*out = fuse.StatfsOut{}
return fuse.OK
return OK
}
// The default OnAdd does nothing.
......@@ -73,37 +74,37 @@ func (n *DefaultOperations) OnAdd(ctx context.Context) {
}
// 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{}
return fuse.OK
return OK
}
func (n *DefaultOperations) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
return fuse.EROFS
func (n *DefaultOperations) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
return syscall.EROFS
}
// The Access default implementation checks traditional unix
// 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)
if !ok {
return fuse.EINVAL
return syscall.EINVAL
}
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
}
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
// 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 {
return f.SetAttr(ctx, in, out)
}
......@@ -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
// 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)
if ch == nil {
return nil, fuse.ENOENT
return nil, syscall.ENOENT
}
var a fuse.AttrOut
status := ch.Operations().GetAttr(ctx, &a)
errno := ch.Operations().GetAttr(ctx, &a)
out.Attr = a.Attr
return ch, status
return ch, errno
}
// Mkdir returns EROFS
func (n *DefaultOperations) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status) {
return nil, fuse.EROFS
func (n *DefaultOperations) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) {
return nil, syscall.EROFS
}
// Mknod returns EROFS
func (n *DefaultOperations) Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (*Inode, fuse.Status) {
return nil, fuse.EROFS
func (n *DefaultOperations) Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) {
return nil, syscall.EROFS
}
// Rmdir returns EROFS
func (n *DefaultOperations) Rmdir(ctx context.Context, name string) fuse.Status {
return fuse.EROFS
func (n *DefaultOperations) Rmdir(ctx context.Context, name string) syscall.Errno {
return syscall.EROFS
}
// Unlink returns EROFS
func (n *DefaultOperations) Unlink(ctx context.Context, name string) fuse.Status {
return fuse.EROFS
func (n *DefaultOperations) Unlink(ctx context.Context, name string) syscall.Errno {
return syscall.EROFS
}
// The default OpenDir always succeeds
func (n *DefaultOperations) OpenDir(ctx context.Context) fuse.Status {
return fuse.OK
func (n *DefaultOperations) OpenDir(ctx context.Context) syscall.Errno {
return OK
}
// 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{}
for k, ch := range InodeOf(n).Children() {
r = append(r, fuse.DirEntry{Mode: ch.Mode(),
Name: k,
Ino: ch.NodeAttr().Ino})
}
return NewListDirStream(r), fuse.OK
return NewListDirStream(r), 0
}
// Rename returns EROFS
func (n *DefaultOperations) Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) fuse.Status {
return fuse.EROFS
func (n *DefaultOperations) Rename(ctx context.Context, name string, newParent Operations, newName string, flags uint32) syscall.Errno {
return syscall.EROFS
}
// 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 {
return f.Read(ctx, dest, off)
}
return nil, fuse.ENOTSUP
return nil, syscall.ENOTSUP
}
// Symlink returns EROFS
func (n *DefaultOperations) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (node *Inode, status fuse.Status) {
return nil, fuse.EROFS
func (n *DefaultOperations) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (node *Inode, errno syscall.Errno) {
return nil, syscall.EROFS
}
// Readlink return ENOTSUP
func (n *DefaultOperations) Readlink(ctx context.Context) ([]byte, fuse.Status) {
return nil, fuse.ENOTSUP
func (n *DefaultOperations) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
return nil, syscall.ENOTSUP
}
// 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 {
return f.Fsync(ctx, flags)
}
return fuse.ENOTSUP
return syscall.ENOTSUP
}
// 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 {
return f.Write(ctx, data, off)
}
return 0, fuse.EROFS
return 0, syscall.EROFS
}
func (n *DefaultOperations) CopyFileRange(ctx context.Context, fhIn FileHandle,
offIn uint64, out *Inode, fhOut FileHandle, offOut uint64,
len uint64, flags uint64) (uint32, fuse.Status) {
return 0, fuse.EROFS
len uint64, flags uint64) (uint32, syscall.Errno) {
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 {
return f.Lseek(ctx, off, whence)
}
return 0, fuse.ENOTSUP
return 0, syscall.ENOTSUP
}
// 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 {
return f.GetLk(ctx, owner, lk, flags, out)
}
return fuse.ENOTSUP
return syscall.ENOTSUP
}
// 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 {
return f.SetLk(ctx, owner, lk, flags)
}
return fuse.ENOTSUP
return syscall.ENOTSUP
}
// 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 {
return f.SetLkw(ctx, owner, lk, flags)
}
return fuse.ENOTSUP
return syscall.ENOTSUP
}
// 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 {
return f.Flush(ctx)
}
return fuse.ENOTSUP
return syscall.ENOTSUP
}
// 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 {
return f.Release(ctx)
}
return fuse.OK
return OK
}
// 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 {
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
// 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 {
f.GetAttr(ctx, out)
}
......@@ -277,38 +278,38 @@ func (n *DefaultOperations) FGetAttr(ctx context.Context, f FileHandle, out *fus
}
// Open returns ENOTSUP
func (n *DefaultOperations) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) {
return nil, 0, fuse.ENOTSUP
func (n *DefaultOperations) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
return nil, 0, syscall.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) {
return nil, nil, 0, fuse.EROFS
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, syscall.EROFS
}
// Link returns ENOTSUP
func (n *DefaultOperations) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (node *Inode, status fuse.Status) {
return nil, fuse.EROFS
func (n *DefaultOperations) Link(ctx context.Context, target Operations, name string, out *fuse.EntryOut) (node *Inode, errno syscall.Errno) {
return nil, syscall.EROFS
}
// The default GetXAttr returns ENOATTR
func (n *DefaultOperations) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, fuse.Status) {
return 0, fuse.ENOATTR
func (n *DefaultOperations) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
return 0, ENOATTR
}
// The default SetXAttr returns ENOATTR
func (n *DefaultOperations) SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) fuse.Status {
return fuse.EROFS
func (n *DefaultOperations) SetXAttr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
return syscall.EROFS
}
// The default RemoveXAttr returns ENOATTR
func (n *DefaultOperations) RemoveXAttr(ctx context.Context, attr string) fuse.Status {
return fuse.ENOATTR
func (n *DefaultOperations) RemoveXAttr(ctx context.Context, attr string) syscall.Errno {
return ENOATTR
}
// The default RemoveXAttr returns an empty list
func (n *DefaultOperations) ListXAttr(ctx context.Context, dest []byte) (uint32, fuse.Status) {
return 0, fuse.OK
func (n *DefaultOperations) ListXAttr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
return 0, OK
}
// DefaultFileHandle satisfies the FileHandle interface, and provides
......@@ -318,50 +319,50 @@ type DefaultFileHandle struct {
var _ = FileHandle((*DefaultFileHandle)(nil))
func (f *DefaultFileHandle) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, fuse.Status) {
return nil, fuse.ENOTSUP
func (f *DefaultFileHandle) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
return nil, syscall.ENOTSUP
}
func (f *DefaultFileHandle) Write(ctx context.Context, data []byte, off int64) (written uint32, status fuse.Status) {
return 0, fuse.ENOTSUP
func (f *DefaultFileHandle) Write(ctx context.Context, data []byte, off int64) (written uint32, errno syscall.Errno) {
return 0, syscall.ENOTSUP
}
func (f *DefaultFileHandle) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) {
return fuse.ENOTSUP
func (f *DefaultFileHandle) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (errno syscall.Errno) {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) {
return fuse.ENOTSUP
func (f *DefaultFileHandle) SetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) {
return fuse.ENOTSUP
func (f *DefaultFileHandle) SetLkw(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32) (errno syscall.Errno) {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) Flush(ctx context.Context) fuse.Status {
return fuse.ENOTSUP
func (f *DefaultFileHandle) Flush(ctx context.Context) syscall.Errno {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) Release(ctx context.Context) fuse.Status {
return fuse.ENOTSUP
func (f *DefaultFileHandle) Release(ctx context.Context) syscall.Errno {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) GetAttr(ctx context.Context, out *fuse.AttrOut) fuse.Status {
return fuse.ENOTSUP
func (f *DefaultFileHandle) GetAttr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status {
return fuse.ENOTSUP
func (f *DefaultFileHandle) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (status fuse.Status) {
return fuse.ENOTSUP
func (f *DefaultFileHandle) Allocate(ctx context.Context, off uint64, size uint64, mode uint32) (errno syscall.Errno) {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) Fsync(ctx context.Context, flags uint32) (status fuse.Status) {
return fuse.ENOTSUP
func (f *DefaultFileHandle) Fsync(ctx context.Context, flags uint32) (errno syscall.Errno) {
return syscall.ENOTSUP
}
func (f *DefaultFileHandle) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, fuse.Status) {
return 0, fuse.ENOTSUP
func (f *DefaultFileHandle) Lseek(ctx context.Context, off uint64, whence uint32) (uint64, syscall.Errno) {
return 0, syscall.ENOTSUP
}
......@@ -30,14 +30,14 @@ type dioFH struct {
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))
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)
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
......@@ -45,8 +45,8 @@ type dioFile struct {
DefaultOperations
}
func (f *dioFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) {
return &dioFH{}, fuse.FOPEN_DIRECT_IO, fuse.OK
func (f *dioFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
return &dioFH{}, fuse.FOPEN_DIRECT_IO, OK
}
func TestDirectIO(t *testing.T) {
......
......@@ -5,6 +5,8 @@
package nodefs
import (
"syscall"
"github.com/hanwen/go-fuse/fuse"
)
......@@ -16,10 +18,10 @@ func (a *dirArray) HasNext() bool {
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]
a.entries = a.entries[1:]
return e, fuse.OK
return e, 0
}
func (a *dirArray) Close() {
......
......@@ -7,14 +7,15 @@ package nodefs
import (
"io"
"os"
"syscall"
"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)
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
defer f.Close()
......@@ -39,9 +40,9 @@ func NewLoopbackDirStream(nm string) (DirStream, fuse.Status) {
}
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 {
}
// 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)
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
ds := &loopbackDirStream{
......@@ -29,11 +29,11 @@ func NewLoopbackDirStream(name string) (DirStream, fuse.Status) {
fd: fd,
}
if err := ds.load(); !err.Ok() {
if err := ds.load(); err != 0 {
ds.Close()
return nil, err
}
return ds, fuse.OK
return ds, OK
}
func (ds *loopbackDirStream) Close() {
......@@ -44,7 +44,7 @@ func (ds *loopbackDirStream) HasNext() bool {
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]))
nameBytes := ds.todo[unsafe.Offsetof(syscall.Dirent{}.Name):de.Reclen]
......@@ -64,15 +64,15 @@ func (ds *loopbackDirStream) Next() (fuse.DirEntry, fuse.Status) {
return result, ds.load()
}
func (ds *loopbackDirStream) load() fuse.Status {
func (ds *loopbackDirStream) load() syscall.Errno {
if len(ds.todo) > 0 {
return fuse.OK
return OK
}
n, err := syscall.Getdents(ds.fd, ds.buf)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
ds.todo = ds.buf[:n]
return fuse.OK
return OK
}
......@@ -24,36 +24,36 @@ type loopbackFile struct {
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))
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)
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)
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
// want to really close the file, we just want to flush. This
// is achieved by closing a dup'd fd.
newFd, err := syscall.Dup(f.fd)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
err = syscall.Close(newFd)
return fuse.ToStatus(err)
return ToErrno(err)
}
func (f *loopbackFile) Fsync(ctx context.Context, flags uint32) (status fuse.Status) {
r := fuse.ToStatus(syscall.Fsync(f.fd))
func (f *loopbackFile) Fsync(ctx context.Context, flags uint32) (errno syscall.Errno) {
r := ToErrno(syscall.Fsync(f.fd))
return r
}
......@@ -64,23 +64,23 @@ const (
_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{}
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)
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)
}
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)
}
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 {
var op int
switch lk.Typ {
......@@ -91,12 +91,12 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
case syscall.F_UNLCK:
op = syscall.LOCK_UN
default:
return fuse.EINVAL
return syscall.EINVAL
}
if !blocking {
op |= syscall.LOCK_NB
}
return fuse.ToStatus(syscall.Flock(f.fd, op))
return ToErrno(syscall.Flock(f.fd, op))
} else {
flk := syscall.Flock_t{}
lk.ToFlockT(&flk)
......@@ -106,24 +106,24 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
} else {
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 {
if status := f.setAttr(ctx, in); !status.Ok() {
return status
func (f *loopbackFile) SetAttr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
if errno := f.setAttr(ctx, in); errno != 0 {
return errno
}
return f.GetAttr(ctx, out)
}
func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Status {
var status fuse.Status
func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) syscall.Errno {
var errno syscall.Errno
if mode, ok := in.GetMode(); ok {
status = fuse.ToStatus(syscall.Fchmod(f.fd, mode))
if !status.Ok() {
return status
errno = ToErrno(syscall.Fchmod(f.fd, mode))
if errno != 0 {
return errno
}
}
......@@ -139,9 +139,9 @@ func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Sta
if gOk {
gid = int(gid32)
}
status = fuse.ToStatus(syscall.Fchown(f.fd, uid, gid))
if !status.Ok() {
return status
errno = ToErrno(syscall.Fchown(f.fd, uid, gid))
if errno != 0 {
return errno
}
}
......@@ -157,33 +157,33 @@ func (f *loopbackFile) setAttr(ctx context.Context, in *fuse.SetAttrIn) fuse.Sta
if !mok {
mp = nil
}
status = f.utimens(ap, mp)
if !status.Ok() {
return status
errno = f.utimens(ap, mp)
if errno != 0 {
return errno
}
}
if sz, ok := in.GetSize(); ok {
status = fuse.ToStatus(syscall.Ftruncate(f.fd, int64(sz)))
if !status.Ok() {
return status
errno = ToErrno(syscall.Ftruncate(f.fd, int64(sz)))
if errno != 0 {
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{}
err := syscall.Fstat(f.fd, &st)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
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))
return uint64(n), fuse.ToStatus(err)
return uint64(n), ToErrno(err)
}
......@@ -6,15 +6,14 @@ package nodefs
import (
"context"
"syscall"
"time"
"github.com/hanwen/go-fuse/fuse"
)
func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) fuse.Status {
return fuse.ENOSYS
func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) syscall.Errno {
return syscall.ENOSYS
}
func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time) fuse.Status {
return fuse.ENOSYS
func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time) syscall.Errno {
return syscall.ENOSYS
}
......@@ -12,19 +12,19 @@ import (
"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))
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
return fuse.OK
return OK
}
// 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
ts[0] = fuse.UtimeToTimespec(a)
ts[1] = fuse.UtimeToTimespec(m)
err := futimens(int(f.fd), &ts)
return fuse.ToStatus(err)
return ToErrno(err)
}
......@@ -11,6 +11,7 @@ import (
"sort"
"strings"
"sync"
"syscall"
"unsafe"
"github.com/hanwen/go-fuse/fuse"
......@@ -631,33 +632,34 @@ retry:
// NotifyEntry notifies the kernel that data for a (directory, name)
// tuple should be invalidated. On next access, a LOOKUP operation
// will be started.
func (n *Inode) NotifyEntry(name string) fuse.Status {
return n.bridge.server.EntryNotify(n.nodeAttr.Ino, name)
func (n *Inode) NotifyEntry(name string) syscall.Errno {
status := n.bridge.server.EntryNotify(n.nodeAttr.Ino, name)
return syscall.Errno(status)
}
// NotifyDelete notifies the kernel that the given inode was removed
// from this directory as entry under the given name. It is equivalent
// 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?
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
// 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?
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.
func (n *Inode) WriteCache(offset int64, data []byte) fuse.Status {
return n.bridge.server.InodeNotifyStoreCache(n.nodeAttr.Ino, offset, data)
func (n *Inode) WriteCache(offset int64, data []byte) syscall.Errno {
return syscall.Errno(n.bridge.server.InodeNotifyStoreCache(n.nodeAttr.Ino, offset, data))
}
// ReadCache reads data from the kernel cache.
func (n *Inode) ReadCache(offset int64, dest []byte) (count int, status fuse.Status) {
return n.bridge.server.InodeRetrieveCache(n.nodeAttr.Ino, offset, dest)
func (n *Inode) ReadCache(offset int64, dest []byte) (count int, errno syscall.Errno) {
c, s := n.bridge.server.InodeRetrieveCache(n.nodeAttr.Ino, offset, dest)
return c, syscall.Errno(s)
}
......@@ -8,6 +8,7 @@ import (
"context"
"os"
"os/exec"
"syscall"
"testing"
"time"
......@@ -25,24 +26,24 @@ type interruptOps struct {
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" {
return nil, fuse.ENOENT
return nil, syscall.ENOENT
}
ch := InodeOf(r).NewInode(ctx, &r.child, NodeAttr{
Ino: 2,
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 {
case <-time.After(100 * time.Millisecond):
return nil, 0, fuse.EIO
return nil, 0, syscall.EIO
case <-ctx.Done():
o.interrupted = true
return nil, 0, fuse.EINTR
return nil, 0, syscall.EINTR
}
}
......
......@@ -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{}
err := syscall.Statfs(n.path(), &s)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
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
st := syscall.Stat_t{}
err = syscall.Stat(n.root, &st)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
out.FromStat(&st)
return fuse.OK
return OK
}
type loopbackNode struct {
......@@ -59,31 +59,31 @@ func (n *loopbackNode) path() string {
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)
st := syscall.Stat_t{}
err := syscall.Lstat(p, &st)
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
out.Attr.FromStat(&st)
node := n.rootNode.newLoopbackNode()
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)
err := syscall.Mknod(p, mode, int(rdev))
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
st := syscall.Stat_t{}
if err := syscall.Lstat(p, &st); err != nil {
syscall.Rmdir(p)
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
out.Attr.FromStat(&st)
......@@ -91,19 +91,19 @@ func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32
node := n.rootNode.newLoopbackNode()
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)
err := os.Mkdir(p, os.FileMode(mode))
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
st := syscall.Stat_t{}
if err := syscall.Lstat(p, &st); err != nil {
syscall.Rmdir(p)
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
out.Attr.FromStat(&st)
......@@ -111,19 +111,19 @@ func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out
node := n.rootNode.newLoopbackNode()
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)
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)
err := syscall.Unlink(p)
return fuse.ToStatus(err)
return ToErrno(err)
}
func toLoopbackNode(op Operations) *loopbackNode {
......@@ -133,7 +133,7 @@ func toLoopbackNode(op Operations) *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)
if flags&unix.RENAME_EXCHANGE != 0 {
return n.renameExchange(name, newParentLoopback, newName)
......@@ -143,7 +143,7 @@ func (n *loopbackNode) Rename(ctx context.Context, name string, newParent Operat
p2 := filepath.Join(newParentLoopback.path(), newName)
err := os.Rename(p1, p2)
return fuse.ToStatus(err)
return ToErrno(err)
}
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)
fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode)
if err != nil {
return nil, nil, 0, fuse.ToStatus(err)
return nil, nil, 0, ToErrno(err)
}
st := syscall.Stat_t{}
if err := syscall.Fstat(fd, &st); err != nil {
syscall.Close(fd)
return nil, nil, 0, fuse.ToStatus(err)
return nil, nil, 0, ToErrno(err)
}
node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&st))
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)
err := syscall.Symlink(target, p)
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
st := syscall.Stat_t{}
if syscall.Lstat(p, &st); err != nil {
syscall.Unlink(p)
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&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)
targetNode := toLoopbackNode(target)
err := syscall.Link(targetNode.path(), p)
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
st := syscall.Stat_t{}
if syscall.Lstat(p, &st); err != nil {
syscall.Unlink(p)
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(ctx, node, n.rootNode.idFromStat(&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()
for l := 256; ; l *= 2 {
buf := make([]byte, l)
sz, err := syscall.Readlink(p, buf)
if err != nil {
return nil, fuse.ToStatus(err)
return nil, ToErrno(err)
}
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()
f, err := syscall.Open(p, int(flags), 0)
if err != nil {
return nil, 0, fuse.ToStatus(err)
return nil, 0, ToErrno(err)
}
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)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
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())
}
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 {
return f.GetAttr(ctx, out)
}
......@@ -273,28 +273,28 @@ func (n *loopbackNode) FGetAttr(ctx context.Context, f FileHandle, out *fuse.Att
st := syscall.Stat_t{}
err = syscall.Lstat(p, &st)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
out.FromStat(&st)
return fuse.OK
return OK
}
func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle,
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)
if !ok {
return 0, fuse.ENOTSUP
return 0, syscall.ENOTSUP
}
lfOut, ok := fhOut.(*loopbackFile)
if !ok {
return 0, fuse.ENOTSUP
return 0, syscall.ENOTSUP
}
signedOffIn := int64(offIn)
signedOffOut := int64(offOut)
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
......
......@@ -8,55 +8,54 @@ import (
"context"
"syscall"
"github.com/hanwen/go-fuse/fuse"
"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)
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))
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)
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)
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)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
defer syscall.Close(fd1)
fd2, err := syscall.Open(newparent.path(), syscall.O_DIRECTORY, 0)
defer syscall.Close(fd2)
if err != nil {
return fuse.ToStatus(err)
return ToErrno(err)
}
var st syscall.Stat_t
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 {
return fuse.EBUSY
return syscall.EBUSY
}
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 {
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) {
t.Fatalf("got after %#v, want %#v", after, st)
}
if code := tc.loopback.Inode().NotifyEntry("file"); !code.Ok() {
t.Errorf("notify failed: %v", code)
if errno := tc.loopback.Inode().NotifyEntry("file"); errno != 0 {
t.Errorf("notify failed: %v", errno)
}
if err := syscall.Lstat(fn, &after); err != syscall.ENOENT {
......
......@@ -14,6 +14,7 @@ import (
"reflect"
"strings"
"sync"
"syscall"
"testing"
"github.com/hanwen/go-fuse/fuse"
......@@ -116,23 +117,23 @@ var _ = (FileOperations)((*zipFile)(nil))
// GetAttr sets the minimum, which is the size. A more full-featured
// 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
return fuse.OK
return OK
}
// 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()
defer zf.mu.Unlock()
if zf.data == nil {
rc, err := zf.file.Open()
if err != nil {
return nil, 0, fuse.EIO
return nil, 0, syscall.EIO
}
content, err := ioutil.ReadAll(rc)
if err != nil {
return nil, 0, fuse.EIO
return nil, 0, syscall.EIO
}
zf.data = content
......@@ -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
// one. The file content is immutable, so hint the kernel to
// 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
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)
if 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
......
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