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

303 lines
7.5 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package mount
  2. import (
  3. "github.com/chrislusf/seaweedfs/weed/filer"
  4. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  5. "github.com/hanwen/go-fuse/v2/fuse"
  6. sys "golang.org/x/sys/unix"
  7. "os"
  8. "runtime"
  9. "strings"
  10. "syscall"
  11. "time"
  12. )
  13. const (
  14. // https://man7.org/linux/man-pages/man7/xattr.7.html#:~:text=The%20VFS%20imposes%20limitations%20that,in%20listxattr(2)).
  15. MAX_XATTR_NAME_SIZE = 255
  16. MAX_XATTR_VALUE_SIZE = 65536
  17. XATTR_PREFIX = "xattr-" // same as filer
  18. )
  19. func (wfs *WFS) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out *fuse.AttrOut) (code fuse.Status) {
  20. if input.NodeId == 1 {
  21. wfs.setRootAttr(out)
  22. return fuse.OK
  23. }
  24. _, entry, status := wfs.maybeReadEntry(input.NodeId)
  25. if status != fuse.OK {
  26. return status
  27. }
  28. out.AttrValid = 1
  29. wfs.setAttrByPbEntry(&out.Attr, input.NodeId, entry)
  30. return fuse.OK
  31. }
  32. func (wfs *WFS) SetAttr(cancel <-chan struct{}, input *fuse.SetAttrIn, out *fuse.AttrOut) (code fuse.Status) {
  33. // TODO this is only for directory. Filet setAttr involves open files and truncate to a size
  34. path, entry, status := wfs.maybeReadEntry(input.NodeId)
  35. if status != fuse.OK {
  36. return status
  37. }
  38. if mode, ok := input.GetMode(); ok {
  39. entry.Attributes.FileMode = uint32(mode)
  40. }
  41. if uid, ok := input.GetUID(); ok {
  42. entry.Attributes.Uid = uid
  43. }
  44. if gid, ok := input.GetGID(); ok {
  45. entry.Attributes.Gid = gid
  46. }
  47. if mtime, ok := input.GetMTime(); ok {
  48. entry.Attributes.Mtime = mtime.Unix()
  49. }
  50. entry.Attributes.Mtime = time.Now().Unix()
  51. out.AttrValid = 1
  52. wfs.setAttrByPbEntry(&out.Attr, input.NodeId, entry)
  53. return wfs.saveEntry(path, entry)
  54. }
  55. // GetXAttr reads an extended attribute, and should return the
  56. // number of bytes. If the buffer is too small, return ERANGE,
  57. // with the required buffer size.
  58. func (wfs *WFS) GetXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string, dest []byte) (size uint32, code fuse.Status) {
  59. //validate attr name
  60. if len(attr) > MAX_XATTR_NAME_SIZE {
  61. if runtime.GOOS == "darwin" {
  62. return 0, fuse.EPERM
  63. } else {
  64. return 0, fuse.ERANGE
  65. }
  66. }
  67. if len(attr) == 0 {
  68. return 0, fuse.EINVAL
  69. }
  70. _, entry, status := wfs.maybeReadEntry(header.NodeId)
  71. if status != fuse.OK {
  72. return 0, status
  73. }
  74. if entry == nil {
  75. return 0, fuse.ENOENT
  76. }
  77. if entry.Extended == nil {
  78. return 0, fuse.ENOATTR
  79. }
  80. data, found := entry.Extended[XATTR_PREFIX+attr]
  81. if !found {
  82. return 0, fuse.ENOATTR
  83. }
  84. if len(dest) < len(data) {
  85. return uint32(len(data)), fuse.ERANGE
  86. }
  87. copy(dest, data)
  88. return uint32(len(data)), fuse.OK
  89. }
  90. // SetXAttr writes an extended attribute.
  91. // https://man7.org/linux/man-pages/man2/setxattr.2.html
  92. // By default (i.e., flags is zero), the extended attribute will be
  93. // created if it does not exist, or the value will be replaced if
  94. // the attribute already exists. To modify these semantics, one of
  95. // the following values can be specified in flags:
  96. //
  97. // XATTR_CREATE
  98. // Perform a pure create, which fails if the named attribute
  99. // exists already.
  100. //
  101. // XATTR_REPLACE
  102. // Perform a pure replace operation, which fails if the named
  103. // attribute does not already exist.
  104. func (wfs *WFS) SetXAttr(cancel <-chan struct{}, input *fuse.SetXAttrIn, attr string, data []byte) fuse.Status {
  105. //validate attr name
  106. if len(attr) > MAX_XATTR_NAME_SIZE {
  107. if runtime.GOOS == "darwin" {
  108. return fuse.EPERM
  109. } else {
  110. return fuse.ERANGE
  111. }
  112. }
  113. if len(attr) == 0 {
  114. return fuse.EINVAL
  115. }
  116. //validate attr value
  117. if len(data) > MAX_XATTR_VALUE_SIZE {
  118. if runtime.GOOS == "darwin" {
  119. return fuse.Status(syscall.E2BIG)
  120. } else {
  121. return fuse.ERANGE
  122. }
  123. }
  124. path, entry, status := wfs.maybeReadEntry(input.NodeId)
  125. if status != fuse.OK {
  126. return status
  127. }
  128. if entry.Extended == nil {
  129. entry.Extended = make(map[string][]byte)
  130. }
  131. oldData, _ := entry.Extended[XATTR_PREFIX+attr]
  132. switch input.Flags {
  133. case sys.XATTR_CREATE:
  134. if len(oldData) > 0 {
  135. break
  136. }
  137. fallthrough
  138. case sys.XATTR_REPLACE:
  139. fallthrough
  140. default:
  141. entry.Extended[XATTR_PREFIX+attr] = data
  142. }
  143. return wfs.saveEntry(path, entry)
  144. }
  145. // ListXAttr lists extended attributes as '\0' delimited byte
  146. // slice, and return the number of bytes. If the buffer is too
  147. // small, return ERANGE, with the required buffer size.
  148. func (wfs *WFS) ListXAttr(cancel <-chan struct{}, header *fuse.InHeader, dest []byte) (n uint32, code fuse.Status) {
  149. _, entry, status := wfs.maybeReadEntry(header.NodeId)
  150. if status != fuse.OK {
  151. return 0, status
  152. }
  153. if entry == nil {
  154. return 0, fuse.ENOENT
  155. }
  156. if entry.Extended == nil {
  157. return 0, fuse.ENOATTR
  158. }
  159. var data []byte
  160. for k := range entry.Extended {
  161. if strings.HasPrefix(k, XATTR_PREFIX) {
  162. data = append(data, k[len(XATTR_PREFIX):]...)
  163. data = append(data, 0)
  164. }
  165. }
  166. if len(dest) < len(data) {
  167. return uint32(len(data)), fuse.ERANGE
  168. }
  169. copy(dest, data)
  170. return uint32(len(data)), fuse.OK
  171. }
  172. // RemoveXAttr removes an extended attribute.
  173. func (wfs *WFS) RemoveXAttr(cancel <-chan struct{}, header *fuse.InHeader, attr string) fuse.Status {
  174. if len(attr) == 0 {
  175. return fuse.EINVAL
  176. }
  177. path, entry, status := wfs.maybeReadEntry(header.NodeId)
  178. if status != fuse.OK {
  179. return status
  180. }
  181. if entry.Extended == nil {
  182. return fuse.ENOATTR
  183. }
  184. _, found := entry.Extended[XATTR_PREFIX+attr]
  185. if !found {
  186. return fuse.ENOATTR
  187. }
  188. delete(entry.Extended, XATTR_PREFIX+attr)
  189. return wfs.saveEntry(path, entry)
  190. }
  191. func (wfs *WFS) setRootAttr(out *fuse.AttrOut) {
  192. now := uint64(time.Now().Unix())
  193. out.AttrValid = 119
  194. out.Ino = 1
  195. setBlksize(&out.Attr, blockSize)
  196. out.Uid = wfs.option.MountUid
  197. out.Gid = wfs.option.MountGid
  198. out.Mtime = now
  199. out.Ctime = now
  200. out.Atime = now
  201. out.Mode = toSystemType(os.ModeDir) | uint32(wfs.option.MountMode)
  202. out.Nlink = 1
  203. }
  204. func (wfs *WFS) setAttrByPbEntry(out *fuse.Attr, inode uint64, entry *filer_pb.Entry) {
  205. out.Ino = inode
  206. out.Size = filer.FileSize(entry)
  207. out.Blocks = (out.Size + blockSize - 1) / blockSize
  208. setBlksize(out, blockSize)
  209. out.Mtime = uint64(entry.Attributes.Mtime)
  210. out.Ctime = uint64(entry.Attributes.Mtime)
  211. out.Atime = uint64(entry.Attributes.Mtime)
  212. out.Mode = toSystemMode(os.FileMode(entry.Attributes.FileMode))
  213. if entry.HardLinkCounter > 0 {
  214. out.Nlink = uint32(entry.HardLinkCounter)
  215. } else {
  216. out.Nlink = 1
  217. }
  218. out.Uid = entry.Attributes.Uid
  219. out.Gid = entry.Attributes.Gid
  220. }
  221. func (wfs *WFS) setAttrByFilerEntry(out *fuse.Attr, inode uint64, entry *filer.Entry) {
  222. out.Ino = inode
  223. out.Size = entry.FileSize
  224. out.Blocks = (out.Size + blockSize - 1) / blockSize
  225. setBlksize(out, blockSize)
  226. out.Atime = uint64(entry.Attr.Mtime.Unix())
  227. out.Mtime = uint64(entry.Attr.Mtime.Unix())
  228. out.Ctime = uint64(entry.Attr.Mtime.Unix())
  229. out.Crtime_ = uint64(entry.Attr.Crtime.Unix())
  230. out.Mode = toSystemMode(entry.Attr.Mode)
  231. if entry.HardLinkCounter > 0 {
  232. out.Nlink = uint32(entry.HardLinkCounter)
  233. } else {
  234. out.Nlink = 1
  235. }
  236. out.Uid = entry.Attr.Uid
  237. out.Gid = entry.Attr.Gid
  238. }
  239. func (wfs *WFS) outputEntry(out *fuse.EntryOut, inode uint64, entry *filer.Entry) {
  240. out.NodeId = inode
  241. out.Generation = 1
  242. out.EntryValid = 1
  243. out.AttrValid = 1
  244. wfs.setAttrByFilerEntry(&out.Attr, inode, entry)
  245. }
  246. func toSystemMode(mode os.FileMode) uint32 {
  247. return toSystemType(mode) | uint32(mode)
  248. }
  249. func toSystemType(mode os.FileMode) uint32 {
  250. switch mode & os.ModeType {
  251. case os.ModeDir:
  252. return syscall.S_IFDIR
  253. case os.ModeSymlink:
  254. return syscall.S_IFLNK
  255. case os.ModeNamedPipe:
  256. return syscall.S_IFIFO
  257. case os.ModeSocket:
  258. return syscall.S_IFSOCK
  259. case os.ModeDevice:
  260. return syscall.S_IFBLK
  261. case os.ModeCharDevice:
  262. return syscall.S_IFCHR
  263. default:
  264. return syscall.S_IFREG
  265. }
  266. }