You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

86 lines
2.0 KiB

// Package systemcontrol defines the privileged system-control boundary used by
// the unprivileged management API.
package systemcontrol
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
type Controller interface {
Reboot(context.Context) error
}
// ResetButtonReader exposes the physical settings-reset button state without
// granting the unprivileged API direct GPIO access.
type ResetButtonReader interface {
ResetButtonPressed(context.Context) (bool, error)
}
type SysfsResetButton struct {
ValuePath string
ActiveLow bool
}
func (b SysfsResetButton) ResetButtonPressed(ctx context.Context) (bool, error) {
if err := ctx.Err(); err != nil {
return false, err
}
path := strings.TrimSpace(b.ValuePath)
if path == "" || !filepath.IsAbs(path) {
return false, errors.New("reset button value path is not configured")
}
content, err := os.ReadFile(path)
if err != nil {
return false, fmt.Errorf("read reset button value: %w", err)
}
value := strings.TrimSpace(string(content))
if value != "0" && value != "1" {
return false, errors.New("reset button value must be 0 or 1")
}
pressed := value == "1"
if b.ActiveLow {
pressed = !pressed
}
return pressed, nil
}
type CommandController struct {
RebootCommand string
}
func (c CommandController) Reboot(ctx context.Context) error {
command := strings.TrimSpace(c.RebootCommand)
if command == "" {
command = "/sbin/reboot"
}
if err := ctx.Err(); err != nil {
return err
}
process := exec.Command(command)
if err := process.Start(); err != nil {
return err
}
return process.Process.Release()
}
type MockController struct {
RebootError error
}
func (c MockController) Reboot(context.Context) error { return c.RebootError }
type UnavailableController struct{ Reason string }
func (c UnavailableController) Reboot(context.Context) error {
reason := strings.TrimSpace(c.Reason)
if reason == "" {
reason = "privileged system control is not configured"
}
return errors.New(reason)
}