diff options
| -rw-r--r-- | cli_args.go | 5 | ||||
| -rw-r--r-- | internal/ctlsock/ctlsock_serve.go | 13 | ||||
| -rw-r--r-- | mount.go | 37 | 
3 files changed, 36 insertions, 19 deletions
| diff --git a/cli_args.go b/cli_args.go index 7301d9a..4d16570 100644 --- a/cli_args.go +++ b/cli_args.go @@ -3,6 +3,7 @@ package main  import (  	"flag"  	"fmt" +	"net"  	"os"  	"strconv"  	"strings" @@ -23,9 +24,11 @@ type argContainer struct {  	// Configuration file name override  	config             string  	notifypid, scryptn int +	// Helper variables that are NOT cli options all start with an underscore  	// _configCustom is true when the user sets a custom config file name. -	// This is not a CLI option.  	_configCustom bool +	// _ctlsockFd stores the control socket file descriptor (ctlsock stores the path) +	_ctlsockFd net.Listener  }  var flagSet *flag.FlagSet diff --git a/internal/ctlsock/ctlsock_serve.go b/internal/ctlsock/ctlsock_serve.go index 63515c0..45b1e5b 100644 --- a/internal/ctlsock/ctlsock_serve.go +++ b/internal/ctlsock/ctlsock_serve.go @@ -46,19 +46,14 @@ type ctlSockHandler struct {  	socket *net.UnixListener  } -// CreateAndServe creates an unix socket at "path" and serves incoming -// connections in a new goroutine. -func CreateAndServe(path string, fs Interface) error { -	sock, err := net.Listen("unix", path) -	if err != nil { -		return err -	} +// Serve serves incoming connections on "sock". This call blocks so you +// probably want to run it in a new goroutine. +func Serve(sock net.Listener, fs Interface) {  	handler := ctlSockHandler{  		fs:     fs,  		socket: sock.(*net.UnixListener),  	} -	go handler.acceptLoop() -	return nil +	handler.acceptLoop()  }  func (ch *ctlSockHandler) acceptLoop() { @@ -4,6 +4,7 @@ import (  	"encoding/json"  	"io/ioutil"  	"log/syslog" +	"net"  	"os"  	"os/exec"  	"os/signal" @@ -50,7 +51,28 @@ func doMount(args *argContainer) int {  		tlog.Fatal.Printf("Invalid mountpoint: %v", err)  		os.Exit(ErrExitMountPoint)  	} -	// Get master key +	// Open control socket early so we can error out before asking the user +	// for the password +	if args.ctlsock != "" { +		// We must use an absolute path because we cd to / when daemonizing. +		// This messes up the delete-on-close logic in the unix socket object. +		args.ctlsock, _ = filepath.Abs(args.ctlsock) +		var sock net.Listener +		sock, err = net.Listen("unix", args.ctlsock) +		if err != nil { +			tlog.Fatal.Printf("ctlsock: %v", err) +			os.Exit(ErrExitMount) +		} +		args._ctlsockFd = sock +		// Close also deletes the socket file +		defer func() { +			err = sock.Close() +			if err != nil { +				tlog.Warn.Print(err) +			} +		}() +	} +	// Get master key (may prompt for the password)  	var masterkey []byte  	var confFile *configfile.ConfFile  	if args.masterkey != "" { @@ -65,6 +87,7 @@ func doMount(args *argContainer) int {  		masterkey = make([]byte, cryptocore.KeyLen)  	} else {  		// Load master key from config file +		// Prompts the user for the password  		masterkey, confFile = loadConfig(args)  		printMasterKey(masterkey)  	} @@ -177,14 +200,10 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF  		finalFs = fs  		ctlSockBackend = fs  	} -	if args.ctlsock != "" { -		err := ctlsock.CreateAndServe(args.ctlsock, ctlSockBackend) -		if err != nil { -			// TODO if the socket cannot be created, we should exit BEFORE -			// asking the user for the password -			tlog.Fatal.Printf("ctlsock: %v", err) -			os.Exit(ErrExitMount) -		} +	// We have opened the socket early so that we cannot fail here after +	// asking the user for the password +	if args._ctlsockFd != nil { +		go ctlsock.Serve(args._ctlsockFd, ctlSockBackend)  	}  	pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}  	pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts) | 
