weedfs_symlink.go 2.1 KB

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