weedfs_symlink.go 2.1 KB

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