luis 7 년 전
부모
커밋
92704792e9
9개의 변경된 파일270개의 추가작업 그리고 235개의 파일을 삭제
  1. 185 0
      cloudfs/core.go
  2. 1 0
      core/driver.go
  3. 0 42
      core/core.go
  4. 13 15
      fs/gdrivefs/client.go
  5. 3 13
      fs/gdrivefs/fileentry.go
  6. 39 40
      fs/gdrivefs/gdrive-fuse.go
  7. 17 0
      fs/gdrivefs/gdrivefs.go
  8. 0 11
      fs/gdrivefs/service.go
  9. 12 114
      main.go

+ 185 - 0
cloudfs/core.go

@@ -0,0 +1,185 @@
+package core
+
+import (
+	"context"
+	"flag"
+	"fmt"
+	"log"
+	"os"
+	"os/signal"
+	"os/user"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"syscall"
+
+	"dev.hexasoftware.com/hxs/prettylog"
+
+	"github.com/jacobsa/fuse"
+	"github.com/jacobsa/fuse/fuseutil"
+)
+
+type Core struct {
+	Config  Config
+	Drivers map[string]DriverFactory
+}
+
+type Config struct {
+	Daemonize     bool
+	CloudFSDriver string
+	VerboseLog    bool
+
+	HomeDir string
+	UID     uint32 // Mount UID
+	GID     uint32 // Mount GID
+}
+
+// New create a New cloudmount core
+func New() *Core {
+	return &Core{Drivers: map[string]DriverFactory{}}
+}
+
+func (c *Core) Init() {
+	// TODO: friendly panics
+	usr, err := user.Current()
+	if err != nil {
+		panic(err)
+	}
+
+	uid, err := strconv.Atoi(usr.Uid)
+	if err != nil {
+		panic(err)
+	}
+	gid, err := strconv.Atoi(usr.Uid)
+	if err != nil {
+		panic(gid)
+	}
+
+	// Defaults
+	c.Config = Config{
+		HomeDir:    filepath.Join(usr.HomeDir, ".cloudmount"),
+		UID:        uint32(uid),
+		GID:        uint32(gid),
+		VerboseLog: false,
+		Daemonize:  false,
+	}
+
+}
+
+func (c *Core) ParseFlags() {
+	var mountoptsFlag string
+
+	flag.StringVar(&c.Config.CloudFSDriver, "t", "gdrive", "which cloud service to use [gdrive]")
+	flag.BoolVar(&c.Config.Daemonize, "d", false, "Run app in background")
+	flag.BoolVar(&c.Config.VerboseLog, "v", false, "Verbose log")
+	flag.StringVar(&c.Config.HomeDir, "h", c.Config.HomeDir, "Path that holds configurations")
+
+	flag.StringVar(&mountoptsFlag, "o", "", "-o [opts]  uid,gid")
+
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, "Usage: %s [options] MOUNTPOINT\n\n", os.Args[0])
+		fmt.Fprintf(os.Stderr, "Options:\n")
+		flag.PrintDefaults()
+		fmt.Fprintf(os.Stderr, "\n")
+	}
+	flag.Parse()
+
+	if len(flag.Args()) < 1 {
+		flag.Usage()
+		//fmt.Println("Usage:\n gdrivemount [-d] [-v] MOUNTPOINT")
+		return
+	}
+	/////////////////////////////////////
+	// Parse mount opts
+	/////////////////
+	pmountopts := strings.Split(mountoptsFlag, ",")
+	mountopts := map[string]string{}
+	for _, v := range pmountopts {
+		keypart := strings.Split(v, "=")
+		if len(keypart) != 2 {
+			continue
+		}
+		mountopts[keypart[0]] = keypart[1]
+	}
+
+	/////////////////////////////////////
+	// Use mount opts
+	///////////////
+	uidStr, ok := mountopts["uid"]
+	if ok {
+		uid, err := strconv.Atoi(uidStr)
+		if err != nil {
+			panic(err)
+		}
+		c.Config.UID = uint32(uid)
+	}
+}
+
+func (c *Core) Start() {
+
+	cloudfs, ok := c.Drivers[c.Config.CloudFSDriver]
+	if !ok {
+		log.Fatal("CloudFS not supported")
+	}
+	driveFS := cloudfs() // Constructor?
+
+	// Start driveFS somehow
+
+	//////////////
+	// Server
+	/////////
+	ctx := context.Background()
+	server := fuseutil.NewFileSystemServer(driveFS)
+	mountPath := flag.Arg(0)
+
+	var err error
+	var mfs *fuse.MountedFileSystem
+
+	if c.Config.VerboseLog {
+		mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{DebugLogger: prettylog.New("fuse"), ErrorLogger: prettylog.New("fuse-err")})
+	} else {
+		mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{})
+	}
+	if err != nil {
+		log.Fatal("Failed mounting path", flag.Arg(0))
+	}
+
+	// Signal handling to refresh Drives
+	sigs := make(chan os.Signal, 2)
+	signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGHUP, syscall.SIGINT, os.Interrupt, syscall.SIGTERM)
+	go func() {
+		for sig := range sigs {
+			log.Println("Signal:", sig)
+			switch sig {
+			case syscall.SIGUSR1:
+				log.Println("Manually Refresh drive")
+				go driveFS.Refresh()
+			case syscall.SIGHUP:
+				log.Println("GC")
+				mem := runtime.MemStats{}
+				runtime.ReadMemStats(&mem)
+				log.Printf("Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
+				runtime.GC()
+
+				runtime.ReadMemStats(&mem)
+				log.Printf("After gc: Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
+
+			case os.Interrupt:
+				log.Println("Graceful unmount")
+				fuse.Unmount(mountPath)
+				os.Exit(1)
+			case syscall.SIGTERM:
+				log.Println("Graceful unmount")
+				fuse.Unmount(mountPath)
+				os.Exit(1)
+			}
+
+		}
+	}()
+
+	if err := mfs.Join(ctx); err != nil {
+		log.Fatalf("Joining: %v", err)
+	}
+
+}

+ 1 - 0
core/driver.go

@@ -5,6 +5,7 @@ import "github.com/jacobsa/fuse/fuseutil"
 // Base Driver
 type Driver interface {
 	fuseutil.FileSystem
+	Init()
 	Refresh()
 }
 

+ 0 - 42
core/core.go

@@ -1,42 +0,0 @@
-package core
-
-import (
-	"os/user"
-	"path/filepath"
-	"strconv"
-)
-
-var (
-	Drivers = map[string]DriverFactory{}
-	Config  ConfigData
-)
-
-type ConfigData struct {
-	WorkDir string
-	UID     uint32 // Mount UID
-	GID     uint32 // Mount GID
-}
-
-// TODO Friendly panics
-func init() {
-	usr, err := user.Current()
-	if err != nil {
-		panic(err)
-	}
-
-	uid, err := strconv.Atoi(usr.Uid)
-	if err != nil {
-		panic(err)
-	}
-	gid, err := strconv.Atoi(usr.Uid)
-	if err != nil {
-		panic(gid)
-	}
-
-	Config = ConfigData{
-		WorkDir: filepath.Join(usr.HomeDir, ".cloudmount"),
-		UID:     uint32(uid),
-		GID:     uint32(gid),
-	}
-
-}

+ 13 - 15
fs/gdrivefs/client.go

@@ -10,31 +10,29 @@ import (
 	"os"
 	"path/filepath"
 
-	"dev.hexasoftware.com/hxs/cloudmount/core"
-
 	drive "google.golang.org/api/drive/v3"
 
 	"golang.org/x/oauth2"
 	"golang.org/x/oauth2/google"
 )
 
-func getClient(ctx context.Context, config *oauth2.Config) *http.Client {
-	cacheFile, err := tokenCacheFile()
+func (d *GDriveDriver) getClient(ctx context.Context, config *oauth2.Config) *http.Client {
+	cacheFile, err := d.tokenCacheFile()
 	if err != nil {
 		log.Fatalf("Unable to get path to cached credential file. %v", err)
 	}
 
-	tok, err := tokenFromFile(cacheFile)
+	tok, err := d.tokenFromFile(cacheFile)
 	if err != nil {
-		tok = getTokenFromWeb(config)
-		saveToken(cacheFile, tok)
+		tok = d.getTokenFromWeb(config)
+		d.saveToken(cacheFile, tok)
 	}
 	return config.Client(ctx, tok)
 
 }
 
-func tokenCacheFile() (string, error) {
-	tokenCacheDir := core.Config.WorkDir
+func (d *GDriveDriver) tokenCacheFile() (string, error) {
+	tokenCacheDir := d.core.Config.HomeDir
 
 	err := os.MkdirAll(tokenCacheDir, 0700)
 
@@ -42,7 +40,7 @@ func tokenCacheFile() (string, error) {
 
 }
 
-func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
+func (d *GDriveDriver) getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
 	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
 
 	fmt.Printf(
@@ -66,7 +64,7 @@ type the authorization code: `, authURL)
 	return tok
 }
 
-func tokenFromFile(file string) (*oauth2.Token, error) {
+func (d *GDriveDriver) tokenFromFile(file string) (*oauth2.Token, error) {
 	f, err := os.Open(file)
 	if err != nil {
 		return nil, err
@@ -78,7 +76,7 @@ func tokenFromFile(file string) (*oauth2.Token, error) {
 	return t, err
 }
 
-func saveToken(file string, token *oauth2.Token) {
+func (d *GDriveDriver) saveToken(file string, token *oauth2.Token) {
 	log.Printf("Saving credential file to: %s\n", file)
 	f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
 	if err != nil {
@@ -99,9 +97,9 @@ func saveToken(file string, token *oauth2.Token) {
 	return configDir, nil
 }*/
 
-func GetDriveService() *drive.Service {
+func (d *GDriveDriver) GetDriveService() *drive.Service {
 
-	configPath := core.Config.WorkDir
+	configPath := d.core.Config.HomeDir
 
 	ctx := context.Background()
 
@@ -115,7 +113,7 @@ func GetDriveService() *drive.Service {
 		log.Fatalf("Unable to parse client secret file: %v", err)
 	}
 
-	client := getClient(ctx, config)
+	client := d.getClient(ctx, config)
 	srv, err := drive.New(client)
 	if err != nil {
 		log.Fatalf("Unable to retrieve drive Client: %v", err)

+ 3 - 13
fs/gdrivefs/fileentry.go

@@ -10,8 +10,6 @@ import (
 	"strings"
 	"time"
 
-	"dev.hexasoftware.com/hxs/cloudmount/core"
-
 	"github.com/jacobsa/fuse/fuseops"
 	drive "google.golang.org/api/drive/v3"
 )
@@ -19,7 +17,7 @@ import (
 //FileEntry entry to handle files
 type FileEntry struct {
 	//parent *FileEntry
-	fs    *GDriveFS   // GDrive FS
+	fs    *FuseHandler
 	GFile *drive.File // GDrive file
 	isDir bool        // Is dir
 	Name  string      // local name
@@ -33,14 +31,6 @@ type FileEntry struct {
 	children []*FileEntry // children
 }
 
-func NewFileEntry(fs *GDriveFS) *FileEntry {
-	return &FileEntry{
-		fs:       fs,
-		children: []*FileEntry{},
-		Attr:     fuseops.InodeAttributes{},
-	}
-}
-
 func (fe *FileEntry) AddChild(child *FileEntry) {
 	//child.parent = fe // is this needed at all?
 	// Solve name here?
@@ -80,8 +70,8 @@ func (fe *FileEntry) SetGFile(f *drive.File) {
 	attr.Size = uint64(f.Size)
 	//attr.Size = uint64(f.QuotaBytesUsed)
 	// Temp
-	attr.Uid = core.Config.UID
-	attr.Gid = core.Config.GID
+	attr.Uid = fe.core.Config.UID
+	attr.Gid = fe.core.Config.GID
 	attr.Crtime, _ = time.Parse(time.RFC3339, f.CreatedTime)
 	attr.Ctime = attr.Crtime // Set CTime to created, although it is change inode metadata
 	attr.Mtime, _ = time.Parse(time.RFC3339, f.ModifiedTime)

+ 39 - 40
fs/gdrivefs/gdrive-fuse.go

@@ -8,7 +8,7 @@ import (
 	"syscall"
 	"time"
 
-	"dev.hexasoftware.com/hxs/cloudmount/core"
+	"dev.hexasoftware.com/hxs/cloudmount/cloudfs"
 	"dev.hexasoftware.com/hxs/prettylog"
 
 	"golang.org/x/net/context"
@@ -21,10 +21,6 @@ import (
 	"github.com/jacobsa/fuse/fuseutil"
 )
 
-func init() {
-	core.Drivers["gdrive"] = NewGDriveFS
-}
-
 var (
 	log = prettylog.New("gdrivemount")
 )
@@ -42,8 +38,8 @@ type fileHandle struct {
 	file *FileEntry
 }*/
 
-// GDriveFS handler
-type GDriveFS struct {
+// FuseHndler handler
+type FuseHandler struct {
 	fuseutil.NotImplementedFileSystem // Defaults
 	srv                               *drive.Service
 
@@ -57,16 +53,10 @@ type GDriveFS struct {
 	// Map IDS with FileEntries
 }
 
-func NewGDriveFS() core.Driver {
-
-	osuser, err := user.Current()
-	if err != nil {
-		log.Fatalf("Unable to fetch current user:", err)
-	}
+func NewFuseHandler() *FuseHandler {
 
-	fs := &GDriveFS{}
-	fs.osuser = osuser
-	fs.srv = GetDriveService()
+	fs := &FuseHandler{}
+	fs.srv = GetDriveClient()
 	fs.root = &FileEntry{
 		fs: fs,
 		Attr: fuseops.InodeAttributes{
@@ -94,11 +84,20 @@ func NewGDriveFS() core.Driver {
 	return fs
 }
 
+func (fs *FuseHandler) NewFileEntry() *FileEntry {
+	return &FileEntry{
+		fs:       fs,
+		children: []*FileEntry{},
+		Attr:     fuseops.InodeAttributes{},
+	}
+
+}
+
 ////////////////////////////////////////////////////////
 // TOOLS & HELPERS
 ////////////////////////////////////////////////////////
 
-func (fs *GDriveFS) createHandle() *fileHandle {
+func (fs *FuseHandler) createHandle() *fileHandle {
 	// Lock here instead
 
 	var handle fuseops.HandleID
@@ -117,16 +116,16 @@ func (fs *GDriveFS) createHandle() *fileHandle {
 }
 
 // Cache somewhere?
-/*func (fs *GDriveFS) getUID() uint32 {
+/*func (fs *FuseHandler) getUID() uint32 {
 	uid, _ := strconv.Atoi(fs.osuser.Uid)
 	return uint32(uid)
 }
-func (fs *GDriveFS) getGID() uint32 {
+func (fs *FuseHandler) getGID() uint32 {
 	gid, _ := strconv.Atoi(fs.osuser.Gid)
 	return uint32(gid)
 }*/
 
-func (fs *GDriveFS) timedRefresh() {
+func (fs *FuseHandler) timedRefresh() {
 
 	go func() {
 		for {
@@ -140,7 +139,7 @@ func (fs *GDriveFS) timedRefresh() {
 }
 
 // Refresh service files
-func (fs *GDriveFS) Refresh() {
+func (fs *FuseHandler) Refresh() {
 	fs.nextRefresh = time.Now().Add(1 * time.Minute)
 
 	fileList := []*drive.File{}
@@ -244,7 +243,7 @@ func (fs *GDriveFS) Refresh() {
 }
 
 // OpenDir return nil error allows open dir
-func (fs *GDriveFS) OpenDir(ctx context.Context, op *fuseops.OpenDirOp) (err error) {
+func (fs *FuseHandler) OpenDir(ctx context.Context, op *fuseops.OpenDirOp) (err error) {
 
 	entry := fs.root.FindByInode(op.Inode, true)
 	if entry == nil {
@@ -259,7 +258,7 @@ func (fs *GDriveFS) OpenDir(ctx context.Context, op *fuseops.OpenDirOp) (err err
 }
 
 // ReadDir lists files into readdirop
-func (fs *GDriveFS) ReadDir(ctx context.Context, op *fuseops.ReadDirOp) (err error) {
+func (fs *FuseHandler) ReadDir(ctx context.Context, op *fuseops.ReadDirOp) (err error) {
 	fh, ok := fs.fileHandles[op.Handle]
 	if !ok {
 		log.Fatal("Handle does not exists")
@@ -303,7 +302,7 @@ func (fs *GDriveFS) ReadDir(ctx context.Context, op *fuseops.ReadDirOp) (err err
 }
 
 // SetInodeAttributes Not sure what attributes gdrive support we just leave this blank for now
-func (fs *GDriveFS) SetInodeAttributes(ctx context.Context, op *fuseops.SetInodeAttributesOp) (err error) {
+func (fs *FuseHandler) SetInodeAttributes(ctx context.Context, op *fuseops.SetInodeAttributesOp) (err error) {
 
 	// Hack to truncate file?
 
@@ -326,7 +325,7 @@ func (fs *GDriveFS) SetInodeAttributes(ctx context.Context, op *fuseops.SetInode
 }
 
 //GetInodeAttributes return attributes
-func (fs *GDriveFS) GetInodeAttributes(ctx context.Context, op *fuseops.GetInodeAttributesOp) (err error) {
+func (fs *FuseHandler) GetInodeAttributes(ctx context.Context, op *fuseops.GetInodeAttributesOp) (err error) {
 
 	f := fs.root.FindByInode(op.Inode, true)
 	if f == nil {
@@ -339,13 +338,13 @@ func (fs *GDriveFS) GetInodeAttributes(ctx context.Context, op *fuseops.GetInode
 }
 
 // ReleaseDirHandle deletes file handle entry
-func (fs *GDriveFS) ReleaseDirHandle(ctx context.Context, op *fuseops.ReleaseDirHandleOp) (err error) {
+func (fs *FuseHandler) ReleaseDirHandle(ctx context.Context, op *fuseops.ReleaseDirHandleOp) (err error) {
 	delete(fs.fileHandles, op.Handle)
 	return
 }
 
 // LookUpInode based on Parent and Name we return a self cached inode
-func (fs *GDriveFS) LookUpInode(ctx context.Context, op *fuseops.LookUpInodeOp) (err error) {
+func (fs *FuseHandler) LookUpInode(ctx context.Context, op *fuseops.LookUpInodeOp) (err error) {
 
 	parentFile := fs.root.FindByInode(op.Parent, true) // true means transverse all
 	if parentFile == nil {
@@ -369,17 +368,17 @@ func (fs *GDriveFS) LookUpInode(ctx context.Context, op *fuseops.LookUpInodeOp)
 }
 
 // StatFS basically allows StatFS to run
-/*func (fs *GDriveFS) StatFS(ctx context.Context, op *fuseops.StatFSOp) (err error) {
+/*func (fs *FuseHandler) StatFS(ctx context.Context, op *fuseops.StatFSOp) (err error) {
 	return
 }*/
 
 // ForgetInode allows to forgetInode
-func (fs *GDriveFS) ForgetInode(ctx context.Context, op *fuseops.ForgetInodeOp) (err error) {
+func (fs *FuseHandler) ForgetInode(ctx context.Context, op *fuseops.ForgetInodeOp) (err error) {
 	return
 }
 
 // GetXAttr special attributes
-func (fs *GDriveFS) GetXAttr(ctx context.Context, op *fuseops.GetXattrOp) (err error) {
+func (fs *FuseHandler) GetXAttr(ctx context.Context, op *fuseops.GetXattrOp) (err error) {
 	return
 }
 
@@ -388,7 +387,7 @@ func (fs *GDriveFS) GetXAttr(ctx context.Context, op *fuseops.GetXattrOp) (err e
 //////////////////////////////////////////////////////////////////////////
 
 // OpenFile creates a temporary handle to be handled on read or write
-func (fs *GDriveFS) OpenFile(ctx context.Context, op *fuseops.OpenFileOp) (err error) {
+func (fs *FuseHandler) OpenFile(ctx context.Context, op *fuseops.OpenFileOp) (err error) {
 	f := fs.root.FindByInode(op.Inode, true) // might not exists
 
 	// Generate new handle
@@ -402,7 +401,7 @@ func (fs *GDriveFS) OpenFile(ctx context.Context, op *fuseops.OpenFileOp) (err e
 }
 
 // ReadFile  if the first time we download the google drive file into a local temporary file
-func (fs *GDriveFS) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) (err error) {
+func (fs *FuseHandler) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) (err error) {
 	lf := fs.fileHandles[op.Handle]
 
 	localFile := lf.entry.Cache()
@@ -415,7 +414,7 @@ func (fs *GDriveFS) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) (err e
 }
 
 // CreateFile creates empty file in google Drive and returns its ID and attributes, only allows file creation on 'My Drive'
-func (fs *GDriveFS) CreateFile(ctx context.Context, op *fuseops.CreateFileOp) (err error) {
+func (fs *FuseHandler) CreateFile(ctx context.Context, op *fuseops.CreateFileOp) (err error) {
 
 	parentFile := fs.root.FindByInode(op.Parent, true)
 	if parentFile == nil {
@@ -476,7 +475,7 @@ func (fs *GDriveFS) CreateFile(ctx context.Context, op *fuseops.CreateFileOp) (e
 
 // WriteFile as ReadFile it creates a temporary file on first read
 // Maybe the ReadFile should be called here aswell to cache current contents since we are using writeAt
-func (fs *GDriveFS) WriteFile(ctx context.Context, op *fuseops.WriteFileOp) (err error) {
+func (fs *FuseHandler) WriteFile(ctx context.Context, op *fuseops.WriteFileOp) (err error) {
 	lf, ok := fs.fileHandles[op.Handle]
 	if !ok {
 		return fuse.EIO
@@ -498,7 +497,7 @@ func (fs *GDriveFS) WriteFile(ctx context.Context, op *fuseops.WriteFileOp) (err
 }
 
 // FlushFile just returns no error, maybe upload should be handled here
-func (fs *GDriveFS) FlushFile(ctx context.Context, op *fuseops.FlushFileOp) (err error) {
+func (fs *FuseHandler) FlushFile(ctx context.Context, op *fuseops.FlushFileOp) (err error) {
 	lf, ok := fs.fileHandles[op.Handle]
 	if !ok {
 		return fuse.EIO
@@ -517,7 +516,7 @@ func (fs *GDriveFS) FlushFile(ctx context.Context, op *fuseops.FlushFileOp) (err
 }
 
 // ReleaseFileHandle closes and deletes any temporary files, upload in case if changed locally
-func (fs *GDriveFS) ReleaseFileHandle(ctx context.Context, op *fuseops.ReleaseFileHandleOp) (err error) {
+func (fs *FuseHandler) ReleaseFileHandle(ctx context.Context, op *fuseops.ReleaseFileHandleOp) (err error) {
 	lf := fs.fileHandles[op.Handle]
 
 	/*if lf.uploadOnDone {
@@ -533,7 +532,7 @@ func (fs *GDriveFS) ReleaseFileHandle(ctx context.Context, op *fuseops.ReleaseFi
 }
 
 // Unlink remove file and remove from local cache entry
-func (fs *GDriveFS) Unlink(ctx context.Context, op *fuseops.UnlinkOp) (err error) {
+func (fs *FuseHandler) Unlink(ctx context.Context, op *fuseops.UnlinkOp) (err error) {
 	parentEntry := fs.root.FindByInode(op.Parent, true)
 	if parentEntry == nil {
 		return fuse.ENOENT
@@ -557,7 +556,7 @@ func (fs *GDriveFS) Unlink(ctx context.Context, op *fuseops.UnlinkOp) (err error
 }
 
 // MkDir creates a directory on a parent dir
-func (fs *GDriveFS) MkDir(ctx context.Context, op *fuseops.MkDirOp) (err error) {
+func (fs *FuseHandler) MkDir(ctx context.Context, op *fuseops.MkDirOp) (err error) {
 
 	parentFile := fs.root.FindByInode(op.Parent, true)
 	if parentFile == nil {
@@ -592,7 +591,7 @@ func (fs *GDriveFS) MkDir(ctx context.Context, op *fuseops.MkDirOp) (err error)
 }
 
 // RmDir fuse implementation
-func (fs *GDriveFS) RmDir(ctx context.Context, op *fuseops.RmDirOp) (err error) {
+func (fs *FuseHandler) RmDir(ctx context.Context, op *fuseops.RmDirOp) (err error) {
 
 	parentFile := fs.root.FindByInode(op.Parent, true)
 	if parentFile == nil {
@@ -617,7 +616,7 @@ func (fs *GDriveFS) RmDir(ctx context.Context, op *fuseops.RmDirOp) (err error)
 }
 
 // Rename fuse implementation
-func (fs *GDriveFS) Rename(ctx context.Context, op *fuseops.RenameOp) (err error) {
+func (fs *FuseHandler) Rename(ctx context.Context, op *fuseops.RenameOp) (err error) {
 	oldParentFile := fs.root.FindByInode(op.OldParent, true)
 	if oldParentFile == nil {
 		return fuse.ENOENT

+ 17 - 0
fs/gdrivefs/gdrivefs.go

@@ -0,0 +1,17 @@
+package gdrivefs
+
+import "dev.hexasoftware.com/hxs/cloudmount/cloudfs"
+
+// Driver for gdrive
+type GDriveDriver struct {
+	core *core.Core
+}
+
+func (d *GDriveDriver) Init(core *core.Core) {
+	d.core = core
+
+}
+
+func (d *GDriveDriver) Start() {
+
+}

+ 0 - 11
fs/gdrivefs/service.go

@@ -1,11 +0,0 @@
-package gdrivefs
-
-import "github.com/jacobsa/fuse/fuseutil"
-
-// Driver for gdrive
-type GDriveDriver interface {
-	Fuse() fuseutil.FileSystem // Fetch the file system
-}
-
-type gdriveService struct {
-}

+ 12 - 114
main.go

@@ -5,21 +5,12 @@ package main
 //go:generate go run cmd/genversion/main.go -package main -out version.go
 
 import (
-	"context"
-	"flag"
 	"fmt"
 	"os"
-	"strconv"
-	"strings"
 
 	"os/exec"
-	"os/signal"
-	"runtime"
-	"syscall"
 
-	"dev.hexasoftware.com/hxs/cloudmount/core"
-	"github.com/jacobsa/fuse"
-	"github.com/jacobsa/fuse/fuseutil"
+	"dev.hexasoftware.com/hxs/cloudmount/cloudfs"
 
 	"dev.hexasoftware.com/hxs/prettylog"
 
@@ -33,66 +24,29 @@ var (
 )
 
 func main() {
-	var daemonizeFlag bool
-	var verboselogFlag bool
-	var clouddriveFlag string
-	var mountoptsFlag string
 
 	prettylog.Global()
 	// getClient
-	fmt.Printf("%s-%s\n\n", Name, Version)
-
-	flag.StringVar(&clouddriveFlag, "t", "gdrive", "which cloud service to use [gdrive]")
-	flag.StringVar(&mountoptsFlag, "o", "", "-o [opts]  uid,gid")
-	flag.BoolVar(&daemonizeFlag, "d", false, "Run app in background")
-	flag.BoolVar(&verboselogFlag, "v", false, "Verbose log")
-
-	flag.Usage = func() {
-		fmt.Fprintf(os.Stderr, "Usage: %s [options] MOUNTPOINT\n\n", os.Args[0])
-		fmt.Fprintf(os.Stderr, "Options:\n")
-		flag.PrintDefaults()
-		fmt.Fprintf(os.Stderr, "\n")
-	}
-	flag.Parse()
+	fmt.Printf("%s-%s\n", Name, Version)
 
-	if len(flag.Args()) < 1 {
-		flag.Usage()
-		//fmt.Println("Usage:\n gdrivemount [-d] [-v] MOUNTPOINT")
-		return
-	}
-	/////////////////////////////////////
-	// Parse mount opts
-	/////////////////
-	pmountopts := strings.Split(mountoptsFlag, ",")
-	mountopts := map[string]string{}
-	for _, v := range pmountopts {
-		keypart := strings.Split(v, "=")
-		if len(keypart) != 2 {
-			continue
-		}
-		mountopts[keypart[0]] = keypart[1]
-	}
+	core := core.New()
 
-	/////////////////////////////////////
-	// Use mount opts
-	///////////////
-	uidStr, ok := mountopts["uid"]
-	if ok {
-		uid, err := strconv.Atoi(uidStr)
-		if err != nil {
-			panic(err)
-		}
-		core.Config.UID = uint32(uid)
-	}
+	core.Drivers["gdrive"] = gdrivefs.New
+
+	core.Init()
+	// Register drivers here too
+	core.ParseFlags()
+
+	core.Start()
 
 	///////////////////////////////
 	// cloud drive Type
 	/////////////////
-	f, ok := core.Drivers[clouddriveFlag] // there can be some interaction before daemon
+	/*f, ok := core.Drivers[clouddriveFlag] // there can be some interaction before daemon
 	if !ok {
 		log.Fatal("FileSystem not supported")
 	}
-	driveFS := f()
+	driveFS := f()*/
 
 	////////////////////////////////
 	// Daemon
@@ -113,60 +67,4 @@ func main() {
 		return
 	}
 
-	//////////////
-	// Server
-	/////////
-	ctx := context.Background()
-	server := fuseutil.NewFileSystemServer(driveFS)
-	mountPath := flag.Arg(0)
-
-	var err error
-	var mfs *fuse.MountedFileSystem
-
-	if verboselogFlag {
-		mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{DebugLogger: prettylog.New("fuse"), ErrorLogger: prettylog.New("fuse-err")})
-	} else {
-		mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{})
-	}
-	if err != nil {
-		log.Fatal("Failed mounting path", flag.Arg(0))
-	}
-
-	// Signal handling to refresh Drives
-	sigs := make(chan os.Signal, 2)
-	signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGHUP, syscall.SIGINT, os.Interrupt, syscall.SIGTERM)
-	go func() {
-		for sig := range sigs {
-			log.Println("Signal:", sig)
-			switch sig {
-			case syscall.SIGUSR1:
-				log.Println("Manually Refresh drive")
-				go driveFS.Refresh()
-			case syscall.SIGHUP:
-				log.Println("GC")
-				mem := runtime.MemStats{}
-				runtime.ReadMemStats(&mem)
-				log.Printf("Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
-				runtime.GC()
-
-				runtime.ReadMemStats(&mem)
-				log.Printf("After gc: Mem: %.2fMB", float64(mem.Alloc)/1024/1024)
-
-			case os.Interrupt:
-				log.Println("Graceful unmount")
-				fuse.Unmount(mountPath)
-				os.Exit(1)
-			case syscall.SIGTERM:
-				log.Println("Graceful unmount")
-				fuse.Unmount(mountPath)
-				os.Exit(1)
-			}
-
-		}
-	}()
-
-	if err := mfs.Join(ctx); err != nil {
-		log.Fatalf("Joining: %v", err)
-	}
-
 }