main.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //+build linux
  2. package main
  3. //go:generate go run cmd/genversion/main.go -package main -out version.go
  4. import (
  5. "context"
  6. "flag"
  7. "fmt"
  8. "os"
  9. "os/exec"
  10. "os/signal"
  11. "runtime"
  12. "syscall"
  13. "dev.hexasoftware.com/hxs/cloudmount/fs/gdrivefs"
  14. "github.com/jacobsa/fuse"
  15. "github.com/jacobsa/fuse/fuseutil"
  16. "dev.hexasoftware.com/hxs/prettylog"
  17. //_ "github.com/icattlecoder/godaemon" // No reason
  18. )
  19. var (
  20. Name = "cloudmount"
  21. log = prettylog.New("main")
  22. )
  23. func main() {
  24. var daemonize bool
  25. var verboselog bool
  26. var clouddrive string
  27. prettylog.Global()
  28. // getClient
  29. fmt.Printf("%s-%s\n\n", Name, Version)
  30. flag.StringVar(&clouddrive, "t", "gdrive", "which cloud service to use [gdrive]")
  31. flag.BoolVar(&daemonize, "d", false, "Run app in background")
  32. flag.BoolVar(&verboselog, "v", false, "Verbose log")
  33. flag.Usage = func() {
  34. fmt.Fprintf(os.Stderr, "Usage: %s [options] MOUNTPOINT\n\n", os.Args[0])
  35. fmt.Fprintf(os.Stderr, "Options:\n")
  36. flag.PrintDefaults()
  37. fmt.Fprintf(os.Stderr, "\n")
  38. }
  39. flag.Parse()
  40. if len(flag.Args()) < 1 {
  41. flag.Usage()
  42. //fmt.Println("Usage:\n gdrivemount [-d] [-v] MOUNTPOINT")
  43. return
  44. }
  45. driveFS := gdrivefs.NewGDriveFS() // there can be some interaction before daemon
  46. // Daemon
  47. if daemonize {
  48. subArgs := []string{}
  49. for _, arg := range os.Args[1:] {
  50. if arg == "-d" { // ignore daemon flag
  51. continue
  52. }
  53. subArgs = append(subArgs, arg)
  54. }
  55. cmd := exec.Command(os.Args[0], subArgs...)
  56. cmd.Start()
  57. fmt.Println("[PID]", cmd.Process.Pid)
  58. os.Exit(0)
  59. return
  60. }
  61. //////////////
  62. // Server
  63. /////////
  64. ctx := context.Background()
  65. server := fuseutil.NewFileSystemServer(driveFS)
  66. mountPath := flag.Arg(0)
  67. var err error
  68. var mfs *fuse.MountedFileSystem
  69. if verboselog {
  70. mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{DebugLogger: prettylog.New("fuse"), ErrorLogger: prettylog.New("fuse-err")})
  71. } else {
  72. mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{})
  73. }
  74. if err != nil {
  75. log.Fatal("Failed mounting path", flag.Arg(0))
  76. }
  77. // Signal handling to refresh Drives
  78. sigs := make(chan os.Signal, 2)
  79. signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGHUP, syscall.SIGINT, os.Interrupt, syscall.SIGTERM)
  80. go func() {
  81. for sig := range sigs {
  82. log.Println("Signal:", sig)
  83. switch sig {
  84. case syscall.SIGUSR1:
  85. log.Println("Manually Refresh drive")
  86. go driveFS.Refresh()
  87. case syscall.SIGHUP:
  88. log.Println("GC")
  89. mem := runtime.MemStats{}
  90. runtime.ReadMemStats(&mem)
  91. log.Printf("Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
  92. runtime.GC()
  93. runtime.ReadMemStats(&mem)
  94. log.Printf("After gc: Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
  95. case os.Interrupt:
  96. log.Println("Graceful unmount")
  97. fuse.Unmount(mountPath)
  98. os.Exit(1)
  99. case syscall.SIGTERM:
  100. log.Println("Graceful unmount")
  101. fuse.Unmount(mountPath)
  102. os.Exit(1)
  103. }
  104. }
  105. }()
  106. if err := mfs.Join(ctx); err != nil {
  107. log.Fatalf("Joining: %v", err)
  108. }
  109. }