浏览代码

Split the share module into core entries and share handlers function to prevent recursive import of user module

Toby Chui 3 年之前
父节点
当前提交
a1002242da
共有 7 个文件被更改,包括 305 次插入172 次删除
  1. 15 5
      file_system.go
  2. 22 1
      mod/filesystem/filesystem.go
  3. 60 164
      mod/share/share.go
  4. 29 0
      mod/share/shareEmulationFs.go
  5. 158 0
      mod/share/shareEntry/shareEntry.go
  6. 2 0
      mod/user/directoryHandler.go
  7. 19 2
      storage.go

+ 15 - 5
file_system.go

@@ -34,12 +34,14 @@ import (
 	module "imuslab.com/arozos/mod/modules"
 	prout "imuslab.com/arozos/mod/prouter"
 	"imuslab.com/arozos/mod/share"
+	"imuslab.com/arozos/mod/share/shareEntry"
 	storage "imuslab.com/arozos/mod/storage"
 	user "imuslab.com/arozos/mod/user"
 )
 
 var (
 	thumbRenderHandler *metadata.RenderHandler
+	shareEntryTable    *shareEntry.ShareEntryTable
 	shareManager       *share.Manager
 )
 
@@ -170,12 +172,13 @@ func FileSystemInit() {
 
 	*/
 	//Create a share manager to handle user file sharae
+	shareEntryTable = shareEntry.NewShareEntryTable(sysdb)
 	shareManager = share.NewShareManager(share.Options{
-		AuthAgent:   authAgent,
-		Database:    sysdb,
-		UserHandler: userHandler,
-		HostName:    *host_name,
-		TmpFolder:   *tmp_directory,
+		AuthAgent:       authAgent,
+		ShareEntryTable: shareEntryTable,
+		UserHandler:     userHandler,
+		HostName:        *host_name,
+		TmpFolder:       *tmp_directory,
 	})
 
 	//Share related functions
@@ -1946,6 +1949,13 @@ func system_fs_listRoot(w http.ResponseWriter, r *http.Request) {
 			} else if store.Hierarchy == "backup" {
 				//Backup drive.
 				backupRoots = append(backupRoots, store.HierarchyConfig.(hybridBackup.BackupTask).ParentUID)
+			} else if store.Hierarchy == "share" {
+				//Share emulated drive
+				var thisDevice = new(rootObject)
+				thisDevice.RootName = store.Name
+				thisDevice.RootPath = store.UUID + ":/"
+				thisDevice.rootID = store.UUID
+				roots = append(roots, thisDevice)
 			}
 		}
 

+ 22 - 1
mod/filesystem/filesystem.go

@@ -139,6 +139,24 @@ func NewFileSystemHandler(option FileSystemOption) (*FileSystemHandler, error) {
 			Filesystem:         fstype,
 			Closed:             false,
 		}, nil
+	} else if option.Filesystem == "virtual" {
+		//Virtual filesystem, use custom mapping logic to handle file access
+		if option.Hierarchy == "share" {
+			//Emulated share virtual file system. Use Share Manager structure
+			return &FileSystemHandler{
+				Name:               option.Name,
+				UUID:               option.Uuid,
+				Path:               "",
+				ReadOnly:           option.Access == "readonly",
+				Parentuid:          option.Parentuid,
+				Hierarchy:          option.Hierarchy,
+				HierarchyConfig:    nil,
+				InitiationTime:     time.Now().Unix(),
+				FilesystemDatabase: nil,
+				Filesystem:         fstype,
+				Closed:             false,
+			}, nil
+		}
 	}
 
 	return nil, errors.New("Not supported file system: " + fstype)
