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.

120 lines
2.7 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. // +build linux darwin
  2. package command
  3. import (
  4. "fmt"
  5. "os"
  6. "runtime"
  7. "path"
  8. "bazil.org/fuse"
  9. "bazil.org/fuse/fs"
  10. "github.com/chrislusf/seaweedfs/weed/filer"
  11. "github.com/chrislusf/seaweedfs/weed/glog"
  12. "github.com/chrislusf/seaweedfs/weed/storage"
  13. "github.com/chrislusf/seaweedfs/weed/util"
  14. "golang.org/x/net/context"
  15. )
  16. func runMount(cmd *Command, args []string) bool {
  17. fmt.Printf("This is SeaweedFS version %s %s %s\n", util.VERSION, runtime.GOOS, runtime.GOARCH)
  18. if *mountOptions.dir == "" {
  19. fmt.Printf("Please specify the mount directory via \"-dir\"")
  20. return false
  21. }
  22. c, err := fuse.Mount(*mountOptions.dir, fuse.LocalVolume())
  23. if err != nil {
  24. glog.Fatal(err)
  25. return false
  26. }
  27. OnInterrupt(func() {
  28. fuse.Unmount(*mountOptions.dir)
  29. c.Close()
  30. })
  31. err = fs.Serve(c, WFS{})
  32. if err != nil {
  33. fuse.Unmount(*mountOptions.dir)
  34. }
  35. // check if the mount process has an error to report
  36. <-c.Ready
  37. if err := c.MountError; err != nil {
  38. glog.Fatal(err)
  39. }
  40. return true
  41. }
  42. type WFS struct{}
  43. func (WFS) Root() (fs.Node, error) {
  44. return &Dir{Path: "/"}, nil
  45. }
  46. type Dir struct {
  47. Id uint64
  48. Path string
  49. DirentMap map[string]*fuse.Dirent
  50. }
  51. func (dir *Dir) Attr(context context.Context, attr *fuse.Attr) error {
  52. attr.Inode = dir.Id
  53. attr.Mode = os.ModeDir | 0555
  54. return nil
  55. }
  56. func (dir *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) {
  57. if dirent, ok := dir.DirentMap[name]; ok {
  58. if dirent.Type == fuse.DT_File {
  59. return &File{dirent.Inode, dirent.Name}, nil
  60. }
  61. return &Dir{
  62. Id: dirent.Inode,
  63. Path: path.Join(dir.Path, dirent.Name),
  64. }, nil
  65. }
  66. return nil, fuse.ENOENT
  67. }
  68. func (dir *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
  69. var ret []fuse.Dirent
  70. if dir.DirentMap == nil {
  71. dir.DirentMap = make(map[string]*fuse.Dirent)
  72. }
  73. if dirs, e := filer.ListDirectories(*mountOptions.filer, dir.Path); e == nil {
  74. for _, d := range dirs.Directories {
  75. dirId := uint64(d.Id)
  76. dirent := fuse.Dirent{Inode: dirId, Name: d.Name, Type: fuse.DT_Dir}
  77. ret = append(ret, dirent)
  78. dir.DirentMap[d.Name] = &dirent
  79. }
  80. }
  81. if files, e := filer.ListFiles(*mountOptions.filer, dir.Path, ""); e == nil {
  82. for _, f := range files.Files {
  83. if fileId, e := storage.ParseFileId(string(f.Id)); e == nil {
  84. fileInode := uint64(fileId.VolumeId)<<48 + fileId.Key
  85. dirent := fuse.Dirent{Inode: fileInode, Name: f.Name, Type: fuse.DT_File}
  86. ret = append(ret, dirent)
  87. dir.DirentMap[f.Name] = &dirent
  88. }
  89. }
  90. }
  91. return ret, nil
  92. }
  93. type File struct {
  94. Id uint64
  95. // FileId filer.FileId
  96. Name string
  97. }
  98. func (file *File) Attr(context context.Context, attr *fuse.Attr) error {
  99. attr.Inode = file.Id
  100. attr.Mode = 0000
  101. return nil
  102. }