You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

dir_node.go 5.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //go:build linux || (darwin && amd64)
  2. package fuse
  3. import (
  4. "context"
  5. "os"
  6. "syscall"
  7. fusefs "github.com/hanwen/go-fuse/v2/fs"
  8. "github.com/hanwen/go-fuse/v2/fuse"
  9. "gitlink.org.cn/cloudream/common/pkgs/logger"
  10. )
  11. type DirNode struct {
  12. NodeBase
  13. dir FsDir
  14. }
  15. func newDirNode(fs *Fuse, dir FsDir) *DirNode {
  16. return &DirNode{NodeBase: NodeBase{fs: fs}, dir: dir}
  17. }
  18. func (n *DirNode) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno {
  19. logger.Tracef("DirNode.Getattr: %v", n.dir.Name())
  20. n.fs.fillAttrOut(n.dir, out)
  21. return 0
  22. }
  23. // Setattr sets attributes for an Inode.
  24. func (n *DirNode) Setattr(ctx context.Context, f fusefs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) (errno syscall.Errno) {
  25. logger.Tracef("DirNode.Setattr: %v", n.dir.Name())
  26. n.fs.fillAttrOut(n.dir, out)
  27. _, ok := in.GetSize()
  28. if ok {
  29. return syscall.ENOSYS
  30. }
  31. modTime, ok := in.GetMTime()
  32. if ok {
  33. err := n.dir.SetModTime(modTime)
  34. if err != nil {
  35. return translateError(err)
  36. }
  37. out.Mtime = uint64(modTime.Unix())
  38. out.Mtimensec = uint32(modTime.Nanosecond())
  39. }
  40. return 0
  41. }
  42. var _ = (fusefs.NodeSetattrer)((*DirNode)(nil))
  43. // accessModeMask masks off the read modes from the flags
  44. const accessModeMask = (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)
  45. // Open opens an Inode (of regular file type) for reading. It
  46. // is optional but recommended to return a FileHandle.
  47. func (n *DirNode) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
  48. logger.Tracef("DirNode.Open: %v, %#o", n.dir.Name(), flags)
  49. rdwrMode := int(flags) & accessModeMask
  50. if rdwrMode != os.O_RDONLY {
  51. return nil, 0, syscall.EPERM
  52. }
  53. reader, err := n.dir.ReadChildren()
  54. if err != nil {
  55. return nil, 0, translateError(err)
  56. }
  57. return newDirHandle(n.dir, reader), 0, 0
  58. }
  59. var _ = (fusefs.NodeOpener)((*DirNode)(nil))
  60. func (n *DirNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) {
  61. logger.Tracef("DirNode.Lookup: %v, %v", n.dir.Name(), name)
  62. child, err := n.dir.Child(ctx, name)
  63. if err != nil {
  64. return nil, translateError(err)
  65. }
  66. switch child := child.(type) {
  67. case FsDir:
  68. node := newDirNode(n.fs, child)
  69. n.fs.fillEntryOut(child, out)
  70. return n.NewInode(ctx, node, fusefs.StableAttr{
  71. Mode: out.Attr.Mode,
  72. }), 0
  73. case FsFile:
  74. node := newFileNode(n.fs, child)
  75. n.fs.fillEntryOut(child, out)
  76. return n.NewInode(ctx, node, fusefs.StableAttr{
  77. Mode: out.Attr.Mode,
  78. }), 0
  79. default:
  80. return nil, syscall.EINVAL
  81. }
  82. }
  83. var _ = (fusefs.NodeLookuper)((*DirNode)(nil))
  84. func (n *DirNode) Opendir(ctx context.Context) syscall.Errno {
  85. return 0
  86. }
  87. var _ = (fusefs.NodeOpendirer)((*DirNode)(nil))
  88. type dirStream struct {
  89. reader DirReader
  90. fs *Fuse
  91. }
  92. func (s *dirStream) HasNext() bool {
  93. return s.reader.HasNext()
  94. }
  95. func (s *dirStream) Next() (fuse.DirEntry, syscall.Errno) {
  96. entries, err := s.reader.Next(1)
  97. if err != nil {
  98. return fuse.DirEntry{}, translateError(err)
  99. }
  100. entry := entries[0]
  101. return fuse.DirEntry{
  102. Name: entry.Name(),
  103. Mode: s.fs.getMode(entry),
  104. }, 0
  105. }
  106. func (s *dirStream) Close() {
  107. s.reader.Close()
  108. }
  109. func (n *DirNode) Readdir(ctx context.Context) (ds fusefs.DirStream, errno syscall.Errno) {
  110. logger.Tracef("DirNode.Readdir: %v", n.dir.Name())
  111. reader, err := n.dir.ReadChildren()
  112. if err != nil {
  113. return nil, translateError(err)
  114. }
  115. return &dirStream{reader: reader, fs: n.fs}, 0
  116. }
  117. var _ = (fusefs.NodeReaddirer)((*DirNode)(nil))
  118. func (n *DirNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) {
  119. logger.Tracef("DirNode.Mkdir: %v, %v, %#o", n.dir.Name(), name, mode)
  120. newDir, err := n.dir.NewDir(ctx, name)
  121. if err != nil {
  122. return nil, translateError(err)
  123. }
  124. node := newDirNode(n.fs, newDir)
  125. n.fs.fillEntryOut(newDir, out)
  126. return n.NewInode(ctx, node, fusefs.StableAttr{
  127. Mode: out.Attr.Mode,
  128. }), 0
  129. }
  130. var _ = (fusefs.NodeMkdirer)((*DirNode)(nil))
  131. 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) {
  132. logger.Tracef("DirNode.Create: %v, %v, %#o, %#o", n.dir.Name(), name, flags, mode)
  133. hd, err := n.dir.NewFile(ctx, name, flags)
  134. if err != nil {
  135. return nil, nil, 0, translateError(err)
  136. }
  137. n.fs.fillEntryOut(hd.Entry(), out)
  138. fileNode := newFileNode(n.fs, hd.Entry())
  139. return n.NewInode(ctx, fileNode, fusefs.StableAttr{
  140. Mode: out.Attr.Mode,
  141. }), hd, 0, 0
  142. }
  143. var _ = (fusefs.NodeCreater)((*DirNode)(nil))
  144. // Unlink should remove a child from this directory. If the
  145. // return status is OK, the Inode is removed as child in the
  146. // FS tree automatically. Default is to return EROFS.
  147. func (n *DirNode) Unlink(ctx context.Context, name string) (errno syscall.Errno) {
  148. logger.Tracef("DirNode.Unlink: %v, %v", n.dir.Name(), name)
  149. return translateError(n.dir.RemoveChild(ctx, name))
  150. }
  151. var _ = (fusefs.NodeUnlinker)((*DirNode)(nil))
  152. // Rmdir is like Unlink but for directories.
  153. // Default is to return EROFS.
  154. func (n *DirNode) Rmdir(ctx context.Context, name string) (errno syscall.Errno) {
  155. logger.Tracef("DirNode.Rmdir: %v, %v", n.dir.Name(), name)
  156. return translateError(n.dir.RemoveChild(ctx, name))
  157. }
  158. var _ = (fusefs.NodeRmdirer)((*DirNode)(nil))
  159. func (n *DirNode) Rename(ctx context.Context, oldName string, newParent fusefs.InodeEmbedder, newName string, flags uint32) (errno syscall.Errno) {
  160. logger.Tracef("DirNode.Rename: %v/%v->%v, %#o", n.dir.Name(), oldName, newName, flags)
  161. newParentNode, ok := newParent.(*DirNode)
  162. if !ok {
  163. return syscall.ENOTDIR
  164. }
  165. return translateError(n.dir.MoveChild(ctx, oldName, newName, newParentNode.dir))
  166. }
  167. var _ = (fusefs.NodeRenamer)((*DirNode)(nil))

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。