From 4121203174e066736850e99b17b60b31f75800d2 Mon Sep 17 00:00:00 2001 From: Daniel Baumgarten Date: Mon, 23 Jul 2018 23:57:46 +0200 Subject: [PATCH] Automatically unmount on termination --- afs/addfs.go | 17 +++++++++++++++-- main.go | 25 +++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/afs/addfs.go b/afs/addfs.go index 222d1d4..79d5540 100644 --- a/afs/addfs.go +++ b/afs/addfs.go @@ -1,8 +1,10 @@ package afs import ( + "errors" "flag" "os" + "os/exec" "path/filepath" "regexp" "time" @@ -17,6 +19,7 @@ type AddFS struct { pathfs.FileSystem opts AddFSOpts mutableFilesRegexes []*regexp.Regexp + mountpoint string } type AddFSOpts struct { @@ -30,6 +33,7 @@ func NewAddFS(source string, opts AddFSOpts) (*AddFS, error) { pathfs.NewLoopbackFileSystem(source), opts, make([]*regexp.Regexp, len(opts.MutableFiles)), + "", } for i, v := range opts.MutableFiles { var err error @@ -41,7 +45,7 @@ func NewAddFS(source string, opts AddFSOpts) (*AddFS, error) { return fs, nil } -func (fs *AddFS) Run() error { +func (fs *AddFS) Mount(mountpoint string) error { origAbs, _ := filepath.Abs(flag.Arg(0)) mOpts := &fuse.MountOptions{ Options: []string{"default_permissions"}, @@ -57,14 +61,23 @@ func (fs *AddFS) Run() error { } pathNode := pathfs.NewPathNodeFs(fs, &pathfs.PathNodeFsOptions{}) conn := nodefs.NewFileSystemConnector(pathNode.Root(), opts) - server, err := fuse.NewServer(conn.RawFS(), flag.Arg(1), mOpts) + server, err := fuse.NewServer(conn.RawFS(), mountpoint, mOpts) if err != nil { return err } + fs.mountpoint = mountpoint server.Serve() return nil } +func (fs *AddFS) Unmount() error { + if fs.mountpoint == "" { + return errors.New("cannot unmount before successfully mounting") + } + umcmd := exec.Command("fusermount", "-u", fs.mountpoint) + return umcmd.Run() +} + func (fs *AddFS) rootUserPermit(context *fuse.Context) bool { return fs.opts.AllowRootMutation && context.Uid == 0 } diff --git a/main.go b/main.go index c67e53c..8bc8030 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" "os" + "os/signal" "syscall" "github.com/dbaumgarten/addfs/afs" @@ -21,6 +22,7 @@ Possible flags: var allowRootMutation = flag.Bool("allowRootMutation", false, "Allow the root-user to mutate files and folders") var ignoreWarnings = flag.Bool("ignoreWarnings", false, "Ignore all errors about file-ownership. ONLY USE IF YOU KNOW WHAT YOU ARE DOING!") +var keepMounted = flag.Bool("keepMounted", false, "Do not attempt to unmount on exiting") var mutableFiles arrayFlags func main() { @@ -37,7 +39,7 @@ func main() { if !*ignoreWarnings { if os.Getegid() != 0 { - fmt.Println("WARNING!: Not running. Only directories that are write-accessible for the user can be mounted. This defeats addfs' write-protection. Aborting for safety-reasons.") + fmt.Println("WARNING!: Not running as root. Only directories that are write-accessible for the user can be mounted. This defeats addfs' write-protection. Aborting for safety-reasons.") os.Exit(1) } err := checkSourceDirectory(flag.Arg(0)) @@ -56,14 +58,33 @@ func main() { fmt.Println("Error: ", err) os.Exit(1) } + + if !*keepMounted { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + go unmountOnInterrupt(afs, c) + } + fmt.Println("Starting FUSE-Filesystem!") - err = afs.Run() + err = afs.Mount(flag.Arg(1)) if err != nil { fmt.Println(err) os.Exit(1) } } +func unmountOnInterrupt(afs *afs.AddFS, c chan os.Signal) { + for _ = range c { + fmt.Println("Unmounting...") + err := afs.Unmount() + if err != nil { + fmt.Println("Error when unmounting:", err) + os.Exit(1) + } + fmt.Println("Successfully unmounted!") + } +} + func checkSourceDirectory(path string) error { stat, err := os.Stat(path) if err != nil {