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.

144 lines
3.4 KiB

8 years ago
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. util.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. var fileIdMap = make(map[uint64]filer.FileId)
  47. type Dir struct {
  48. Path string
  49. DirentMap map[string]*fuse.Dirent
  50. }
  51. func (dir *Dir) Attr(context context.Context, attr *fuse.Attr) error {
  52. attr.Mode = os.ModeDir | 0555
  53. return nil
  54. }
  55. func (dir *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) {
  56. if entry, err := filer.LookupDirectoryEntry(*mountOptions.filer, dir.Path, name); err == nil {
  57. if !entry.Found {
  58. return nil, fuse.ENOENT
  59. }
  60. if entry.FileId != "" {
  61. return &File{FileId: filer.FileId(entry.FileId), Name: name}, nil
  62. } else {
  63. return &Dir{Path: path.Join(dir.Path, name)}, nil
  64. }
  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. dirent := fuse.Dirent{Name: string(d), Type: fuse.DT_Dir}
  76. ret = append(ret, dirent)
  77. dir.DirentMap[string(d)] = &dirent
  78. }
  79. }
  80. if files, e := filer.ListFiles(*mountOptions.filer, dir.Path, ""); e == nil {
  81. for _, f := range files.Files {
  82. if fileId, e := storage.ParseFileId(string(f.Id)); e == nil {
  83. fileInode := uint64(fileId.VolumeId)<<48 + fileId.Key
  84. dirent := fuse.Dirent{Name: f.Name, Type: fuse.DT_File}
  85. ret = append(ret, dirent)
  86. dir.DirentMap[f.Name] = &dirent
  87. fileIdMap[fileInode] = f.Id
  88. }
  89. }
  90. }
  91. return ret, nil
  92. }
  93. func (dir *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
  94. name := path.Join(dir.Path, req.Name)
  95. err := filer.DeleteDirectoryOrFile(*mountOptions.filer, name, req.Dir)
  96. if err != nil {
  97. fmt.Printf("Delete file %s [ERROR] %s\n", name, err)
  98. }
  99. return err
  100. }
  101. type File struct {
  102. FileId filer.FileId
  103. Name string
  104. }
  105. func (file *File) Attr(context context.Context, attr *fuse.Attr) error {
  106. attr.Mode = 0444
  107. ret, err := filer.GetFileSize(*mountOptions.filer, string(file.FileId))
  108. if err == nil {
  109. attr.Size = ret.Size
  110. } else {
  111. fmt.Printf("Get file %s attr [ERROR] %s\n", file.Name, err)
  112. }
  113. return err
  114. }
  115. func (file *File) ReadAll(ctx context.Context) ([]byte, error) {
  116. ret, err := filer.GetFileContent(*mountOptions.filer, string(file.FileId))
  117. if err == nil {
  118. return ret.Content, nil
  119. }
  120. fmt.Printf("Get file %s content [ERROR] %s\n", file.Name, err)
  121. return nil, err
  122. }