ctlsock: exit early if socket cannot be created; delete on exit
Both are achieved by opening the socket from main and passing it to the ctlsock package instead of passing the path.
This commit is contained in:
parent
e1833fa26a
commit
6af725ff09
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -23,9 +24,11 @@ type argContainer struct {
|
||||||
// Configuration file name override
|
// Configuration file name override
|
||||||
config string
|
config string
|
||||||
notifypid, scryptn int
|
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.
|
// _configCustom is true when the user sets a custom config file name.
|
||||||
// This is not a CLI option.
|
|
||||||
_configCustom bool
|
_configCustom bool
|
||||||
|
// _ctlsockFd stores the control socket file descriptor (ctlsock stores the path)
|
||||||
|
_ctlsockFd net.Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
var flagSet *flag.FlagSet
|
var flagSet *flag.FlagSet
|
||||||
|
|
|
@ -46,19 +46,14 @@ type ctlSockHandler struct {
|
||||||
socket *net.UnixListener
|
socket *net.UnixListener
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateAndServe creates an unix socket at "path" and serves incoming
|
// Serve serves incoming connections on "sock". This call blocks so you
|
||||||
// connections in a new goroutine.
|
// probably want to run it in a new goroutine.
|
||||||
func CreateAndServe(path string, fs Interface) error {
|
func Serve(sock net.Listener, fs Interface) {
|
||||||
sock, err := net.Listen("unix", path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
handler := ctlSockHandler{
|
handler := ctlSockHandler{
|
||||||
fs: fs,
|
fs: fs,
|
||||||
socket: sock.(*net.UnixListener),
|
socket: sock.(*net.UnixListener),
|
||||||
}
|
}
|
||||||
go handler.acceptLoop()
|
handler.acceptLoop()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *ctlSockHandler) acceptLoop() {
|
func (ch *ctlSockHandler) acceptLoop() {
|
||||||
|
|
37
mount.go
37
mount.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -50,7 +51,28 @@ func doMount(args *argContainer) int {
|
||||||
tlog.Fatal.Printf("Invalid mountpoint: %v", err)
|
tlog.Fatal.Printf("Invalid mountpoint: %v", err)
|
||||||
os.Exit(ErrExitMountPoint)
|
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 masterkey []byte
|
||||||
var confFile *configfile.ConfFile
|
var confFile *configfile.ConfFile
|
||||||
if args.masterkey != "" {
|
if args.masterkey != "" {
|
||||||
|
@ -65,6 +87,7 @@ func doMount(args *argContainer) int {
|
||||||
masterkey = make([]byte, cryptocore.KeyLen)
|
masterkey = make([]byte, cryptocore.KeyLen)
|
||||||
} else {
|
} else {
|
||||||
// Load master key from config file
|
// Load master key from config file
|
||||||
|
// Prompts the user for the password
|
||||||
masterkey, confFile = loadConfig(args)
|
masterkey, confFile = loadConfig(args)
|
||||||
printMasterKey(masterkey)
|
printMasterKey(masterkey)
|
||||||
}
|
}
|
||||||
|
@ -177,14 +200,10 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF
|
||||||
finalFs = fs
|
finalFs = fs
|
||||||
ctlSockBackend = fs
|
ctlSockBackend = fs
|
||||||
}
|
}
|
||||||
if args.ctlsock != "" {
|
// We have opened the socket early so that we cannot fail here after
|
||||||
err := ctlsock.CreateAndServe(args.ctlsock, ctlSockBackend)
|
// asking the user for the password
|
||||||
if err != nil {
|
if args._ctlsockFd != nil {
|
||||||
// TODO if the socket cannot be created, we should exit BEFORE
|
go ctlsock.Serve(args._ctlsockFd, ctlSockBackend)
|
||||||
// asking the user for the password
|
|
||||||
tlog.Fatal.Printf("ctlsock: %v", err)
|
|
||||||
os.Exit(ErrExitMount)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}
|
pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}
|
||||||
pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts)
|
pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts)
|
||||||
|
|
Loading…
Reference in New Issue