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.

87 lines
2.2 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
  1. package mount
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/chrislusf/seaweedfs/weed/filer"
  6. "github.com/chrislusf/seaweedfs/weed/glog"
  7. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  8. "github.com/hanwen/go-fuse/v2/fuse"
  9. "os"
  10. "time"
  11. )
  12. /** Create a symbolic link */
  13. func (wfs *WFS) Symlink(cancel <-chan struct{}, header *fuse.InHeader, target string, name string, out *fuse.EntryOut) (code fuse.Status) {
  14. if wfs.IsOverQuota {
  15. return fuse.EPERM
  16. }
  17. if s := checkName(name); s != fuse.OK {
  18. return s
  19. }
  20. dirPath, code := wfs.inodeToPath.GetPath(header.NodeId)
  21. if code != fuse.OK {
  22. return
  23. }
  24. entryFullPath := dirPath.Child(name)
  25. request := &filer_pb.CreateEntryRequest{
  26. Directory: string(dirPath),
  27. Entry: &filer_pb.Entry{
  28. Name: name,
  29. IsDirectory: false,
  30. Attributes: &filer_pb.FuseAttributes{
  31. Mtime: time.Now().Unix(),
  32. Crtime: time.Now().Unix(),
  33. FileMode: uint32(os.FileMode(0777) | os.ModeSymlink),
  34. Uid: header.Uid,
  35. Gid: header.Gid,
  36. SymlinkTarget: target,
  37. },
  38. },
  39. Signatures: []int32{wfs.signature},
  40. }
  41. err := wfs.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
  42. wfs.mapPbIdFromLocalToFiler(request.Entry)
  43. defer wfs.mapPbIdFromFilerToLocal(request.Entry)
  44. if err := filer_pb.CreateEntry(client, request); err != nil {
  45. return fmt.Errorf("symlink %s: %v", entryFullPath, err)
  46. }
  47. wfs.metaCache.InsertEntry(context.Background(), filer.FromPbEntry(request.Directory, request.Entry))
  48. return nil
  49. })
  50. if err != nil {
  51. glog.V(0).Infof("Symlink %s => %s: %v", entryFullPath, target, err)
  52. return fuse.EIO
  53. }
  54. inode := wfs.inodeToPath.Lookup(entryFullPath, os.ModeSymlink, false, 0, true)
  55. wfs.outputPbEntry(out, inode, request.Entry)
  56. return fuse.OK
  57. }
  58. func (wfs *WFS) Readlink(cancel <-chan struct{}, header *fuse.InHeader) (out []byte, code fuse.Status) {
  59. entryFullPath, code := wfs.inodeToPath.GetPath(header.NodeId)
  60. if code != fuse.OK {
  61. return
  62. }
  63. entry, status := wfs.maybeLoadEntry(entryFullPath)
  64. if status != fuse.OK {
  65. return nil, status
  66. }
  67. if os.FileMode(entry.Attributes.FileMode)&os.ModeSymlink == 0 {
  68. return nil, fuse.EINVAL
  69. }
  70. return []byte(entry.Attributes.SymlinkTarget), fuse.OK
  71. }