Browse Source

Utils to parse -o options

Cleaned logging, added extra verbose flag
luis 7 years ago
parent
commit
6192c65262

+ 76 - 39
README.md

@@ -1,13 +1,29 @@
 cloudmount
 cloudmount
 =====================
 =====================
-
 Linux util to Mount cloud drives
 Linux util to Mount cloud drives
 
 
-####Usage:
+**Table of Contents**
+
+- [Installation](#installation)
+- [Usage](#usage)
+- [Example](#example)
+- [Cloud services](#cloud-services)
+  - [Google drive](#google-drive)
+  - [Dropbox](#dropbox)
+- [Signals](#signals)
+
+<a name="installation"></a>
+#### Installation
+```bash
+$ go get dev.hexasoftware.com/hxs/cloudmount
+```
+
+<a name="usage"></a>
+#### Usage
 ```bash
 ```bash
 $ cloudmount -h
 $ cloudmount -h
 
 
-cloudmount-0.3-3-gadf4880 - built: 2017-07-11 01:34:58 UTC
+cloudmount-0.4-5-gf01e8fb - built: 2017-07-17 05:09:51 UTC
 
 
 Usage: cloudmount [options] [<source>] <directory>
 Usage: cloudmount [options] [<source>] <directory>
 
 
@@ -16,35 +32,40 @@ Source: can be json/yaml configuration file usually with credentials or cloud sp
 Options:
 Options:
   -d	Run app in background
   -d	Run app in background
   -o string
   -o string
-    	uid,gid ex: -o uid=1000,gid=0 
+    	uid=1000,gid=1000,ro=false
   -r duration
   -r duration
-    	Timed cloud synchronization interval [if applied] (default 2m0s)
+    	Timed cloud synchronization interval [if applied] (default 5s)
   -t string
   -t string
     	which cloud service to use [gdrive] (default "gdrive")
     	which cloud service to use [gdrive] (default "gdrive")
   -v	Verbose log
   -v	Verbose log
+  -vv
+    	Extra Verbose log
   -w string
   -w string
-    	Work dir, path that holds configurations (default "<homedir>/.cloudmount")
-```
+    	Work dir, path that holds configurations (default "$HOME/.cloudmount")
 
 
-
-#### Example:
+```
+<a name="example"></a>
+#### Example
 ```bash
 ```bash
-$ go get dev.hexasoftware.com/hxs/cloudmount
-# will default source file to $HOME/.cloudmount/gdrive.json
-$ cloudmount MOUNTPOINT
+# will default source file to $HOME/.cloudmount/gdrive.yaml
+$ cloudmount -t gdrive /mnt/gdrive
 # or 
 # or 
-$ cloudmount gdrive.json MOUNTPOINT
-
+$ cloudmount -t dropbox dropbox.yaml /mnt/gdrive
 ```
 ```
-#### Source config:
-Configuration files/source can be written in following formats:
-* json
+
+**Source config**
+Configuration files/source can be written in following formats:   
 * yaml
 * yaml
+* json
 
 
-#### Support for:
+<a name="cloud-services"></a>
+#### Cloud services
 * Google Drive
 * Google Drive
+* Dropbox
 
 
+--------------
 
 
+<a name="google-drive"></a>
 ### Google Drive
 ### Google Drive
 
 
 Setup Google client secrets:
 Setup Google client secrets:
@@ -60,46 +81,62 @@ https://console.developers.google.com/apis/credentials
 >	5. Select the application type Other, enter the name "Drive API Quickstart", and click the Create button.
 >	5. Select the application type Other, enter the name "Drive API Quickstart", and click the Create button.
 >	6. With the result dialog, copy clientID and client secret and create json file as shown in example (this can be retrieved any time by clicking on the api key)
 >	6. With the result dialog, copy clientID and client secret and create json file as shown in example (this can be retrieved any time by clicking on the api key)
 
 
-sample *gdrive.json* config:    
-```json
-{
-  "client_secret": {
-   "client_id": "CLIENTID",
-   "client_secret": "CLIENTSECRET"
-  }
-}
-```
-or yaml format:
+sample _gdrive.yaml_ config:    
 ```yaml
 ```yaml
 client_secret:
 client_secret:
-  client_id: CLIENTID
-  client_secret: CLIENTSECRET
+  client_id: *Client ID*
+  client_secret: *Client Secret*
 ```
 ```
-
 ```bash
 ```bash
-$ cloudmount gdrive.json $HOME/mntpoint
+$ cloudmount gdrive.yaml $HOME/mntpoint
 ```
 ```
 
 
-Also it's possible to create the json/yaml file in home directory as 
-__$HOME/.cloudmount/gdrive.json__
-if &lt;source&gt; parameter is ommited it will default to this file
-
+Also it's possible to create the yaml file in home directory as 
+__$HOME/.cloudmount/gdrive.yaml__
+if &lt;source&gt; parameter is omitted it will default to this file
 
 
 cloudmount gdrivefs will retrieve an oauth2 token and save in same file
 cloudmount gdrivefs will retrieve an oauth2 token and save in same file
 
 
 
 
+<a name="dropbox"></a>
+### Dropbox
+
+Setup Dropbox client secrets:
+
+https://www.dropbox.com/developers/apps
+
+> 1. Click _Create App_ 
+> 2. Select the API, type of access, and App name 
+> 3. Use the values from _App key_ and _App secret_
+
+sample _dropbox.yaml_ file:
+```yaml
+client_secret:
+  client_id: *App Key*
+  client_secret: *App secret*
+
+```
+
+```bash
+$ cloudmount -t dropbox savedfile.yaml /mnt/point
+```
+
+On the first run a link will appear and it will request a token resuling from the link
+
+--------------------
 
 
 #### Signals
 #### Signals
 Signal | Action                                                                                               | ex
 Signal | Action                                                                                               | ex
 -------|------------------------------------------------------------------------------------------------------|-----------------
 -------|------------------------------------------------------------------------------------------------------|-----------------
-USR1   | Refreshes directory tree from file system                                                            | killall -USR1 gdrivemount
-HUP    | Perform a GC and shows memory usage <small>Works when its not running in daemon mode</small>         | killall -HUP gdrivemount
+USR1   | Refreshes directory tree from file system                                                            | killall -USR1 cloudmount
+HUP    | Perform a GC and shows memory usage <small>Works when its not running in daemon mode</small>         | killall -HUP cloudmount
 
 
 
 
 
 
 #### TODO & IDEAS:
 #### TODO & IDEAS:
 * Consider using github.com/codegangsta/cli
 * Consider using github.com/codegangsta/cli
 * Create test suit to implement new packages
 * Create test suit to implement new packages
-* GDrive: long term caching, maintain most used files locally until flush/change
+* Caching: long term caching, maintain most used files locally until flush/change
+
 
 
 
 

+ 0 - 30
SPEC.md

@@ -1,30 +0,0 @@
-
-
-
-Fuse Interface -> File container -> Service (produces File)
-
-
-Package structure
-
-
-cloudfs/ core package
-
-fs/gdrivefs  
- * Init check configuration
- * Fetch FuseHandler
-
-
-Make usage something like this:
-
-```bash
-	cloudfs source.json destfolder
-
-```
-
-
-Core should not care about flags, only config
-
-main should care about flags
-
-
-

+ 3 - 3
TODO.md

@@ -1,13 +1,13 @@
 #### TODO:   
 #### TODO:   
-* Safemode flag not needed i supose 
-* Add verbosity levels (sometimes just want to log the driver and not fuse)
 * Create test cases
 * Create test cases
-* Create and reference dropbox oauth doc
 * Remove default gdrive and determine fs by arg[0] when possible
 * Remove default gdrive and determine fs by arg[0] when possible
 	* cloudmount.gdrive will mount gdrive
 	* cloudmount.gdrive will mount gdrive
 	* cloudmount.dropbox ..
 	* cloudmount.dropbox ..
 
 
 #### Done:   
 #### Done:   
+* Create and reference dropbox oauth doc
+* Add verbosity levels (sometimes just want to log the driver and not fuse)
+* Safemode flag not needed i supose 
 * move client from fs's to service.go
 * move client from fs's to service.go
 * Sanitize error on basefs, file_container produces err, basefs produces fuse.E..
 * Sanitize error on basefs, file_container produces err, basefs produces fuse.E..
 
 

+ 26 - 32
flags.go

@@ -6,10 +6,9 @@ import (
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
-	"strconv"
-	"strings"
 
 
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
+	"dev.hexasoftware.com/hxs/cloudmount/internal/coreutil"
 )
 )
 
 
 func parseFlags(config *core.Config) (err error) {
 func parseFlags(config *core.Config) (err error) {
@@ -18,10 +17,11 @@ func parseFlags(config *core.Config) (err error) {
 	flag.StringVar(&config.Type, "t", config.Type, "which cloud service to use [gdrive]")
 	flag.StringVar(&config.Type, "t", config.Type, "which cloud service to use [gdrive]")
 	flag.BoolVar(&config.Daemonize, "d", false, "Run app in background")
 	flag.BoolVar(&config.Daemonize, "d", false, "Run app in background")
 	flag.BoolVar(&config.VerboseLog, "v", false, "Verbose log")
 	flag.BoolVar(&config.VerboseLog, "v", false, "Verbose log")
+	flag.BoolVar(&config.Verbose2Log, "vv", false, "Extra Verbose log")
 	flag.StringVar(&config.HomeDir, "w", config.HomeDir, "Work dir, path that holds configurations")
 	flag.StringVar(&config.HomeDir, "w", config.HomeDir, "Work dir, path that holds configurations")
 	flag.DurationVar(&config.RefreshTime, "r", config.RefreshTime, "Timed cloud synchronization interval [if applied]")
 	flag.DurationVar(&config.RefreshTime, "r", config.RefreshTime, "Timed cloud synchronization interval [if applied]")
 
 
-	flag.StringVar(&mountoptsFlag, "o", "", "uid,gid,safemode ex: -o uid=1000,gid=0")
+	flag.StringVar(&mountoptsFlag, "o", "", fmt.Sprintf("%v", config.Options))
 
 
 	flag.Usage = func() {
 	flag.Usage = func() {
 		fmt.Fprintf(os.Stderr, "\n")
 		fmt.Fprintf(os.Stderr, "\n")
@@ -33,6 +33,11 @@ func parseFlags(config *core.Config) (err error) {
 	}
 	}
 	flag.Parse()
 	flag.Parse()
 
 
+	fileExt := filepath.Ext(os.Args[0])
+	if fileExt != "" {
+		config.Type = fileExt[1:]
+	}
+
 	if flag.NArg() < 1 {
 	if flag.NArg() < 1 {
 		flag.Usage()
 		flag.Usage()
 		//fmt.Println("Usage:\n gdrivemount [-d] [-v] <SRC/CONFIG> <MOUNTPOINT>")
 		//fmt.Println("Usage:\n gdrivemount [-d] [-v] <SRC/CONFIG> <MOUNTPOINT>")
@@ -45,41 +50,30 @@ func parseFlags(config *core.Config) (err error) {
 		config.Source = flag.Arg(0)
 		config.Source = flag.Arg(0)
 		config.Target = flag.Arg(1)
 		config.Target = flag.Arg(1)
 	}
 	}
-	/////////////////////////////////////
-	// Parse mount opts
-	/////////////////
-	pmountopts := strings.Split(mountoptsFlag, ",")
-	mountopts := map[string]string{}
-	for _, v := range pmountopts {
-		if keyindex := strings.Index(v, "="); keyindex != -1 {
-			key := strings.TrimSpace(v[:keyindex])
-			value := strings.TrimSpace(v[keyindex+1:])
-			mountopts[key] = value
-		}
+
+	if config.Verbose2Log {
+		config.VerboseLog = true
 	}
 	}
 
 
-	/////////////////////////////////////
-	// Use mount opts
-	///////////////
-	uidStr, ok := mountopts["uid"]
-	if ok {
-		uid, err := strconv.Atoi(uidStr)
-		if err != nil {
-			panic(err)
+	// Read fs type from config file
+	sourceType := struct {
+		Type string `json:"type"`
+	}{}
+	coreutil.ParseConfig(config.Source, &sourceType)
+	if sourceType.Type != "" {
+		if config.Type != "" && sourceType.Type != config.Type {
+			log.Fatalf("ERR: service mismatch <source> specifies '%s' while flag -t is '%s'", sourceType.Type, config.Type)
 		}
 		}
-		config.UID = uint32(uid)
+		config.Type = sourceType.Type
 	}
 	}
 
 
-	gidStr, ok := mountopts["gid"]
-	if ok {
-		gid, err := strconv.Atoi(gidStr)
-		if err != nil {
-			panic(err)
-		}
-		config.GID = uint32(gid)
+	if config.Type == "" {
+		log.Fatalf("ERR: Missing -t param, unknown file system")
 	}
 	}
-	if mountopts["safemode"] == "true" {
-		config.Safemode = true
+
+	err = coreutil.ParseOptions(mountoptsFlag, &config.Options)
+	if err != nil {
+		log.Fatal("ERR: Invalid syntax parsing mount options")
 	}
 	}
 	return
 	return
 }
 }

+ 24 - 6
internal/core/config.go

@@ -1,20 +1,38 @@
 package core
 package core
 
 
-import "time"
+import (
+	"time"
+
+	"dev.hexasoftware.com/hxs/cloudmount/internal/coreutil"
+)
 
 
 // Config struct
 // Config struct
 type Config struct {
 type Config struct {
 	Daemonize   bool
 	Daemonize   bool
 	Type        string
 	Type        string
 	VerboseLog  bool
 	VerboseLog  bool
+	Verbose2Log bool
 	RefreshTime time.Duration
 	RefreshTime time.Duration
 	HomeDir     string
 	HomeDir     string
-	UID         uint32 // Mount UID
-	GID         uint32 // Mount GID
 	Target      string // should be a folder
 	Target      string // should be a folder
 	Source      string
 	Source      string
-	Safemode    bool
 
 
-	// Driver specific params:
-	Param map[string]interface{}
+	//Options map[string]string
+	Options Options
+}
+
+// Options are specified in cloudmount -o option1=1, option2=2
+type Options struct { // are Options for specific driver?
+	// Sub options
+	UID      uint32 `opt:"uid"`
+	GID      uint32 `opt:"gid"` // Mount GID
+	Readonly bool   `opt:"ro"`
+}
+
+func (o Options) String() string {
+	return coreutil.OptionString(o)
+}
+func (o Options) ToMap() map[string]string {
+	// Convert to map
+	return map[string]string{}
 }
 }

+ 39 - 16
internal/core/core.go

@@ -3,15 +3,16 @@ package core
 import (
 import (
 	"context"
 	"context"
 	"flag"
 	"flag"
+	glog "log"
 	"os"
 	"os"
 	"os/signal"
 	"os/signal"
 	"os/user"
 	"os/user"
 	"path/filepath"
 	"path/filepath"
 	"runtime"
 	"runtime"
-	"strconv"
 	"syscall"
 	"syscall"
 	"time"
 	"time"
 
 
+	"dev.hexasoftware.com/hxs/cloudmount/internal/coreutil"
 	"dev.hexasoftware.com/hxs/prettylog"
 	"dev.hexasoftware.com/hxs/prettylog"
 
 
 	"github.com/jacobsa/fuse"
 	"github.com/jacobsa/fuse"
@@ -19,7 +20,9 @@ import (
 )
 )
 
 
 var (
 var (
-	log = prettylog.New("cloudmount")
+	pname  = "cloudmount"
+	log    = prettylog.Dummy()
+	errlog = prettylog.New(pname + "-err")
 )
 )
 
 
 // Core struct
 // Core struct
@@ -39,28 +42,32 @@ func New() *Core {
 		panic(err)
 		panic(err)
 	}
 	}
 
 
-	uid, err := strconv.Atoi(usr.Uid)
+	var uid, gid uint32
+	err = coreutil.StringAssign(usr.Uid, &uid)
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)
 	}
 	}
-	gid, err := strconv.Atoi(usr.Gid)
+	err = coreutil.StringAssign(usr.Gid, &gid)
 	if err != nil {
 	if err != nil {
-		panic(gid)
+		panic(err)
 	}
 	}
 
 
 	return &Core{
 	return &Core{
 		Drivers: map[string]DriverFactory{},
 		Drivers: map[string]DriverFactory{},
 		Config: Config{
 		Config: Config{
 			Daemonize:   false,
 			Daemonize:   false,
-			Type:        "gdrive",
+			Type:        "",
 			VerboseLog:  false,
 			VerboseLog:  false,
 			RefreshTime: 5 * time.Second,
 			RefreshTime: 5 * time.Second,
 			HomeDir:     filepath.Join(usr.HomeDir, ".cloudmount"),
 			HomeDir:     filepath.Join(usr.HomeDir, ".cloudmount"),
 			Source:      filepath.Join(usr.HomeDir, ".cloudmount", "gdrive.yaml"),
 			Source:      filepath.Join(usr.HomeDir, ".cloudmount", "gdrive.yaml"),
 
 
-			Safemode: false,
-			UID:      uint32(uid),
-			GID:      uint32(gid),
+			// Defaults at least
+			Options: Options{
+				UID:      uint32(uid),
+				GID:      uint32(gid),
+				Readonly: false,
+			},
 		},
 		},
 	}
 	}
 
 
@@ -69,9 +76,13 @@ func New() *Core {
 // Init to be run after configuration
 // Init to be run after configuration
 func (c *Core) Init() (err error) {
 func (c *Core) Init() (err error) {
 
 
+	if c.Config.VerboseLog {
+		log = prettylog.New(pname)
+	}
+
 	fsFactory, ok := c.Drivers[c.Config.Type]
 	fsFactory, ok := c.Drivers[c.Config.Type]
 	if !ok {
 	if !ok {
-		log.Fatal("CloudFS not supported")
+		errlog.Fatal("CloudFS not supported")
 	}
 	}
 
 
 	c.CurrentFS = fsFactory(c) // Factory
 	c.CurrentFS = fsFactory(c) // Factory
@@ -93,13 +104,25 @@ func (c *Core) Mount() {
 	var err error
 	var err error
 	var mfs *fuse.MountedFileSystem
 	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{})
+	fsname := c.Config.Source
+
+	var dbgLogger *glog.Logger
+	var errLogger *glog.Logger
+	if c.Config.Verbose2Log { // Extra verbose
+		dbgLogger = prettylog.New("fuse")
+		errLogger = prettylog.New("fuse-err")
 	}
 	}
+
+	mfs, err = fuse.Mount(mountPath, server, &fuse.MountConfig{
+		VolumeName: "cloudmount",
+		//Options:     coreutil.OptionMap(c.Config.Options),
+		FSName:      fsname,
+		DebugLogger: dbgLogger,
+		ErrorLogger: errLogger,
+		ReadOnly:    c.Config.Options.Readonly,
+	})
 	if err != nil {
 	if err != nil {
-		log.Fatal("Failed mounting path", flag.Arg(0), err)
+		errlog.Fatal("Failed mounting path ", flag.Arg(0), err)
 	}
 	}
 
 
 	// Signal handling to refresh Drives
 	// Signal handling to refresh Drives
@@ -136,7 +159,7 @@ func (c *Core) Mount() {
 	}()
 	}()
 
 
 	if err := mfs.Join(ctx); err != nil {
 	if err := mfs.Join(ctx); err != nil {
-		log.Fatalf("Joining: %v", err)
+		errlog.Fatalf("Joining: %v", err)
 	}
 	}
 
 
 }
 }

+ 0 - 64
internal/core/util.go

@@ -1,64 +0,0 @@
-package core
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"os"
-	"strings"
-
-	"github.com/go-yaml/yaml"
-)
-
-// ParseConfig, reads yaml or json file into a struct
-func ParseConfig(srcfile string, out interface{}) (err error) {
-	if srcfile == "" {
-		return
-	}
-	f, err := os.Open(srcfile)
-	if err != nil {
-		return err
-	}
-	defer f.Close()
-
-	if strings.HasSuffix(srcfile, ".json") {
-		// Read as JSON
-		json.NewDecoder(f).Decode(out)
-		return
-	}
-	if strings.HasSuffix(srcfile, ".yaml") {
-		data, err := ioutil.ReadAll(f)
-		if err != nil {
-			return err
-		}
-		// Read as yaml
-		yaml.Unmarshal(data, out)
-	}
-	return err
-}
-
-func SaveConfig(name string, obj interface{}) (err error) {
-	var data []byte
-	if strings.HasSuffix(name, ".json") {
-		data, err = json.MarshalIndent(obj, "  ", "  ")
-		if err != nil {
-			return err
-		}
-	}
-	if strings.HasSuffix(name, ".yaml") {
-		data, err = yaml.Marshal(obj)
-		if err != nil {
-			return err
-		}
-	}
-
-	f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
-	if err != nil {
-		log.Fatalf("Unable to save config: %v\n", err)
-	}
-	defer f.Close()
-
-	f.Write(data)
-	f.Sync()
-
-	return err
-}

+ 186 - 0
internal/coreutil/util.go

@@ -0,0 +1,186 @@
+package coreutil
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"reflect"
+	"strconv"
+	"strings"
+
+	"github.com/go-yaml/yaml"
+)
+
+// ParseConfig, reads yaml or json file into a struct
+func ParseConfig(srcfile string, out interface{}) (err error) {
+	if srcfile == "" {
+		return
+	}
+	f, err := os.Open(srcfile)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	if strings.HasSuffix(srcfile, ".json") {
+		// Read as JSON
+		json.NewDecoder(f).Decode(out)
+		return
+	}
+	if strings.HasSuffix(srcfile, ".yaml") {
+		data, err := ioutil.ReadAll(f)
+		if err != nil {
+			return err
+		}
+		// Read as yaml
+		yaml.Unmarshal(data, out)
+	}
+	return err
+}
+
+func SaveConfig(name string, obj interface{}) (err error) {
+	var data []byte
+	if strings.HasSuffix(name, ".json") {
+		data, err = json.MarshalIndent(obj, "  ", "  ")
+		if err != nil {
+			return err
+		}
+	}
+	if strings.HasSuffix(name, ".yaml") {
+		data, err = yaml.Marshal(obj)
+		if err != nil {
+			return err
+		}
+	}
+
+	f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		log.Fatalf("Unable to save config: %v\n", err)
+	}
+	defer f.Close()
+
+	f.Write(data)
+	f.Sync()
+
+	return err
+}
+
+// ParseOptions parses mount options like -o uid=100,gid=100 to struct
+func ParseOptions(opt string, out interface{}) (err error) {
+	mountopts := map[string]string{}
+	parts := strings.Split(opt, ",")
+	// First Map to keyvalue
+	for _, v := range parts {
+		if keyindex := strings.Index(v, "="); keyindex != -1 { // Eq
+			key := strings.TrimSpace(v[:keyindex])
+			value := strings.TrimSpace(v[keyindex+1:])
+			mountopts[key] = value
+		} else {
+			mountopts[v] = "true"
+		}
+	}
+
+	// Assign map to object by Tag by iterating fields
+	typ := reflect.TypeOf(out).Elem() // Should be pointer
+	val := reflect.ValueOf(out).Elem()
+	for i := 0; i < typ.NumField(); i++ {
+		fieldTyp := typ.Field(i)
+		fieldVal := val.Field(i)
+		name := strings.ToLower(fieldTyp.Name)
+		if tag, ok := fieldTyp.Tag.Lookup("opt"); ok {
+			tagParts := strings.Split(tag, ",")
+			if len(tagParts) > 0 && tagParts[0] != "" {
+				name = tagParts[0]
+			}
+		}
+
+		if v, ok := mountopts[name]; ok {
+			err = StringAssign(v, fieldVal.Addr().Interface())
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return
+}
+
+// StringAssign parseString and place value in
+func StringAssign(s string, v interface{}) (err error) {
+	val := reflect.ValueOf(v).Elem()
+	switch val.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: // More values
+		parsed, err := strconv.ParseInt(s, 10, 64)
+		if err != nil {
+			return err
+		}
+		sval := reflect.ValueOf(parsed)
+		val.Set(sval.Convert(val.Type()))
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: // More values
+		parsed, err := strconv.ParseUint(s, 10, 64)
+		if err != nil {
+			return err
+		}
+		sval := reflect.ValueOf(parsed)
+		val.Set(sval.Convert(val.Type()))
+	case reflect.Bool:
+		parsed, err := strconv.ParseBool(s)
+		if err != nil {
+			return err
+		}
+		sval := reflect.ValueOf(parsed)
+		val.Set(sval)
+	}
+
+	return
+}
+
+func OptionString(o interface{}) string {
+	ret := ""
+	typ := reflect.TypeOf(o) // Should be pointer
+	val := reflect.ValueOf(o)
+	for i := 0; i < typ.NumField(); i++ {
+		fieldTyp := typ.Field(i)
+		fieldVal := val.Field(i)
+		name := strings.ToLower(fieldTyp.Name)
+		desc := ""
+		if tag, ok := fieldTyp.Tag.Lookup("opt"); ok {
+			tagParts := strings.Split(tag, ",")
+			if len(tagParts) > 0 && tagParts[0] != "" {
+				name = tagParts[0]
+			}
+			/*if len(tagParts) >= 2 {
+				desc = tagParts[1]
+			}*/
+		}
+		if i != 0 {
+			ret += ","
+		}
+		if desc != "" {
+			ret += fmt.Sprintf("%s=%v (%s)", name, fieldVal.Interface(), desc)
+		} else {
+			ret += fmt.Sprintf("%s=%v", name, fieldVal.Interface())
+		}
+	}
+
+	return ret
+}
+func OptionMap(o interface{}) map[string]string {
+	ret := map[string]string{}
+	typ := reflect.TypeOf(o) // Should be pointer
+	val := reflect.ValueOf(o)
+	for i := 0; i < typ.NumField(); i++ {
+		fieldTyp := typ.Field(i)
+		fieldVal := val.Field(i)
+		name := strings.ToLower(fieldTyp.Name)
+		if tag, ok := fieldTyp.Tag.Lookup("opt"); ok {
+			tagParts := strings.Split(tag, ",")
+			if len(tagParts) > 0 && tagParts[0] != "" {
+				name = tagParts[0]
+			}
+		}
+		ret[name] = fmt.Sprintf("%v", fieldVal.Interface())
+	}
+	return ret
+}

+ 43 - 17
internal/fs/basefs/basefs.go

@@ -4,8 +4,6 @@ package basefs
 import (
 import (
 	"errors"
 	"errors"
 	"io"
 	"io"
-	"io/ioutil"
-	glog "log"
 	"math"
 	"math"
 	"os"
 	"os"
 	"sync"
 	"sync"
@@ -27,7 +25,9 @@ import (
 const maxInodes = math.MaxUint64
 const maxInodes = math.MaxUint64
 
 
 var (
 var (
-	log = glog.New(ioutil.Discard, "", 0)
+	pname  = "basefs"
+	log    = prettylog.Dummy()
+	errlog = prettylog.New(pname + "-err")
 	// ErrNotImplemented basic Not implemented error
 	// ErrNotImplemented basic Not implemented error
 	ErrNotImplemented = errors.New("Not implemented")
 	ErrNotImplemented = errors.New("Not implemented")
 	// ErrPermission permission denied error
 	// ErrPermission permission denied error
@@ -56,8 +56,7 @@ type BaseFS struct {
 // New Creates a new BaseFS with config based on core
 // New Creates a new BaseFS with config based on core
 func New(core *core.Core) *BaseFS {
 func New(core *core.Core) *BaseFS {
 	if core.Config.VerboseLog {
 	if core.Config.VerboseLog {
-		log = prettylog.New("basefs")
-
+		log = prettylog.New(pname)
 	}
 	}
 
 
 	fs := &BaseFS{
 	fs := &BaseFS{
@@ -67,8 +66,8 @@ func New(core *core.Core) *BaseFS {
 	}
 	}
 
 
 	fs.Root = NewFileContainer(fs)
 	fs.Root = NewFileContainer(fs)
-	fs.Root.uid = core.Config.UID
-	fs.Root.gid = core.Config.GID
+	fs.Root.uid = fs.Config.Options.UID
+	fs.Root.gid = fs.Config.Options.GID
 
 
 	loadingFile := File{Name: "Loading...", ID: "0"}
 	loadingFile := File{Name: "Loading...", ID: "0"}
 	entry := fs.Root.FileEntry(&loadingFile, maxInodes) // Last inode
 	entry := fs.Root.FileEntry(&loadingFile, maxInodes) // Last inode
@@ -120,7 +119,8 @@ func (fs *BaseFS) CheckForChanges() {
 			continue
 			continue
 		}
 		}
 		if entry != nil {
 		if entry != nil {
-			entry.SetFile(c.File, fs.Config.UID, fs.Config.GID)
+			entry.SetFile(c.File, fs.Config.Options.UID, fs.Config.Options.GID)
+			//entry.SetFile(c.File)
 		} else {
 		} else {
 			//Create new one
 			//Create new one
 			fs.Root.FileEntry(c.File) // Creating new one
 			fs.Root.FileEntry(c.File) // Creating new one
@@ -181,7 +181,7 @@ func (fs *BaseFS) OpenDir(ctx context.Context, op *fuseops.OpenDirOp) (err error
 func (fs *BaseFS) ReadDir(ctx context.Context, op *fuseops.ReadDirOp) (err error) {
 func (fs *BaseFS) ReadDir(ctx context.Context, op *fuseops.ReadDirOp) (err error) {
 	fh, ok := fs.fileHandles[op.Handle]
 	fh, ok := fs.fileHandles[op.Handle]
 	if !ok {
 	if !ok {
-		log.Fatal("Handle does not exists")
+		errlog.Fatal("Handle does not exists")
 	}
 	}
 
 
 	if op.Offset == 0 { // Rebuild/rewind dir list
 	if op.Offset == 0 { // Rebuild/rewind dir list
@@ -341,13 +341,16 @@ func (fs *BaseFS) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) (err err
 // CreateFile creates empty file in google Drive and returns its ID and attributes, only allows file creation on 'My Drive'
 // CreateFile creates empty file in google Drive and returns its ID and attributes, only allows file creation on 'My Drive'
 // Cloud SPECIFIC
 // Cloud SPECIFIC
 func (fs *BaseFS) CreateFile(ctx context.Context, op *fuseops.CreateFileOp) (err error) {
 func (fs *BaseFS) CreateFile(ctx context.Context, op *fuseops.CreateFileOp) (err error) {
+	/*if fs.Config.Options.Readonly {
+		return syscall.EPERM
+	}*/
 
 
 	parentFile := fs.Root.FindByInode(op.Parent)
 	parentFile := fs.Root.FindByInode(op.Parent)
 	if parentFile == nil {
 	if parentFile == nil {
 		return fuse.ENOENT
 		return fuse.ENOENT
 	}
 	}
 	// Only write on child folders
 	// Only write on child folders
-	if fs.Config.Safemode && parentFile == fs.Root.FileEntries[fuseops.RootInodeID] {
+	if parentFile == fs.Root.FileEntries[fuseops.RootInodeID] {
 		return syscall.EPERM
 		return syscall.EPERM
 	}
 	}
 
 
@@ -385,6 +388,10 @@ func (fs *BaseFS) CreateFile(ctx context.Context, op *fuseops.CreateFileOp) (err
 // Maybe the ReadFile should be called here aswell to cache current contents since we are using writeAt
 // Maybe the ReadFile should be called here aswell to cache current contents since we are using writeAt
 // CLOUD SPECIFIC
 // CLOUD SPECIFIC
 func (fs *BaseFS) WriteFile(ctx context.Context, op *fuseops.WriteFileOp) (err error) {
 func (fs *BaseFS) WriteFile(ctx context.Context, op *fuseops.WriteFileOp) (err error) {
+	/*if fs.Config.Options.Readonly {
+		return syscall.EPERM
+	}*/
+
 	handle, ok := fs.fileHandles[op.Handle]
 	handle, ok := fs.fileHandles[op.Handle]
 	if !ok {
 	if !ok {
 		return fuse.EIO
 		return fuse.EIO
@@ -407,6 +414,10 @@ func (fs *BaseFS) WriteFile(ctx context.Context, op *fuseops.WriteFileOp) (err e
 // FlushFile just returns no error, maybe upload should be handled here
 // FlushFile just returns no error, maybe upload should be handled here
 // COMMON
 // COMMON
 func (fs *BaseFS) FlushFile(ctx context.Context, op *fuseops.FlushFileOp) (err error) {
 func (fs *BaseFS) FlushFile(ctx context.Context, op *fuseops.FlushFileOp) (err error) {
+	/*if fs.Config.Options.Readonly {
+		return syscall.EPERM
+	}*/
+
 	handle, ok := fs.fileHandles[op.Handle]
 	handle, ok := fs.fileHandles[op.Handle]
 	if !ok {
 	if !ok {
 		return fuse.EIO
 		return fuse.EIO
@@ -438,9 +449,13 @@ func (fs *BaseFS) ReleaseFileHandle(ctx context.Context, op *fuseops.ReleaseFile
 // Unlink remove file and remove from local cache entry
 // Unlink remove file and remove from local cache entry
 // SPECIFIC
 // SPECIFIC
 func (fs *BaseFS) Unlink(ctx context.Context, op *fuseops.UnlinkOp) (err error) {
 func (fs *BaseFS) Unlink(ctx context.Context, op *fuseops.UnlinkOp) (err error) {
-	if fs.Config.Safemode && op.Parent == fuseops.RootInodeID {
+	/*if fs.Config.Options.Readonly {
 		return syscall.EPERM
 		return syscall.EPERM
 	}
 	}
+
+	/*if op.Parent == fuseops.RootInodeID {
+		return syscall.EPERM
+	}*/
 	parentEntry := fs.Root.FindByInode(op.Parent)
 	parentEntry := fs.Root.FindByInode(op.Parent)
 	if parentEntry == nil {
 	if parentEntry == nil {
 		return fuse.ENOENT
 		return fuse.ENOENT
@@ -458,9 +473,13 @@ func (fs *BaseFS) Unlink(ctx context.Context, op *fuseops.UnlinkOp) (err error)
 
 
 // MkDir creates a directory on a parent dir
 // MkDir creates a directory on a parent dir
 func (fs *BaseFS) MkDir(ctx context.Context, op *fuseops.MkDirOp) (err error) {
 func (fs *BaseFS) MkDir(ctx context.Context, op *fuseops.MkDirOp) (err error) {
-	if fs.Config.Safemode && op.Parent == fuseops.RootInodeID {
+	/*if fs.Config.Options.Readonly {
 		return syscall.EPERM
 		return syscall.EPERM
-	}
+	}*/
+
+	/*if op.Parent == fuseops.RootInodeID {
+		return syscall.EPERM
+	}*/
 
 
 	parentFile := fs.Root.FindByInode(op.Parent)
 	parentFile := fs.Root.FindByInode(op.Parent)
 	if parentFile == nil {
 	if parentFile == nil {
@@ -484,9 +503,13 @@ func (fs *BaseFS) MkDir(ctx context.Context, op *fuseops.MkDirOp) (err error) {
 
 
 // RmDir fuse implementation
 // RmDir fuse implementation
 func (fs *BaseFS) RmDir(ctx context.Context, op *fuseops.RmDirOp) (err error) {
 func (fs *BaseFS) RmDir(ctx context.Context, op *fuseops.RmDirOp) (err error) {
-	if fs.Config.Safemode && op.Parent == fuseops.RootInodeID {
+	/*if fs.Config.Options.Readonly {
 		return syscall.EPERM
 		return syscall.EPERM
-	}
+	}*/
+
+	/*if op.Parent == fuseops.RootInodeID {
+		return syscall.EPERM
+	}*/
 
 
 	parentFile := fs.Root.FindByInode(op.Parent)
 	parentFile := fs.Root.FindByInode(op.Parent)
 	if parentFile == nil {
 	if parentFile == nil {
@@ -505,10 +528,13 @@ func (fs *BaseFS) RmDir(ctx context.Context, op *fuseops.RmDirOp) (err error) {
 
 
 // Rename fuse implementation
 // Rename fuse implementation
 func (fs *BaseFS) Rename(ctx context.Context, op *fuseops.RenameOp) (err error) {
 func (fs *BaseFS) Rename(ctx context.Context, op *fuseops.RenameOp) (err error) {
+	/*if fs.Config.Options.Readonly {
+		return syscall.EPERM
+	}*/
 
 
-	if fs.Config.Safemode && (op.OldParent == fuseops.RootInodeID || op.NewParent == fuseops.RootInodeID) {
+	/*if op.OldParent == fuseops.RootInodeID || op.NewParent == fuseops.RootInodeID {
 		return syscall.EPERM
 		return syscall.EPERM
-	}
+	}*/
 	oldParentEntry := fs.Root.FindByInode(op.OldParent)
 	oldParentEntry := fs.Root.FindByInode(op.OldParent)
 	if oldParentEntry == nil {
 	if oldParentEntry == nil {
 		return fuse.ENOENT
 		return fuse.ENOENT

+ 7 - 6
internal/fs/basefs/file_container.go

@@ -24,18 +24,19 @@ type FileContainer struct {
 }
 }
 
 
 func NewFileContainer(fs *BaseFS) *FileContainer {
 func NewFileContainer(fs *BaseFS) *FileContainer {
+
 	fc := &FileContainer{
 	fc := &FileContainer{
 		FileEntries: map[fuseops.InodeID]*FileEntry{},
 		FileEntries: map[fuseops.InodeID]*FileEntry{},
 		fs:          fs,
 		fs:          fs,
 		//client:  fs.Client,
 		//client:  fs.Client,
 		inodeMU: &sync.Mutex{},
 		inodeMU: &sync.Mutex{},
-		uid:     fs.Config.UID,
-		gid:     fs.Config.GID,
+		uid:     fs.Config.Options.UID,
+		gid:     fs.Config.Options.GID,
 	}
 	}
 	rootEntry := fc.FileEntry(nil, fuseops.RootInodeID)
 	rootEntry := fc.FileEntry(nil, fuseops.RootInodeID)
 	rootEntry.Attr.Mode = os.FileMode(0755) | os.ModeDir
 	rootEntry.Attr.Mode = os.FileMode(0755) | os.ModeDir
-	rootEntry.Attr.Uid = fs.Config.UID
-	rootEntry.Attr.Gid = fs.Config.GID
+	rootEntry.Attr.Uid = fc.uid
+	rootEntry.Attr.Gid = fc.gid
 
 
 	return fc
 	return fc
 }
 }
@@ -169,7 +170,6 @@ func (fc *FileContainer) FileEntry(file *File, inodeOps ...fuseops.InodeID) *Fil
 		log.Println("Filename contains invalid chars, sanitizing: '%s'-'%s'", name, newName)
 		log.Println("Filename contains invalid chars, sanitizing: '%s'-'%s'", name, newName)
 		name = newName
 		name = newName
 	}
 	}
-
 	fe := &FileEntry{
 	fe := &FileEntry{
 		Inode: inode,
 		Inode: inode,
 		Name:  name,
 		Name:  name,
@@ -177,6 +177,7 @@ func (fc *FileContainer) FileEntry(file *File, inodeOps ...fuseops.InodeID) *Fil
 	// Temp gfile?
 	// Temp gfile?
 	if file != nil {
 	if file != nil {
 		fe.SetFile(file, fc.uid, fc.gid)
 		fe.SetFile(file, fc.uid, fc.gid)
+		//fe.SetFile(file)
 	}
 	}
 	fc.FileEntries[inode] = fe
 	fc.FileEntries[inode] = fe
 
 
@@ -209,8 +210,8 @@ func (fc *FileContainer) Sync(fe *FileEntry) (err error) {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	log.Println("Uploaded file size:", upFile.Size)
 	fe.SetFile(upFile, fc.uid, fc.gid) // update local GFile entry
 	fe.SetFile(upFile, fc.uid, fc.gid) // update local GFile entry
+	//fe.SetFile(upFile) // update local GFile entry
 	return
 	return
 
 
 }
 }

+ 4 - 5
internal/fs/dropboxfs/dropboxfs.go

@@ -1,22 +1,21 @@
 package dropboxfs
 package dropboxfs
 
 
 import (
 import (
-	"io/ioutil"
-	glog "log"
-
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/fs/basefs"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/fs/basefs"
 	"dev.hexasoftware.com/hxs/prettylog"
 	"dev.hexasoftware.com/hxs/prettylog"
 )
 )
 
 
 var (
 var (
-	log = glog.New(ioutil.Discard, "", 0)
+	pname  = "dropboxfs"
+	log    = prettylog.Dummy()
+	errlog = prettylog.New(pname + "-err")
 )
 )
 
 
 // New Create basefs with Dropbox service
 // New Create basefs with Dropbox service
 func New(core *core.Core) core.DriverFS {
 func New(core *core.Core) core.DriverFS {
 	if core.Config.VerboseLog {
 	if core.Config.VerboseLog {
-		log = prettylog.New("dropboxfs")
+		log = prettylog.New(pname)
 	}
 	}
 	fs := basefs.New(core)
 	fs := basefs.New(core)
 	fs.Service = NewService(&core.Config) // DropBoxService
 	fs.Service = NewService(&core.Config) // DropBoxService

+ 4 - 3
internal/fs/dropboxfs/service.go

@@ -10,6 +10,7 @@ import (
 	"golang.org/x/oauth2"
 	"golang.org/x/oauth2"
 
 
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
+	"dev.hexasoftware.com/hxs/cloudmount/internal/coreutil"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/fs/basefs"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/fs/basefs"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/oauth2util"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/oauth2util"
 
 
@@ -29,9 +30,9 @@ func NewService(coreConfig *core.Config) *Service {
 	log.Println("Initializing dropbox service")
 	log.Println("Initializing dropbox service")
 	log.Println("Source config:", coreConfig.Source)
 	log.Println("Source config:", coreConfig.Source)
 
 
-	err := core.ParseConfig(coreConfig.Source, &serviceConfig)
+	err := coreutil.ParseConfig(coreConfig.Source, &serviceConfig)
 	if err != nil {
 	if err != nil {
-		log.Fatalf("Unable to read <source>: %v", err)
+		errlog.Fatalf("Unable to read <source>: %v", err)
 	}
 	}
 	config := &oauth2.Config{
 	config := &oauth2.Config{
 		ClientID:     serviceConfig.ClientSecret.ClientID,
 		ClientID:     serviceConfig.ClientSecret.ClientID,
@@ -46,7 +47,7 @@ func NewService(coreConfig *core.Config) *Service {
 	if serviceConfig.Auth == nil {
 	if serviceConfig.Auth == nil {
 		tok := oauth2util.GetTokenFromWeb(config)
 		tok := oauth2util.GetTokenFromWeb(config)
 		serviceConfig.Auth = tok
 		serviceConfig.Auth = tok
-		core.SaveConfig(coreConfig.Source, &serviceConfig)
+		coreutil.SaveConfig(coreConfig.Source, &serviceConfig)
 	}
 	}
 
 
 	dbconfig := dropbox.Config{Token: serviceConfig.Auth.AccessToken}
 	dbconfig := dropbox.Config{Token: serviceConfig.Auth.AccessToken}

+ 7 - 1
internal/fs/gdrivefs/gdrivefs.go

@@ -7,12 +7,18 @@ import (
 )
 )
 
 
 var (
 var (
-	log = prettylog.New("gdrivefs")
+	pname  = "gdrive"
+	log    = prettylog.Dummy()
+	errlog = prettylog.New(pname + "-err")
 )
 )
 
 
 // New new Filesystem implementation based on gdrive Service
 // New new Filesystem implementation based on gdrive Service
 func New(core *core.Core) core.DriverFS {
 func New(core *core.Core) core.DriverFS {
 
 
+	if core.Config.VerboseLog {
+		log = prettylog.New(pname)
+	}
+
 	fs := basefs.New(core)
 	fs := basefs.New(core)
 	fs.Service = NewService(&core.Config)
 	fs.Service = NewService(&core.Config)
 
 

+ 5 - 4
internal/fs/gdrivefs/service.go

@@ -9,6 +9,7 @@ import (
 	"golang.org/x/oauth2"
 	"golang.org/x/oauth2"
 
 
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/core"
+	"dev.hexasoftware.com/hxs/cloudmount/internal/coreutil"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/fs/basefs"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/fs/basefs"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/oauth2util"
 	"dev.hexasoftware.com/hxs/cloudmount/internal/oauth2util"
 
 
@@ -32,9 +33,9 @@ func NewService(coreConfig *core.Config) *Service {
 	log.Println("Initializing gdrive service")
 	log.Println("Initializing gdrive service")
 	log.Println("Source config:", coreConfig.Source)
 	log.Println("Source config:", coreConfig.Source)
 
 
-	err := core.ParseConfig(coreConfig.Source, &serviceConfig)
+	err := coreutil.ParseConfig(coreConfig.Source, &serviceConfig)
 	if err != nil {
 	if err != nil {
-		log.Fatalf("Unable to read <source>: %v", err)
+		errlog.Fatalf("Unable to read <source>: %v", err)
 	}
 	}
 	config := &oauth2.Config{
 	config := &oauth2.Config{
 		ClientID:     serviceConfig.ClientSecret.ClientID,
 		ClientID:     serviceConfig.ClientSecret.ClientID,
@@ -49,13 +50,13 @@ func NewService(coreConfig *core.Config) *Service {
 	if serviceConfig.Auth == nil {
 	if serviceConfig.Auth == nil {
 		tok := oauth2util.GetTokenFromWeb(config)
 		tok := oauth2util.GetTokenFromWeb(config)
 		serviceConfig.Auth = tok
 		serviceConfig.Auth = tok
-		core.SaveConfig(coreConfig.Source, &serviceConfig)
+		coreutil.SaveConfig(coreConfig.Source, &serviceConfig)
 	}
 	}
 
 
 	client := config.Client(oauth2.NoContext, serviceConfig.Auth)
 	client := config.Client(oauth2.NoContext, serviceConfig.Auth)
 	driveCli, err := drive.New(client)
 	driveCli, err := drive.New(client)
 	if err != nil {
 	if err != nil {
-		log.Fatalf("Unable to retrieve drive Client: %v", err)
+		errlog.Fatalf("Unable to retrieve drive Client: %v", err)
 	}
 	}
 
 
 	return &Service{client: driveCli}
 	return &Service{client: driveCli}

+ 2 - 3
main.go

@@ -7,7 +7,6 @@ package main
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"net/http"
 	"os"
 	"os"
 
 
 	"os/exec"
 	"os/exec"
@@ -25,14 +24,14 @@ var (
 
 
 func main() {
 func main() {
 	// TODO: TEMP
 	// TODO: TEMP
-	{
+	/*{
 		// Globally insecure SSL for debugging
 		// Globally insecure SSL for debugging
 		r, _ := http.NewRequest("GET", "http://localhost", nil)
 		r, _ := http.NewRequest("GET", "http://localhost", nil)
 		cli := &http.Client{}
 		cli := &http.Client{}
 		cli.Do(r)
 		cli.Do(r)
 		tr := http.DefaultTransport.(*http.Transport)
 		tr := http.DefaultTransport.(*http.Transport)
 		tr.TLSClientConfig.InsecureSkipVerify = true
 		tr.TLSClientConfig.InsecureSkipVerify = true
-	}
+	}*/
 
 
 	prettylog.Global()
 	prettylog.Global()
 
 

+ 1 - 1
vendor/github.com/jacobsa/fuse/mount_config.go

@@ -165,7 +165,7 @@ func (c *MountConfig) toMap() (opts map[string]string) {
 	// Cf. https://bugs.freedesktop.org/show_bug.cgi?id=90907
 	// Cf. https://bugs.freedesktop.org/show_bug.cgi?id=90907
 	fsname := c.FSName
 	fsname := c.FSName
 	if runtime.GOOS == "linux" && fsname == "" {
 	if runtime.GOOS == "linux" && fsname == "" {
-		fsname = "some_fuse_file_system"
+		fsname = "cloudmount"
 	}
 	}
 
 
 	// Special file system name?
 	// Special file system name?

+ 1 - 1
version.go

@@ -2,5 +2,5 @@ package main
 
 
 const (
 const (
   //Version contains version of the package
   //Version contains version of the package
-  Version = "0.4-4-g806e41c - built: 2017-07-15 21:01:58 UTC"
+  Version = "0.4-5-gf01e8fb - built: 2017-07-17 05:09:51 UTC"
 )
 )