|
- package mount
-
- import (
- "context"
- "os"
- "syscall"
-
- fusefs "github.com/hanwen/go-fuse/v2/fs"
- "github.com/hanwen/go-fuse/v2/fuse"
- )
-
- type DirNode struct {
- NodeBase
- dir FsDir
- }
-
- func newDirNode(vfs *Vfs, dir FsDir) *DirNode {
- return &DirNode{NodeBase: NodeBase{vfs: vfs}, dir: dir}
- }
-
- func (n *DirNode) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno {
- n.vfs.fillAttrOut(n.dir, out)
- return 0
- }
-
- // Setattr sets attributes for an Inode.
- func (n *DirNode) Setattr(ctx context.Context, f fusefs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) (errno syscall.Errno) {
- n.vfs.fillAttrOut(n.dir, out)
-
- _, ok := in.GetSize()
- if ok {
- return syscall.ENOSYS
- }
-
- modTime, ok := in.GetMTime()
- if ok {
- err := n.dir.SetModTime(modTime)
- if err != nil {
- return translateError(err)
- }
- out.Mtime = uint64(modTime.Unix())
- out.Mtimensec = uint32(modTime.Nanosecond())
- }
-
- return 0
- }
-
- var _ = (fusefs.NodeSetattrer)((*DirNode)(nil))
-
- // accessModeMask masks off the read modes from the flags
- const accessModeMask = (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)
-
- // Open opens an Inode (of regular file type) for reading. It
- // is optional but recommended to return a FileHandle.
- func (n *DirNode) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
- rdwrMode := int(flags) & accessModeMask
- if rdwrMode != os.O_RDONLY {
- return nil, 0, syscall.EPERM
- }
-
- reader, err := n.dir.ReadChildren()
- if err != nil {
- return nil, 0, translateError(err)
- }
-
- return newDirHandle(n.dir, reader), 0, 0
- }
-
- var _ = (fusefs.NodeOpener)((*DirNode)(nil))
-
- func (n *DirNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) {
- child, err := n.dir.Child(ctx, name)
- if err != nil {
- return nil, translateError(err)
- }
-
- switch child := child.(type) {
- case FsDir:
- node := newDirNode(n.vfs, child)
- n.vfs.fillEntryOut(child, out)
-
- return node.NewInode(ctx, node, fusefs.StableAttr{
- Mode: out.Attr.Mode,
- }), 0
-
- case FsFile:
- node := newFileNode(n.vfs, child)
- n.vfs.fillEntryOut(child, out)
-
- return node.NewInode(ctx, node, fusefs.StableAttr{
- Mode: out.Attr.Mode,
- }), 0
-
- default:
- return nil, syscall.EINVAL
- }
- }
-
- var _ = (fusefs.NodeLookuper)((*DirNode)(nil))
-
- func (n *DirNode) Opendir(ctx context.Context) syscall.Errno {
- return 0
- }
-
- var _ = (fusefs.NodeOpendirer)((*DirNode)(nil))
-
- type dirStream struct {
- reader DirReader
- vfs *Vfs
- }
-
- func (s *dirStream) HasNext() bool {
- return s.reader.HasNext()
- }
-
- func (s *dirStream) Next() (fuse.DirEntry, syscall.Errno) {
- entries, err := s.reader.Next(1)
- if err != nil {
- return fuse.DirEntry{}, translateError(err)
- }
- entry := entries[0]
-
- return fuse.DirEntry{
- Name: entry.Name(),
- Mode: s.vfs.getMode(entry),
- }, 0
- }
-
- func (s *dirStream) Close() {
- s.reader.Close()
- }
-
- func (n *DirNode) Readdir(ctx context.Context) (ds fusefs.DirStream, errno syscall.Errno) {
- reader, err := n.dir.ReadChildren()
- if err != nil {
- return nil, translateError(err)
- }
-
- return &dirStream{reader: reader, vfs: n.vfs}, 0
- }
-
- var _ = (fusefs.NodeReaddirer)((*DirNode)(nil))
-
- func (n *DirNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) {
- newDir, err := n.dir.NewDir(ctx, name)
- if err != nil {
- return nil, translateError(err)
- }
-
- node := newDirNode(n.vfs, newDir)
- n.vfs.fillEntryOut(newDir, out)
-
- return node.NewInode(ctx, node, fusefs.StableAttr{
- Mode: out.Attr.Mode,
- }), 0
- }
-
- var _ = (fusefs.NodeMkdirer)((*DirNode)(nil))
-
- func (n *DirNode) Create(ctx context.Context, name string, flags uint32, mode uint32, out *fuse.EntryOut) (node *fusefs.Inode, fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
- newFile, err := n.dir.NewFile(ctx, name, flags)
- if err != nil {
- return nil, nil, 0, translateError(err)
- }
-
- hd, err := newFile.Open(flags)
- if err != nil {
- return nil, nil, 0, translateError(err)
- }
-
- n.vfs.fillEntryOut(newFile, out)
-
- fileNode := newFileNode(n.vfs, newFile)
- return fileNode.NewInode(ctx, fileNode, fusefs.StableAttr{
- Mode: out.Attr.Mode,
- }), hd, 0, 0
- }
-
- var _ = (fusefs.NodeCreater)((*DirNode)(nil))
-
- // 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. Default is to return EROFS.
- func (n *DirNode) Unlink(ctx context.Context, name string) (errno syscall.Errno) {
- return translateError(n.dir.RemoveChild(ctx, name))
- }
-
- var _ = (fusefs.NodeUnlinker)((*DirNode)(nil))
-
- // Rmdir is like Unlink but for directories.
- // Default is to return EROFS.
- func (n *DirNode) Rmdir(ctx context.Context, name string) (errno syscall.Errno) {
- return translateError(n.dir.RemoveChild(ctx, name))
- }
-
- var _ = (fusefs.NodeRmdirer)((*DirNode)(nil))
-
- func (n *DirNode) Rename(ctx context.Context, oldName string, newParent fusefs.InodeEmbedder, newName string, flags uint32) (errno syscall.Errno) {
- newParentNode, ok := newParent.(*DirNode)
- if !ok {
- return syscall.ENOTDIR
- }
- return translateError(n.dir.MoveChild(ctx, oldName, newName, newParentNode.dir))
- }
-
- var _ = (fusefs.NodeRenamer)((*DirNode)(nil))
|