Initial implementation of arca, a LUKS volume manager.
Go CLI using cobra with mount, unmount, status, and init subcommands. Unlocks via udisks2 D-Bus (passphrase/keyfile) or cryptsetup (FIDO2/TPM2) with ordered method fallback. Includes NixOS-specific LD_LIBRARY_PATH injection for systemd cryptsetup token plugins. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
100
internal/config/config.go
Normal file
100
internal/config/config.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Config holds the arca configuration.
|
||||
type Config struct {
|
||||
Devices map[string]DeviceConfig `yaml:"devices"`
|
||||
}
|
||||
|
||||
// DeviceConfig holds per-device settings.
|
||||
type DeviceConfig struct {
|
||||
UUID string `yaml:"uuid"`
|
||||
Mountpoint string `yaml:"mountpoint,omitempty"`
|
||||
Methods []string `yaml:"methods,omitempty"`
|
||||
Keyfile string `yaml:"keyfile,omitempty"`
|
||||
}
|
||||
|
||||
// ResolvedDevice holds the effective settings for a device lookup.
|
||||
type ResolvedDevice struct {
|
||||
UUID string
|
||||
Mountpoint string
|
||||
Methods []string
|
||||
Keyfile string
|
||||
}
|
||||
|
||||
// Load reads the config file. Returns an empty config if the file doesn't exist.
|
||||
func Load() *Config {
|
||||
cfg := &Config{
|
||||
Devices: make(map[string]DeviceConfig),
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(configPath())
|
||||
if err != nil {
|
||||
return cfg
|
||||
}
|
||||
|
||||
yaml.Unmarshal(data, cfg)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// ResolveDevice looks up by alias name first, then checks if the argument
|
||||
// is a device path matching a known alias (e.g. "/dev/sda1" matches "sda1").
|
||||
// If nothing matches, returns defaults for a bare device path.
|
||||
func (c *Config) ResolveDevice(nameOrPath string) ResolvedDevice {
|
||||
// Direct alias match.
|
||||
if dev, ok := c.Devices[nameOrPath]; ok {
|
||||
return resolvedFrom(dev)
|
||||
}
|
||||
|
||||
// Match device path against aliases: "/dev/sda1" matches alias "sda1".
|
||||
base := filepath.Base(nameOrPath)
|
||||
if dev, ok := c.Devices[base]; ok {
|
||||
return resolvedFrom(dev)
|
||||
}
|
||||
|
||||
return ResolvedDevice{
|
||||
Methods: []string{"passphrase"},
|
||||
}
|
||||
}
|
||||
|
||||
func resolvedFrom(dev DeviceConfig) ResolvedDevice {
|
||||
methods := dev.Methods
|
||||
if len(methods) == 0 {
|
||||
methods = []string{"passphrase"}
|
||||
}
|
||||
return ResolvedDevice{
|
||||
UUID: dev.UUID,
|
||||
Mountpoint: dev.Mountpoint,
|
||||
Methods: methods,
|
||||
Keyfile: dev.Keyfile,
|
||||
}
|
||||
}
|
||||
|
||||
// AliasFor returns the config alias for a given UUID, or "" if none.
|
||||
func (c *Config) AliasFor(uuid string) string {
|
||||
for name, dev := range c.Devices {
|
||||
if dev.UUID == uuid {
|
||||
return name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Path returns the config file path, respecting XDG_CONFIG_HOME.
|
||||
func Path() string {
|
||||
return configPath()
|
||||
}
|
||||
|
||||
func configPath() string {
|
||||
if dir := os.Getenv("XDG_CONFIG_HOME"); dir != "" {
|
||||
return filepath.Join(dir, "arca", "config.yaml")
|
||||
}
|
||||
home, _ := os.UserHomeDir()
|
||||
return filepath.Join(home, ".config", "arca", "config.yaml")
|
||||
}
|
||||
Reference in New Issue
Block a user