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.

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