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.

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