@@ -195,7 +213,10 @@ func (fsh *FileSystemHandler) DeleteFileRecord(realpath string) error {
 //Close an openeded File System
 func (fsh *FileSystemHandler) Close() {
 	//Close the fsh database
-	fsh.FilesystemDatabase.Close()
+	if fsh.FilesystemDatabase != nil {
+		fsh.FilesystemDatabase.Close()
+	}
+
 }
 
 //Helper function

+ 60 - 164
mod/share/share.go

@@ -18,7 +18,6 @@ import (
 	"path/filepath"
 	"strconv"
 	"strings"
-	"sync"
 	"time"
 
 	"github.com/valyala/fasttemplate"
@@ -26,61 +25,29 @@ import (
 	uuid "github.com/satori/go.uuid"
 	"imuslab.com/arozos/mod/auth"
 	"imuslab.com/arozos/mod/common"
-	"imuslab.com/arozos/mod/database"
 	filesystem "imuslab.com/arozos/mod/filesystem"
+	"imuslab.com/arozos/mod/share/shareEntry"
 	"imuslab.com/arozos/mod/user"
 )
 
 type Options struct {
-	AuthAgent   *auth.AuthAgent
-	Database    *database.Database
-	UserHandler *user.UserHandler
-	HostName    string
-	TmpFolder   string
-}
-
-type ShareOption struct {
-	UUID             string
-	FileRealPath     string
-	Owner            string
-	Accessibles      []string //Use to store username or group names if permission is groups or users
-	Permission       string   //Access permission, allow {anyone / signedin / samegroup / groups / users}
-	AllowLivePreview bool
+	AuthAgent       *auth.AuthAgent
+	UserHandler     *user.UserHandler
+	ShareEntryTable *shareEntry.ShareEntryTable
+	HostName        string
+	TmpFolder       string
 }
 
 type Manager struct {
-	fileToUrlMap *sync.Map
-	urlToFileMap *sync.Map
-	options      Options
+	options Options
 }
 
 //Create a new Share Manager
 func NewShareManager(options Options) *Manager {
-	//Create the share table if not exists
-	db := options.Database
-	db.NewTable("share")
-
-	fileToUrlMap := sync.Map{}
-	urlToFileMap := sync.Map{}
-
-	//Load the old share links
-	entries, _ := db.ListTable("share")
-	for _, keypairs := range entries {
-		shareObject := new(ShareOption)
-		json.Unmarshal(keypairs[1], &shareObject)
-		if shareObject != nil {
-			//Append this to the maps
-			fileToUrlMap.Store(shareObject.FileRealPath, shareObject)
-			urlToFileMap.Store(shareObject.UUID, shareObject)
-		}
-
-	}
 
 	//Return a new manager object
 	return &Manager{
-		options:      options,
-		fileToUrlMap: &fileToUrlMap,
-		urlToFileMap: &urlToFileMap,
+		options: options,
 	}
 }
 
@@ -88,7 +55,6 @@ func NewShareManager(options Options) *Manager {
 func (s *Manager) HandleShareAccess(w http.ResponseWriter, r *http.Request) {
 	//New download method variables
 	subpathElements := []string{}
-
 	directDownload := false
 	directServe := false
 	relpath := ""
@@ -184,10 +150,10 @@ func (s *Manager) HandleShareAccess(w http.ResponseWriter, r *http.Request) {
 	}
 
 	//Check if id exists
-	val, ok := s.urlToFileMap.Load(id)
+	val, ok := s.options.ShareEntryTable.UrlToFileMap.Load(id)
 	if ok {
 		//Parse the option structure
-		shareOption := val.(*ShareOption)
+		shareOption := val.(*shareEntry.ShareOption)
 
 		//Check for permission
 		if shareOption.Permission == "anyone" {
@@ -598,22 +564,22 @@ func (s *Manager) HandleShareCheck(w http.ResponseWriter, r *http.Request) {
 
 	type Result struct {
 		IsShared  bool
-		ShareUUID *ShareOption
+		ShareUUID *shareEntry.ShareOption
 	}
 
 	//Check if share exists
-	shareExists := s.FileIsShared(rpath)
+	shareExists := s.options.ShareEntryTable.FileIsShared(rpath)
 	if !shareExists {
 		//Share not exists
 		js, _ := json.Marshal(Result{
 			IsShared:  false,
-			ShareUUID: &ShareOption{},
+			ShareUUID: &shareEntry.ShareOption{},
 		})
 		sendJSONResponse(w, string(js))
 
 	} else {
 		//Share exists
-		thisSharedInfo := s.GetShareObjectFromRealPath(rpath)
+		thisSharedInfo := s.options.ShareEntryTable.GetShareObjectFromRealPath(rpath)
 		js, _ := json.Marshal(Result{
 			IsShared:  true,
 			ShareUUID: thisSharedInfo,
@@ -677,7 +643,7 @@ func (s *Manager) HandleEditShare(w http.ResponseWriter, r *http.Request) {
 	}
 
 	//Check if share exists
-	so := s.GetShareObjectFromUUID(uuid)
+	so := s.options.ShareEntryTable.GetShareObjectFromUUID(uuid)
 	if so == nil {
 		//This share url not exists
 		sendErrorResponse(w, "Share UUID not exists")
@@ -713,7 +679,7 @@ func (s *Manager) HandleEditShare(w http.ResponseWriter, r *http.Request) {
 		}
 
 		//Write changes to database
-		s.options.Database.Write("share", uuid, so)
+		s.options.ShareEntryTable.Database.Write("share", uuid, so)
 
 	} else if sharetype == "groups" || sharetype == "users" {
 		//Username or group is listed = ok
@@ -721,7 +687,7 @@ func (s *Manager) HandleEditShare(w http.ResponseWriter, r *http.Request) {
 		so.Accessibles = settings
 
 		//Write changes to database
-		s.options.Database.Write("share", uuid, so)
+		s.options.ShareEntryTable.Database.Write("share", uuid, so)
 	}
 
 	sendOK(w)
@@ -754,7 +720,7 @@ func (s *Manager) HandleDeleteShare(w http.ResponseWriter, r *http.Request) {
 }
 
 //Craete a new file or folder share
-func (s *Manager) CreateNewShare(userinfo *user.User, vpath string) (*ShareOption, error) {
+func (s *Manager) CreateNewShare(userinfo *user.User, vpath string) (*shareEntry.ShareOption, error) {
 	//Translate the vpath to realpath
 	rpath, err := userinfo.VirtualPathToRealPath(vpath)
 	if err != nil {
@@ -768,10 +734,10 @@ func (s *Manager) CreateNewShare(userinfo *user.User, vpath string) (*ShareOptio
 	}
 
 	//Check if the share already exists. If yes, use the previous link
-	val, ok := s.fileToUrlMap.Load(rpath)
+	val, ok := s.options.ShareEntryTable.FileToUrlMap.Load(rpath)
 	if ok {
 		//Exists. Send back the old share url
-		ShareOption := val.(*ShareOption)
+		ShareOption := val.(*shareEntry.ShareOption)
 		return ShareOption, nil
 
 	} else {
@@ -785,7 +751,7 @@ func (s *Manager) CreateNewShare(userinfo *user.User, vpath string) (*ShareOptio
 		}
 
 		//Create a share object
-		shareOption := ShareOption{
+		shareOption := shareEntry.ShareOption{
 			UUID:             shareUUID,
 			FileRealPath:     rpath,
 			Owner:            userinfo.Username,
@@ -795,95 +761,16 @@ func (s *Manager) CreateNewShare(userinfo *user.User, vpath string) (*ShareOptio
 		}
 
 		//Store results on two map to make sure O(1) Lookup time
-		s.fileToUrlMap.Store(rpath, &shareOption)
-		s.urlToFileMap.Store(shareUUID, &shareOption)
+		s.options.ShareEntryTable.FileToUrlMap.Store(rpath, &shareOption)
+		s.options.ShareEntryTable.UrlToFileMap.Store(shareUUID, &shareOption)
 
 		//Write object to database
-		s.options.Database.Write("share", shareUUID, shareOption)
+		s.options.ShareEntryTable.Database.Write("share", shareUUID, shareOption)
 
 		return &shareOption, nil
 	}
 }
 
-//Delete the share on this vpath
-func (s *Manager) DeleteShare(userinfo *user.User, vpath string) error {
-	//Translate the vpath to realpath
-	rpath, err := userinfo.VirtualPathToRealPath(vpath)
-	if err != nil {
-		return errors.New("Unable to find the file on disk")
-	}
-
-	//Check if the share already exists. If yes, use the previous link
-	val, ok := s.fileToUrlMap.Load(rpath)
-	if ok {
-		//Exists. Send back the old share url
-		uuid := val.(*ShareOption).UUID
-
-		//Remove this from the database
-		err = s.options.Database.Delete("share", uuid)
-		if err != nil {
-			return err
-		}
-
-		//Remove this form the current sync map
-		s.urlToFileMap.Delete(uuid)
-		s.fileToUrlMap.Delete(rpath)
-
-		return nil
-
-	} else {
-		//Already deleted from buffered record.
-		return nil
-	}
-
-}
-
-func (s *Manager) GetShareUUIDFromPath(rpath string) string {
-	targetShareObject := s.GetShareObjectFromRealPath(rpath)
-	if (targetShareObject) != nil {
-		return targetShareObject.UUID
-	}
-	return ""
-}
-
-func (s *Manager) GetShareObjectFromRealPath(rpath string) *ShareOption {
-	rpath = filepath.ToSlash(filepath.Clean(rpath))
-	var targetShareOption *ShareOption
-	s.fileToUrlMap.Range(func(k, v interface{}) bool {
-		filePath := k.(string)
-		shareObject := v.(*ShareOption)
-
-		if filepath.ToSlash(filepath.Clean(filePath)) == rpath {
-			targetShareOption = shareObject
-		}
-
-		return true
-	})
-
-	return targetShareOption
-}
-
-func (s *Manager) GetShareObjectFromUUID(uuid string) *ShareOption {
-	var targetShareOption *ShareOption
-	s.urlToFileMap.Range(func(k, v interface{}) bool {
-		thisUuid := k.(string)
-		shareObject := v.(*ShareOption)
-
-		if thisUuid == uuid {
-			targetShareOption = shareObject
-		}
-
-		return true
-	})
-
-	return targetShareOption
-}
-
-func (s *Manager) FileIsShared(rpath string) bool {
-	shareUUID := s.GetShareUUIDFromPath(rpath)
-	return shareUUID != ""
-}
-
 func ServePermissionDeniedPage(w http.ResponseWriter) {
 	w.WriteHeader(http.StatusForbidden)
 	pageContent := []byte("Permissioned Denied")
@@ -935,42 +822,51 @@ func validateShareModes(mode string) (bool, string, []string) {
 	return false, "", []string{}
 }
 
-func (s *Manager) RemoveShareByRealpath(rpath string) error {
-	so, ok := s.fileToUrlMap.Load(rpath)
-	if ok {
-		shareUUID := so.(*ShareOption).UUID
-		s.urlToFileMap.Delete(shareUUID)
-		s.fileToUrlMap.Delete(rpath)
-		s.options.Database.Delete("share", shareUUID)
-	} else {
-		return errors.New("Share with given realpath not exists")
-	}
-	return nil
-}
-
-func (s *Manager) RemoveShareByUUID(uuid string) error {
-	so, ok := s.urlToFileMap.Load(uuid)
-	if ok {
-		s.fileToUrlMap.Delete(so.(*ShareOption).FileRealPath)
-		s.urlToFileMap.Delete(uuid)
-		s.options.Database.Delete("share", uuid)
-	} else {
-		return errors.New("Share with given uuid not exists")
-	}
-	return nil
-}
-
 //Check and clear shares that its pointinf files no longe exists
 func (s *Manager) ValidateAndClearShares() {
 	//Iterate through all shares within the system
-	s.fileToUrlMap.Range(func(k, v interface{}) bool {
+	s.options.ShareEntryTable.FileToUrlMap.Range(func(k, v interface{}) bool {
 		thisRealPath := k.(string)
 		if !fileExists(thisRealPath) {
 			//This share source file don't exists anymore. Remove it
-			s.RemoveShareByRealpath(thisRealPath)
+			s.options.ShareEntryTable.RemoveShareByRealpath(thisRealPath)
 			log.Println("*Share* Removing share to file: " + thisRealPath + " as it no longer exists")
 		}
 		return true
 	})
 
 }
+
+func (s *Manager) DeleteShare(userinfo *user.User, vpath string) error {
+	//Translate the vpath to realpath
+	rpath, err := userinfo.VirtualPathToRealPath(vpath)
+	if err != nil {
+		return errors.New("Unable to find the file on disk")
+	}
+
+	return s.options.ShareEntryTable.DeleteShare(rpath)
+}
+
+func (s *Manager) GetShareUUIDFromPath(rpath string) string {
+	return s.options.ShareEntryTable.GetShareUUIDFromPath(rpath)
+}
+
+func (s *Manager) GetShareObjectFromRealPath(rpath string) *shareEntry.ShareOption {
+	return s.options.ShareEntryTable.GetShareObjectFromRealPath(rpath)
+}
+
+func (s *Manager) GetShareObjectFromUUID(uuid string) *shareEntry.ShareOption {
+	return s.options.ShareEntryTable.GetShareObjectFromUUID(uuid)
+}
+
+func (s *Manager) FileIsShared(rpath string) bool {
+	return s.options.ShareEntryTable.FileIsShared(rpath)
+}
+
+func (s *Manager) RemoveShareByRealpath(rpath string) error {
+	return s.RemoveShareByRealpath(rpath)
+}
+
+func (s *Manager) RemoveShareByUUID(uuid string) error {
+	return s.options.ShareEntryTable.RemoveShareByUUID(uuid)
+}

+ 29 - 0
mod/share/shareEmulationFs.go

@@ -0,0 +1,29 @@
+package share
+
+/*
+	Share Emulation File System
+
+	This script emulate the shares that a user can access as a
+	virtual file system mountable by the ArozOS File Manager
+
+*/
+
+type ShareVFS struct {
+	Browse  func(string) ([]string, error)
+	Resolve func(string) (string, error)
+}
+
+func NewShareVFSHierarchySpecificConfig() *ShareVFS {
+	return &ShareVFS{
+		Browse:  GenerateVirtualFileView,
+		Resolve: ResolveVirtualPathToShareObjectPath,
+	}
+}
+
+func ResolveVirtualPathToShareObjectPath(subpath string) (string, error) {
+	return "", nil
+}
+
+func GenerateVirtualFileView(requestedPath string) ([]string, error) {
+	return []string{}, nil
+}

+ 158 - 0
mod/share/shareEntry/shareEntry.go

@@ -0,0 +1,158 @@
+package shareEntry
+
+import (
+	"encoding/json"
+	"errors"
+	"path/filepath"
+	"sync"
+
+	"imuslab.com/arozos/mod/database"
+)
+
+/*
+	Share Entry
+
+	This module is designed to isolate the entry operatiosn with the
+	handle operations so as to reduce the complexity of recursive import
+	during development
+*/
+
+type ShareEntryTable struct {
+	FileToUrlMap *sync.Map
+	UrlToFileMap *sync.Map
+	Database     *database.Database
+}
+
+type ShareOption struct {
+	UUID             string
+	FileRealPath     string
+	Owner            string
+	Accessibles      []string //Use to store username or group names if permission is groups or users
+	Permission       string   //Access permission, allow {anyone / signedin / samegroup / groups / users}
+	AllowLivePreview bool
+}
+
+func NewShareEntryTable(db *database.Database) *ShareEntryTable {
+	//Create the share table if not exists
+	db.NewTable("share")
+
+	FileToUrlMap := sync.Map{}
+	UrlToFileMap := sync.Map{}
+
+	//Load the old share links
+	entries, _ := db.ListTable("share")
+	for _, keypairs := range entries {
+		shareObject := new(ShareOption)
+		json.Unmarshal(keypairs[1], &shareObject)
+		if shareObject != nil {
+			//Append this to the maps
+			FileToUrlMap.Store(shareObject.FileRealPath, shareObject)
+			UrlToFileMap.Store(shareObject.UUID, shareObject)
+		}
+
+	}
+
+	return &ShareEntryTable{
+		FileToUrlMap: &FileToUrlMap,
+		UrlToFileMap: &UrlToFileMap,
+		Database:     db,
+	}
+}
+
+//Delete the share on this vpath
+func (s *ShareEntryTable) DeleteShare(rpath string) error {
+	//Check if the share already exists. If yes, use the previous link
+	val, ok := s.FileToUrlMap.Load(rpath)
+	if ok {
+		//Exists. Send back the old share url
+		uuid := val.(*ShareOption).UUID
+
+		//Remove this from the database
+		err := s.Database.Delete("share", uuid)
+		if err != nil {
+			return err
+		}
+
+		//Remove this form the current sync map
+		s.UrlToFileMap.Delete(uuid)
+		s.FileToUrlMap.Delete(rpath)
+
+		return nil
+
+	} else {
+		//Already deleted from buffered record.
+		return nil
+	}
+
+}
+
+func (s *ShareEntryTable) GetShareUUIDFromPath(rpath string) string {
+	targetShareObject := s.GetShareObjectFromRealPath(rpath)
+	if (targetShareObject) != nil {
+		return targetShareObject.UUID
+	}
+	return ""
+}
+
+func (s *ShareEntryTable) GetShareObjectFromRealPath(rpath string) *ShareOption {
+	rpath = filepath.ToSlash(filepath.Clean(rpath))
+	var targetShareOption *ShareOption
+	s.FileToUrlMap.Range(func(k, v interface{}) bool {
+		filePath := k.(string)
+		shareObject := v.(*ShareOption)
+
+		if filepath.ToSlash(filepath.Clean(filePath)) == rpath {
+			targetShareOption = shareObject
+		}
+
+		return true
+	})
+
+	return targetShareOption
+}
+
+func (s *ShareEntryTable) GetShareObjectFromUUID(uuid string) *ShareOption {
+	var targetShareOption *ShareOption
+	s.UrlToFileMap.Range(func(k, v interface{}) bool {
+		thisUuid := k.(string)
+		shareObject := v.(*ShareOption)
+
+		if thisUuid == uuid {
+			targetShareOption = shareObject
+		}
+
+		return true
+	})
+
+	return targetShareOption
+}
+
+func (s *ShareEntryTable) FileIsShared(rpath string) bool {
+	shareUUID := s.GetShareUUIDFromPath(rpath)
+	return shareUUID != ""
+}
+
+func (s *ShareEntryTable) RemoveShareByRealpath(rpath string) error {
+	so, ok := s.FileToUrlMap.Load(rpath)
+	if ok {
+		shareUUID := so.(*ShareOption).UUID
+		s.UrlToFileMap.Delete(shareUUID)
+		s.FileToUrlMap.Delete(rpath)
+		s.Database.Delete("share", shareUUID)
+	} else {
+		return errors.New("Share with given realpath not exists")
+	}
+	return nil
+}
+
+func (s *ShareEntryTable) RemoveShareByUUID(uuid string) error {
+	so, ok := s.UrlToFileMap.Load(uuid)
+	if ok {
+		s.FileToUrlMap.Delete(so.(*ShareOption).FileRealPath)
+		s.UrlToFileMap.Delete(uuid)
+		s.Database.Delete("share", uuid)
+	} else {
+		return errors.New("Share with given uuid not exists")
+	}
+	return nil
+}

+ 2 - 0
mod/user/directoryHandler.go

@@ -105,6 +105,8 @@ func (u *User) VirtualPathToRealPath(vpath string) (string, error) {
 				return filepath.ToSlash(filepath.Clean(storage.Path) + "/users/" + u.Username + subpath), nil
 			} else if storage.Hierarchy == "public" {
 				return filepath.ToSlash(filepath.Clean(storage.Path) + subpath), nil
+			} else if storage.Hierarchy == "share" {
+				//return storage.HierarchyConfig.(share.ShareVFS).Resolve(subpath)
 			} else {
 				return "", errors.New("Unknown Filesystem Handler Hierarchy")
 			}

+ 19 - 2
storage.go

@@ -58,7 +58,7 @@ func LoadBaseStoragePool() error {
 	})
 
 	if err != nil {
-		log.Println("Failed to initiate user root storage directory: " + *root_directory)
+		log.Println("Failed to initiate user root storage directory: "+*root_directory, err.Error())
 		return err
 	}
 	fsHandlers = append(fsHandlers, baseHandler)
@@ -74,11 +74,28 @@ func LoadBaseStoragePool() error {
 	})
 
 	if err != nil {
-		log.Println("Failed to initiate tmp storage directory: " + *tmp_directory)
+		log.Println("Failed to initiate tmp storage directory: "+*tmp_directory, err.Error())
 		return err
 	}
 	fsHandlers = append(fsHandlers, tmpHandler)
 
+	//Load the special share folder as storage unit
+	shareHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
+		Name:       "share",
+		Uuid:       "share",
+		Path:       filepath.ToSlash(filepath.Clean(*tmp_directory)) + "/",
+		Access:     "readonly",
+		Hierarchy:  "share",
+		Automount:  false,
+		Filesystem: "virtual",
+	})
+
+	if err != nil {
+		log.Println("Failed to initiate share virtual storage directory: " + err.Error())
+		return err
+	}
+	fsHandlers = append(fsHandlers, shareHandler)
+
 	//Load all the storage config from file
 	rawConfig, err := ioutil.ReadFile(*storage_config_file)
 	if err != nil {