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.2 kB

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

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