Implement Handle
This commit is contained in:
136
handle.go
136
handle.go
@@ -2,7 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"syscall"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
@@ -13,12 +17,13 @@ var _ fs.HandleFlusher = (*Handle)(nil)
|
||||
var _ fs.HandleLocker = (*Handle)(nil)
|
||||
var _ fs.HandlePOSIXLocker = (*Handle)(nil)
|
||||
var _ fs.HandlePoller = (*Handle)(nil)
|
||||
var _ fs.HandleReadAller = (*Handle)(nil)
|
||||
var _ fs.HandleReadDirAller = (*Handle)(nil)
|
||||
var _ fs.HandleReader = (*Handle)(nil)
|
||||
var _ fs.HandleReleaser = (*Handle)(nil)
|
||||
var _ fs.HandleWriter = (*Handle)(nil)
|
||||
|
||||
// var _ fs.HandleReadAller = (*Handle)(nil)
|
||||
|
||||
type Handle struct {
|
||||
f *os.File
|
||||
}
|
||||
@@ -26,16 +31,28 @@ type Handle struct {
|
||||
// Flush is called each time the file or directory is closed.
|
||||
// Because there can be multiple file descriptors referring to a
|
||||
// single opened file, Flush can be called multiple times.
|
||||
func (h *Handle) Flush(ctx context.Context, req *fuse.FlushRequest) error {
|
||||
panic("TODO")
|
||||
func (h *Handle) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) {
|
||||
defer func() { log.Printf("[flush] handle=%q -- err=%v", h.f.Name(), err) }()
|
||||
return h.f.Sync()
|
||||
}
|
||||
|
||||
func (h *Handle) ReadAll(ctx context.Context) ([]byte, error) {
|
||||
panic("TODO")
|
||||
func (h *Handle) ReadDirAll(ctx context.Context) (ents []fuse.Dirent, err error) {
|
||||
defer func() { log.Printf("[readdirall] handle=%q -- ents=%d err=%v", h.f.Name(), len(ents), err) }()
|
||||
|
||||
fis, err := h.f.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (h *Handle) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
panic("TODO")
|
||||
// Convert FileInfo objects to FUSE directory entries.
|
||||
ents = make([]fuse.Dirent, len(fis))
|
||||
for i, fi := range fis {
|
||||
statt := fi.Sys().(*syscall.Stat_t)
|
||||
ents[i] = fuse.Dirent{Inode: statt.Ino, Name: fi.Name()}
|
||||
}
|
||||
|
||||
sort.Slice(ents, func(i, j int) bool { return ents[i].Name < ents[j].Name })
|
||||
return ents, nil
|
||||
}
|
||||
|
||||
// Read requests to read data from the handle.
|
||||
@@ -47,8 +64,32 @@ func (h *Handle) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
//
|
||||
// Note that reads beyond the size of the file as reported by Attr
|
||||
// are not even attempted (except in OpenDirectIO mode).
|
||||
func (h *Handle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
||||
panic("TODO")
|
||||
func (h *Handle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) (err error) {
|
||||
defer func() {
|
||||
log.Printf("[read] handle=%q offset=%d size=%d flags=%#o lockowner=%d fileflags=%#o -- data=%d err=%v",
|
||||
h.f.Name(),
|
||||
req.Offset,
|
||||
req.Size,
|
||||
req.Flags,
|
||||
req.LockOwner,
|
||||
req.FileFlags,
|
||||
len(resp.Data),
|
||||
err,
|
||||
)
|
||||
}()
|
||||
|
||||
// TODO: Flags ReadFlags
|
||||
// TODO: LockOwner
|
||||
// TODO: FileFlags OpenFlags
|
||||
|
||||
buf := make([]byte, req.Size)
|
||||
n, err := h.f.ReadAt(buf, req.Offset)
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
resp.Data = buf[:n]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write requests to write data into the handle at the given offset.
|
||||
@@ -62,12 +103,34 @@ func (h *Handle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.Rea
|
||||
// Writes that grow the file are expected to update the file size
|
||||
// (as seen through Attr). Note that file size changes are
|
||||
// communicated also through Setattr.
|
||||
func (h *Handle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
|
||||
panic("TODO")
|
||||
func (h *Handle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) (err error) {
|
||||
defer func() {
|
||||
log.Printf(
|
||||
"[write] handle=%q offset=%d size=%d flags=%#o lockowner=%d fileflags=%#o -- data=%d err=%v",
|
||||
h.f.Name(),
|
||||
req.Offset,
|
||||
len(req.Data),
|
||||
req.Flags,
|
||||
req.LockOwner,
|
||||
req.FileFlags,
|
||||
resp.Size,
|
||||
err,
|
||||
)
|
||||
}()
|
||||
|
||||
// Offset int64
|
||||
// Data []byte
|
||||
// Flags WriteFlags
|
||||
// LockOwner LockOwner
|
||||
// FileFlags OpenFlags
|
||||
|
||||
resp.Size, err = h.f.WriteAt(req.Data, req.Offset)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
|
||||
panic("TODO")
|
||||
func (h *Handle) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) {
|
||||
defer func() { log.Printf("[release] handle=%q -- err=%v", h.f.Name(), err) }()
|
||||
return h.f.Close()
|
||||
}
|
||||
|
||||
// Poll checks whether the handle is currently ready for I/O, and
|
||||
@@ -87,6 +150,20 @@ func (h *Handle) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
|
||||
// The Go runtime uses epoll-based I/O whenever possible, even for
|
||||
// regular files.
|
||||
func (h *Handle) Poll(ctx context.Context, req *fuse.PollRequest, resp *fuse.PollResponse) error {
|
||||
log.Printf("[poll] handle=%q flags=%#o events=%#o", h.f.Name(), req.Flags, req.Events)
|
||||
|
||||
//type PollRequest struct {
|
||||
// Header `json:"-"`
|
||||
// Handle HandleID
|
||||
//
|
||||
// Flags PollFlags
|
||||
// Events PollEvents
|
||||
//}
|
||||
|
||||
//type PollResponse struct {
|
||||
// REvents PollEvents
|
||||
//}
|
||||
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
@@ -98,12 +175,27 @@ func (h *Handle) Poll(ctx context.Context, req *fuse.PollRequest, resp *fuse.Pol
|
||||
// (UnlockRequest, ReleaseRequest, FlushRequest) and also
|
||||
// in e.g. ReadRequest, WriteRequest.
|
||||
func (h *Handle) Lock(ctx context.Context, req *fuse.LockRequest) error {
|
||||
log.Printf("[lock] handle=%q lockowner=%d lock=%#o lockflags=%#o", h.f.Name(), req.LockOwner, req.Lock, req.LockFlags)
|
||||
|
||||
// type LockRequest struct {
|
||||
// Header
|
||||
// Handle HandleID
|
||||
// // LockOwner is a unique identifier for the originating client, to identify locks.
|
||||
// LockOwner LockOwner
|
||||
// Lock FileLock
|
||||
// LockFlags LockFlags
|
||||
// }
|
||||
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
// LockWait acquires a lock on a byte range of the node, waiting
|
||||
// until the lock can be obtained (or context is canceled).
|
||||
func (h *Handle) LockWait(ctx context.Context, req *fuse.LockWaitRequest) error {
|
||||
log.Printf("[lockwait] handle=%q lockowner=%d lock=%#o lockflags=%#o", h.f.Name(), req.LockOwner, req.Lock, req.LockFlags)
|
||||
|
||||
// type LockWaitRequest LockRequest
|
||||
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
@@ -111,6 +203,10 @@ func (h *Handle) LockWait(ctx context.Context, req *fuse.LockWaitRequest) error
|
||||
// be released also implicitly, see HandleFlockLocker and
|
||||
// HandlePOSIXLocker.
|
||||
func (h *Handle) Unlock(ctx context.Context, req *fuse.UnlockRequest) error {
|
||||
log.Printf("[unlock] handle=%q lockowner=%d lock=%#o lockflags=%#o", h.f.Name(), req.LockOwner, req.Lock, req.LockFlags)
|
||||
|
||||
// type UnlockRequest LockRequest
|
||||
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
@@ -123,5 +219,19 @@ func (h *Handle) Unlock(ctx context.Context, req *fuse.UnlockRequest) error {
|
||||
// have Lock.Type F_UNLCK, and the whole struct should be
|
||||
// overwritten for in case of conflicting locks.
|
||||
func (h *Handle) QueryLock(ctx context.Context, req *fuse.QueryLockRequest, resp *fuse.QueryLockResponse) error {
|
||||
log.Printf("[querylock] handle=%q lockowner=%d lock=%#o lockflags=%#o", h.f.Name(), req.LockOwner, req.Lock, req.LockFlags)
|
||||
|
||||
// type QueryLockRequest struct {
|
||||
// Header
|
||||
// Handle HandleID
|
||||
// LockOwner LockOwner
|
||||
// Lock FileLock
|
||||
// LockFlags LockFlags
|
||||
// }
|
||||
|
||||
// type QueryLockResponse struct {
|
||||
// Lock FileLock
|
||||
// }
|
||||
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
106
node.go
106
node.go
@@ -49,8 +49,8 @@ func (n *Node) srcpath() string {
|
||||
return filepath.Join(n.fs.SourcePath, n.path)
|
||||
}
|
||||
|
||||
func (n *Node) Attr(ctx context.Context, a *fuse.Attr) error {
|
||||
log.Printf("[attr] node=%q", n.path)
|
||||
func (n *Node) Attr(ctx context.Context, a *fuse.Attr) (err error) {
|
||||
defer func() { log.Printf("[attr] node=%q -- attr=%s err=%v", n.path, a.String(), err) }()
|
||||
|
||||
fi, err := os.Stat(n.srcpath())
|
||||
if err != nil {
|
||||
@@ -86,8 +86,8 @@ func (n *Node) Attr(ctx context.Context, a *fuse.Attr) error {
|
||||
// the directory, Lookup should return ENOENT.
|
||||
//
|
||||
// Lookup need not to handle the names "." and "..".
|
||||
func (n *Node) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
||||
log.Printf("[lookup] node=%q name=%q", n.path, name)
|
||||
func (n *Node) Lookup(ctx context.Context, name string) (_ fs.Node, err error) {
|
||||
defer func() { log.Printf("[lookup] node=%q name=%q -- err=%v", n.path, name, err) }()
|
||||
|
||||
path := filepath.Join(n.path, name)
|
||||
srcpath := filepath.Join(n.fs.SourcePath, path)
|
||||
@@ -97,15 +97,15 @@ func (n *Node) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
||||
return NewNode(n.fs, path), nil
|
||||
}
|
||||
|
||||
func (n *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
log.Printf("[readdirall] node=%q", n.path)
|
||||
func (n *Node) ReadDirAll(ctx context.Context) (ents []fuse.Dirent, err error) {
|
||||
defer func() { log.Printf("[readdirall] node=%q -- ents=%d err=%v", n.path, len(ents), err) }()
|
||||
|
||||
fis, err := ioutil.ReadDir(n.srcpath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ents := make([]fuse.Dirent, len(fis))
|
||||
ents = make([]fuse.Dirent, len(fis))
|
||||
for i, fi := range fis {
|
||||
statt := fi.Sys().(*syscall.Stat_t)
|
||||
ents[i] = fuse.Dirent{Inode: statt.Ino, Name: fi.Name()}
|
||||
@@ -130,8 +130,8 @@ func (n *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
// req.Valid is a bitmask of what fields are actually being set.
|
||||
// For example, the method should not change the mode of the file
|
||||
// unless req.Valid.Mode() is true.
|
||||
func (n *Node) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
|
||||
log.Printf("[setattr] node=%q req=%s", n.path, req.String())
|
||||
func (n *Node) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) (err error) {
|
||||
defer func() { log.Printf("[setattr] node=%q req=%s -- err=%v", n.path, req.String(), err) }()
|
||||
|
||||
// Obtain current file stat.
|
||||
srcpath := n.srcpath()
|
||||
@@ -200,10 +200,10 @@ func (n *Node) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse
|
||||
|
||||
// TODO: Not sure what these are for.
|
||||
if req.Valid.Handle() {
|
||||
panic("TODO?")
|
||||
println("TODO: setattr.handle")
|
||||
}
|
||||
if req.Valid.LockOwner() {
|
||||
panic("TODO?")
|
||||
println("TODO: setattr.lockowner")
|
||||
}
|
||||
|
||||
// Update response attributes.
|
||||
@@ -211,8 +211,10 @@ func (n *Node) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse
|
||||
}
|
||||
|
||||
// Symlink creates a new symbolic link in the receiver, which must be a directory.
|
||||
func (n *Node) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (fs.Node, error) {
|
||||
log.Printf("[symlink] node=%q newname=%q target=%q", n.path, req.NewName, req.Target)
|
||||
func (n *Node) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (_ fs.Node, err error) {
|
||||
defer func() {
|
||||
log.Printf("[symlink] node=%q newname=%q target=%q -- err=%v", n.path, req.NewName, req.Target, err)
|
||||
}()
|
||||
if err := os.Symlink(req.Target, req.NewName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -220,17 +222,19 @@ func (n *Node) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (fs.Node,
|
||||
}
|
||||
|
||||
// Readlink reads a symbolic link.
|
||||
func (n *Node) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, error) {
|
||||
log.Printf("[readlink] node=%q", n.path)
|
||||
func (n *Node) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (_ string, err error) {
|
||||
defer func() { log.Printf("[readlink] node=%q -- err=%v", n.path, err) }()
|
||||
return os.Readlink(n.srcpath())
|
||||
}
|
||||
|
||||
// Link creates a new directory entry in the receiver based on an
|
||||
// existing Node. Receiver must be a directory.
|
||||
func (n *Node) Link(ctx context.Context, req *fuse.LinkRequest, _old fs.Node) (fs.Node, error) {
|
||||
func (n *Node) Link(ctx context.Context, req *fuse.LinkRequest, _old fs.Node) (_ fs.Node, err error) {
|
||||
old := _old.(*Node)
|
||||
|
||||
log.Printf("[link] node=%q oldnode=%q name=%q", n.path, old.srcpath(), req.NewName)
|
||||
defer func() {
|
||||
log.Printf("[link] node=%q oldnode=%q name=%q -- err=%v", n.path, old.srcpath(), req.NewName, err)
|
||||
}()
|
||||
// assert(n.IsDir())
|
||||
|
||||
if err := os.Link(old.srcpath(), req.NewName); err != nil {
|
||||
@@ -242,8 +246,8 @@ func (n *Node) Link(ctx context.Context, req *fuse.LinkRequest, _old fs.Node) (f
|
||||
// Remove removes the entry with the given name from
|
||||
// the receiver, which must be a directory. The entry to be removed
|
||||
// may correspond to a file (unlink) or to a directory (rmdir).
|
||||
func (n *Node) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
|
||||
log.Printf("[remove] node=%q name=%q dir=%v", n.path, req.Name, req.Dir)
|
||||
func (n *Node) Remove(ctx context.Context, req *fuse.RemoveRequest) (err error) {
|
||||
defer func() { log.Printf("[remove] node=%q name=%q dir=%v -- err=%v", n.path, req.Name, req.Dir, err) }()
|
||||
|
||||
if req.Dir {
|
||||
return syscall.Rmdir(filepath.Join(n.srcpath(), req.Name))
|
||||
@@ -259,8 +263,8 @@ func (n *Node) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
|
||||
// call but not the open(2) system call. If Access is not
|
||||
// implemented, the Node behaves as if it always returns nil
|
||||
// (permission granted), relying on checks in Open instead.
|
||||
func (n *Node) Access(ctx context.Context, req *fuse.AccessRequest) error {
|
||||
log.Printf("[access] node=%q mask=%#o", n.path, req.Mask)
|
||||
func (n *Node) Access(ctx context.Context, req *fuse.AccessRequest) (err error) {
|
||||
defer func() { log.Printf("[access] node=%q mask=%#o -- err=%v", n.path, req.Mask, err) }()
|
||||
|
||||
return syscall.Access(n.srcpath(), req.Mask)
|
||||
}
|
||||
@@ -271,9 +275,9 @@ func (n *Node) Access(ctx context.Context, req *fuse.AccessRequest) error {
|
||||
// Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (Node, error)
|
||||
//}
|
||||
|
||||
func (n *Node) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
|
||||
log.Printf("[mkdir] node=%q mode=%#o umask=%#o", n.path, req.Mode, req.Umask)
|
||||
if err := syscall.Mkdir(filepath.Join(n.srcpath(), req.Name), uint32(req.Mode&req.Umask)); err != nil {
|
||||
func (n *Node) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (_ fs.Node, err error) {
|
||||
defer func() { log.Printf("[mkdir] node=%q mode=%#o umask=%#o -- err=%v", n.path, req.Mode, req.Umask, err) }()
|
||||
if err := syscall.Mkdir(filepath.Join(n.srcpath(), req.Name), uint32(req.Mode^req.Umask)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewNode(n.fs, filepath.Join(n.path, req.Name)), nil
|
||||
@@ -289,8 +293,8 @@ func (n *Node) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, erro
|
||||
// succeed, and the Node itself will be used as the Handle.
|
||||
//
|
||||
// XXX note about access. XXX OpenFlags.
|
||||
func (n *Node) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
||||
log.Printf("[open] node=%q dir=%v flags=%#o", n.path, req.Dir, req.Flags)
|
||||
func (n *Node) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (_ fs.Handle, err error) {
|
||||
defer func() { log.Printf("[open] node=%q dir=%v flags=%#o -- err=%v", n.path, req.Dir, req.Flags, err) }()
|
||||
|
||||
// TODO(bbj): Where does mode come from?
|
||||
f, err := os.OpenFile(n.srcpath(), int(req.Flags), 0777)
|
||||
@@ -301,10 +305,12 @@ func (n *Node) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenR
|
||||
}
|
||||
|
||||
// Create creates a new directory entry in the receiver, which must be a directory.
|
||||
func (n *Node) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
|
||||
log.Printf("[create] node=%q name=%q flags=%#o mode=%#o umask=%#o", n.path, req.Name, req.Flags, req.Mode, req.Umask)
|
||||
func (n *Node) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (_ fs.Node, _ fs.Handle, err error) {
|
||||
defer func() {
|
||||
log.Printf("[create] node=%q name=%q flags=%#o mode=%#o umask=%#o -- err=%v", n.path, req.Name, req.Flags, req.Mode, req.Umask, err)
|
||||
}()
|
||||
|
||||
f, err := os.OpenFile(filepath.Join(n.srcpath(), req.Name), int(req.Flags), req.Mode&req.Umask)
|
||||
f, err := os.OpenFile(filepath.Join(n.srcpath(), req.Name), int(req.Flags), req.Mode^req.Umask)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -318,22 +324,26 @@ func (n *Node) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.C
|
||||
// implicitly forgotten as part of the unmount.
|
||||
// func (n *Node) Forget() { panic("TODO") }
|
||||
|
||||
func (n *Node) Rename(ctx context.Context, req *fuse.RenameRequest, _newDir fs.Node) error {
|
||||
func (n *Node) Rename(ctx context.Context, req *fuse.RenameRequest, _newDir fs.Node) (err error) {
|
||||
newDir := _newDir.(*Node)
|
||||
log.Printf("[rename] node=%q oldname=%q newnode=%q newname=%q", n.path, req.NewName, newDir.path, req.OldName)
|
||||
func() {
|
||||
log.Printf("[rename] node=%q oldname=%q newnode=%q newname=%q -- err=%v", n.path, req.NewName, newDir.path, req.OldName, err)
|
||||
}()
|
||||
return os.Rename(filepath.Join(n.srcpath(), req.OldName), filepath.Join(newDir.srcpath(), req.NewName))
|
||||
}
|
||||
|
||||
func (n *Node) Mknod(ctx context.Context, req *fuse.MknodRequest) (fs.Node, error) {
|
||||
log.Printf("[mknod] node=%q name=%q mode=%#o rdev=%q newname=%q", n.path, req.Name, req.Mode, req.Rdev, req.Umask)
|
||||
if err := syscall.Mknod(filepath.Join(n.srcpath(), req.Name), uint32(req.Mode&req.Umask), int(req.Rdev)); err != nil {
|
||||
func (n *Node) Mknod(ctx context.Context, req *fuse.MknodRequest) (_ fs.Node, err error) {
|
||||
defer func() {
|
||||
log.Printf("[mknod] node=%q name=%q mode=%#o rdev=%q newname=%q -- err=%v", n.path, req.Name, req.Mode, req.Rdev, req.Umask, err)
|
||||
}()
|
||||
if err := syscall.Mknod(filepath.Join(n.srcpath(), req.Name), uint32(req.Mode^req.Umask), int(req.Rdev)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewNode(n.fs, filepath.Join(n.path, req.Name)), nil
|
||||
}
|
||||
|
||||
func (n *Node) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
||||
log.Printf("[fsync] node=%q flags=%#o dir=%v", n.path, req.Flags, req.Dir)
|
||||
func (n *Node) Fsync(ctx context.Context, req *fuse.FsyncRequest) (err error) {
|
||||
defer func() { log.Printf("[fsync] node=%q flags=%#o dir=%v -- err=%v", n.path, req.Flags, req.Dir, err) }()
|
||||
|
||||
f, err := os.Open(n.srcpath())
|
||||
if err != nil {
|
||||
@@ -349,35 +359,39 @@ func (n *Node) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
||||
// node.
|
||||
//
|
||||
// If there is no xattr by that name, returns fuse.ErrNoXattr.
|
||||
func (n *Node) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error {
|
||||
log.Printf("[getxattr] node=%q name=%q", n.path, req.Name)
|
||||
func (n *Node) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) (err error) {
|
||||
defer func() { log.Printf("[getxattr] node=%q name=%q -- err=%T", n.path, req.Name, err) }()
|
||||
|
||||
// TODO(bbj): Handle req.Size & returned syscall.Getxattr() size.
|
||||
_, err := syscall.Getxattr(n.srcpath(), req.Name, resp.Xattr)
|
||||
if _, err = syscall.Getxattr(n.srcpath(), req.Name, resp.Xattr); err == syscall.ENODATA {
|
||||
return fuse.ErrNoXattr
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Listxattr lists the extended attributes recorded for the node.
|
||||
func (n *Node) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error {
|
||||
log.Printf("[listxattr] node=%q", n.path)
|
||||
func (n *Node) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) (err error) {
|
||||
defer func() { log.Printf("[listxattr] node=%q -- err=%v", n.path, err) }()
|
||||
|
||||
// TODO(bbj): Handle req.Size & returned syscall.Getxattr() size.
|
||||
_, err := syscall.Listxattr(n.srcpath(), resp.Xattr)
|
||||
_, err = syscall.Listxattr(n.srcpath(), resp.Xattr)
|
||||
return err
|
||||
}
|
||||
|
||||
// Setxattr sets an extended attribute with the given name and
|
||||
// value for the node.
|
||||
func (n *Node) Setxattr(ctx context.Context, req *fuse.SetxattrRequest) error {
|
||||
log.Printf("[setxattr] node=%q name=%q data=%q flags=%#o", n.path, req.Name, string(req.Xattr), req.Flags)
|
||||
func (n *Node) Setxattr(ctx context.Context, req *fuse.SetxattrRequest) (err error) {
|
||||
defer func() {
|
||||
log.Printf("[setxattr] node=%q name=%q data=%q flags=%#o", n.path, req.Name, string(req.Xattr), req.Flags, err)
|
||||
}()
|
||||
return syscall.Setxattr(n.srcpath(), req.Name, req.Xattr, int(req.Flags))
|
||||
}
|
||||
|
||||
// Removexattr removes an extended attribute for the name.
|
||||
//
|
||||
// If there is no xattr by that name, returns fuse.ErrNoXattr.
|
||||
func (n *Node) Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) error {
|
||||
log.Printf("[removexattr] node=%q name=%q", n.path, req.Name)
|
||||
func (n *Node) Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) (err error) {
|
||||
defer func() { log.Printf("[removexattr] node=%q name=%q -- err=%v", n.path, req.Name, err) }()
|
||||
return syscall.Removexattr(n.srcpath(), req.Name)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user