M7: add verbose mode for debugging
Add -v/--verbose persistent flag that prints debug info to stderr: D-Bus connection status, token plugin directory discovery, unlock method sequencing with per-method success/failure, and full cryptsetup command lines including LD_LIBRARY_PATH. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"git.wntrmute.dev/kyle/arca/internal/verbose"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,6 +13,10 @@ var rootCmd = &cobra.Command{
|
|||||||
Short: "Mount and unmount LUKS-encrypted volumes",
|
Short: "Mount and unmount LUKS-encrypted volumes",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.PersistentFlags().BoolVarP(&verbose.Enabled, "verbose", "v", false, "print debug information to stderr")
|
||||||
|
}
|
||||||
|
|
||||||
func SetVersion(v string) {
|
func SetVersion(v string) {
|
||||||
rootCmd.Version = v
|
rootCmd.Version = v
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.wntrmute.dev/kyle/arca/internal/verbose"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Open opens a LUKS device using cryptsetup with token-based unlock.
|
// Open opens a LUKS device using cryptsetup with token-based unlock.
|
||||||
@@ -12,6 +15,8 @@ func Open(devicePath, mapperName string) error {
|
|||||||
args := withTokenPluginEnv([]string{"cryptsetup", "open", devicePath, mapperName, "--token-only"})
|
args := withTokenPluginEnv([]string{"cryptsetup", "open", devicePath, mapperName, "--token-only"})
|
||||||
args = withPrivilege(args)
|
args = withPrivilege(args)
|
||||||
|
|
||||||
|
verbose.Printf("exec: %s", strings.Join(args, " "))
|
||||||
|
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
@@ -101,6 +106,7 @@ func findTokenPluginDir() string {
|
|||||||
// NixOS stable symlink — survives rebuilds.
|
// NixOS stable symlink — survives rebuilds.
|
||||||
const nixSystemPath = "/run/current-system/sw/lib/cryptsetup"
|
const nixSystemPath = "/run/current-system/sw/lib/cryptsetup"
|
||||||
if hasTokenPlugins(nixSystemPath) {
|
if hasTokenPlugins(nixSystemPath) {
|
||||||
|
verbose.Printf("token plugin dir: %s", nixSystemPath)
|
||||||
return nixSystemPath
|
return nixSystemPath
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,11 +115,13 @@ func findTokenPluginDir() string {
|
|||||||
if resolved, err := filepath.EvalSymlinks(bin); err == nil {
|
if resolved, err := filepath.EvalSymlinks(bin); err == nil {
|
||||||
dir := filepath.Join(filepath.Dir(filepath.Dir(resolved)), "lib", "cryptsetup")
|
dir := filepath.Join(filepath.Dir(filepath.Dir(resolved)), "lib", "cryptsetup")
|
||||||
if hasTokenPlugins(dir) {
|
if hasTokenPlugins(dir) {
|
||||||
|
verbose.Printf("token plugin dir (from systemd-cryptenroll): %s", dir)
|
||||||
return dir
|
return dir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verbose.Printf("no token plugin directory found")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"git.wntrmute.dev/kyle/arca/internal/verbose"
|
||||||
"github.com/godbus/dbus/v5"
|
"github.com/godbus/dbus/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ func NewClient() (*Client, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot connect to udisks2 — is the udisks2 service running? (%w)", err)
|
return nil, fmt.Errorf("cannot connect to udisks2 — is the udisks2 service running? (%w)", err)
|
||||||
}
|
}
|
||||||
|
verbose.Printf("connected to system D-Bus")
|
||||||
return &Client{conn: conn}, nil
|
return &Client{conn: conn}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"git.wntrmute.dev/kyle/arca/internal/cryptsetup"
|
"git.wntrmute.dev/kyle/arca/internal/cryptsetup"
|
||||||
"git.wntrmute.dev/kyle/arca/internal/udisks"
|
"git.wntrmute.dev/kyle/arca/internal/udisks"
|
||||||
|
"git.wntrmute.dev/kyle/arca/internal/verbose"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Result holds the outcome of a successful unlock.
|
// Result holds the outcome of a successful unlock.
|
||||||
@@ -35,12 +36,16 @@ func New(client *udisks.Client, opts Options) *Unlocker {
|
|||||||
|
|
||||||
// Unlock tries each method in order and returns the result on first success.
|
// Unlock tries each method in order and returns the result on first success.
|
||||||
func (u *Unlocker) Unlock(dev *udisks.BlockDevice, methods []string) (*Result, error) {
|
func (u *Unlocker) Unlock(dev *udisks.BlockDevice, methods []string) (*Result, error) {
|
||||||
|
verbose.Printf("unlock %s: methods %v", dev.DevicePath, methods)
|
||||||
var errs []error
|
var errs []error
|
||||||
for _, method := range methods {
|
for _, method := range methods {
|
||||||
|
verbose.Printf("trying method: %s", method)
|
||||||
res, err := u.tryMethod(dev, method)
|
res, err := u.tryMethod(dev, method)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
verbose.Printf("method %s succeeded", method)
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
verbose.Printf("method %s failed: %v", method, err)
|
||||||
errs = append(errs, fmt.Errorf("%s: %w", method, err))
|
errs = append(errs, fmt.Errorf("%s: %w", method, err))
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("all unlock methods failed for %s:\n%w", dev.DevicePath, errors.Join(errs...))
|
return nil, fmt.Errorf("all unlock methods failed for %s:\n%w", dev.DevicePath, errors.Join(errs...))
|
||||||
|
|||||||
16
internal/verbose/verbose.go
Normal file
16
internal/verbose/verbose.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package verbose
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enabled is set by the root command's --verbose flag.
|
||||||
|
var Enabled bool
|
||||||
|
|
||||||
|
// Printf prints to stderr if verbose mode is enabled.
|
||||||
|
func Printf(format string, args ...any) {
|
||||||
|
if Enabled {
|
||||||
|
fmt.Fprintf(os.Stderr, "arca: "+format+"\n", args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user