xattr.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package filesys
  2. import (
  3. "context"
  4. "strings"
  5. "syscall"
  6. "github.com/seaweedfs/fuse"
  7. "github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
  8. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  9. "github.com/chrislusf/seaweedfs/weed/util"
  10. )
  11. const (
  12. XATTR_PREFIX = "xattr-" // same as filer
  13. )
  14. func getxattr(entry *filer_pb.Entry, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error {
  15. if entry == nil {
  16. return fuse.ErrNoXattr
  17. }
  18. if entry.Extended == nil {
  19. return fuse.ErrNoXattr
  20. }
  21. data, found := entry.Extended[XATTR_PREFIX+req.Name]
  22. if !found {
  23. return fuse.ErrNoXattr
  24. }
  25. if req.Position < uint32(len(data)) {
  26. size := req.Size
  27. if req.Position+size >= uint32(len(data)) {
  28. size = uint32(len(data)) - req.Position
  29. }
  30. if size == 0 {
  31. resp.Xattr = data[req.Position:]
  32. } else {
  33. resp.Xattr = data[req.Position : req.Position+size]
  34. }
  35. }
  36. return nil
  37. }
  38. func setxattr(entry *filer_pb.Entry, req *fuse.SetxattrRequest) error {
  39. if entry == nil {
  40. return fuse.EIO
  41. }
  42. if entry.Extended == nil {
  43. entry.Extended = make(map[string][]byte)
  44. }
  45. data, _ := entry.Extended[XATTR_PREFIX+req.Name]
  46. newData := make([]byte, int(req.Position)+len(req.Xattr))
  47. copy(newData, data)
  48. copy(newData[int(req.Position):], req.Xattr)
  49. entry.Extended[XATTR_PREFIX+req.Name] = newData
  50. return nil
  51. }
  52. func removexattr(entry *filer_pb.Entry, req *fuse.RemovexattrRequest) error {
  53. if entry == nil {
  54. return fuse.ErrNoXattr
  55. }
  56. if entry.Extended == nil {
  57. return fuse.ErrNoXattr
  58. }
  59. _, found := entry.Extended[XATTR_PREFIX+req.Name]
  60. if !found {
  61. return fuse.ErrNoXattr
  62. }
  63. delete(entry.Extended, XATTR_PREFIX+req.Name)
  64. return nil
  65. }
  66. func listxattr(entry *filer_pb.Entry, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error {
  67. if entry == nil {
  68. return fuse.EIO
  69. }
  70. for k := range entry.Extended {
  71. if strings.HasPrefix(k, XATTR_PREFIX) {
  72. resp.Append(k[len(XATTR_PREFIX):])
  73. }
  74. }
  75. size := req.Size
  76. if req.Position+size >= uint32(len(resp.Xattr)) {
  77. size = uint32(len(resp.Xattr)) - req.Position
  78. }
  79. if size == 0 {
  80. resp.Xattr = resp.Xattr[req.Position:]
  81. } else {
  82. resp.Xattr = resp.Xattr[req.Position : req.Position+size]
  83. }
  84. return nil
  85. }
  86. func (wfs *WFS) maybeLoadEntry(dir, name string) (entry *filer_pb.Entry, err error) {
  87. fullpath := util.NewFullPath(dir, name)
  88. // glog.V(3).Infof("read entry cache miss %s", fullpath)
  89. // return a valid entry for the mount root
  90. if string(fullpath) == wfs.option.FilerMountRootPath {
  91. return &filer_pb.Entry{
  92. Name: name,
  93. IsDirectory: true,
  94. Attributes: &filer_pb.FuseAttributes{
  95. Mtime: wfs.option.MountMtime.Unix(),
  96. FileMode: uint32(wfs.option.MountMode),
  97. Uid: wfs.option.MountUid,
  98. Gid: wfs.option.MountGid,
  99. Crtime: wfs.option.MountCtime.Unix(),
  100. },
  101. }, nil
  102. }
  103. // read from async meta cache
  104. meta_cache.EnsureVisited(wfs.metaCache, wfs, util.FullPath(dir))
  105. cachedEntry, cacheErr := wfs.metaCache.FindEntry(context.Background(), fullpath)
  106. if cacheErr == filer_pb.ErrNotFound {
  107. return nil, fuse.ENOENT
  108. }
  109. return cachedEntry.ToProtoEntry(), cacheErr
  110. }
  111. func checkName(name string) error {
  112. if len(name) >= 256 {
  113. return syscall.ENAMETOOLONG
  114. }
  115. return nil
  116. }