mirror of
https://github.com/Quad4-Software/Reticulum-Go
synced 2026-08-29 23:48:44 -04:00
143 lines
3 KiB
Go
143 lines
3 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright (c) 2024-2026 Quad4.io
|
|
|
|
package sandbox
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"quad4/reticulum-go/pkg/common"
|
|
)
|
|
|
|
type extraPathKind int
|
|
|
|
const (
|
|
pathRWFile extraPathKind = iota
|
|
pathROFile
|
|
pathRWDir
|
|
pathRODir
|
|
)
|
|
|
|
type extraPath struct {
|
|
path string
|
|
kind extraPathKind
|
|
}
|
|
|
|
func isRouterProfile(cfg *common.ReticulumConfig) bool {
|
|
if cfg == nil {
|
|
return false
|
|
}
|
|
return strings.EqualFold(strings.TrimSpace(cfg.SandboxProfile), common.SandboxProfileRouter)
|
|
}
|
|
|
|
func collectExtraPaths(cfg *common.ReticulumConfig) []extraPath {
|
|
if cfg == nil {
|
|
return nil
|
|
}
|
|
seen := make(map[string]struct{})
|
|
var out []extraPath
|
|
add := func(p string, kind extraPathKind) {
|
|
p = strings.TrimSpace(p)
|
|
if p == "" || p == "." {
|
|
return
|
|
}
|
|
if !filepath.IsAbs(p) {
|
|
return
|
|
}
|
|
key := p + "\x00" + strconv.Itoa(int(kind))
|
|
if _, ok := seen[key]; ok {
|
|
return
|
|
}
|
|
seen[key] = struct{}{}
|
|
out = append(out, extraPath{path: p, kind: kind})
|
|
}
|
|
addFileOrParent := func(p string, fileKind extraPathKind, parentKind extraPathKind) {
|
|
p = strings.TrimSpace(p)
|
|
if p == "" {
|
|
return
|
|
}
|
|
add(p, fileKind)
|
|
parent := filepath.Dir(p)
|
|
if parent != "" && parent != "." && parent != "/" {
|
|
add(parent, parentKind)
|
|
}
|
|
}
|
|
|
|
if cfg.ConfigPath != "" {
|
|
add(filepath.Dir(cfg.ConfigPath), pathRWDir)
|
|
}
|
|
if cfg.LogFile != "" {
|
|
add(filepath.Dir(cfg.LogFile), pathRWDir)
|
|
}
|
|
if cfg.NetworkIdentityPath != "" {
|
|
addFileOrParent(cfg.NetworkIdentityPath, pathROFile, pathRODir)
|
|
}
|
|
if cfg.ControlAPISocket != "" {
|
|
addFileOrParent(cfg.ControlAPISocket, pathRWFile, pathRWDir)
|
|
}
|
|
|
|
for _, iface := range cfg.Interfaces {
|
|
if iface == nil {
|
|
continue
|
|
}
|
|
dev := strings.TrimSpace(iface.Device)
|
|
if dev == "" {
|
|
dev = strings.TrimSpace(iface.Address)
|
|
}
|
|
if looksLikeDevicePath(dev) {
|
|
add(dev, pathRWFile)
|
|
}
|
|
addCommandPath(iface.Command, add)
|
|
addCommandPath(iface.DiscoveryLocationCmd, add)
|
|
addCommandPath(iface.ReachableOn, add)
|
|
addFileOrParent(iface.CertFile, pathROFile, pathRODir)
|
|
addFileOrParent(iface.KeyFile, pathROFile, pathRODir)
|
|
addFileOrParent(iface.PeerKey, pathROFile, pathRODir)
|
|
}
|
|
|
|
for _, p := range cfg.SandboxExtraPaths {
|
|
p = strings.TrimSpace(p)
|
|
if p == "" {
|
|
continue
|
|
}
|
|
if before, ok := strings.CutSuffix(p, "/"); ok {
|
|
add(before, pathRWDir)
|
|
continue
|
|
}
|
|
add(p, pathRWFile)
|
|
parent := filepath.Dir(p)
|
|
if parent != "" && parent != "." && parent != "/" {
|
|
add(parent, pathRWDir)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func looksLikeDevicePath(p string) bool {
|
|
if !filepath.IsAbs(p) {
|
|
return false
|
|
}
|
|
return strings.HasPrefix(p, "/dev/") || strings.Contains(p, "/tty")
|
|
}
|
|
|
|
func addCommandPath(command string, add func(string, extraPathKind)) {
|
|
command = strings.TrimSpace(command)
|
|
if command == "" {
|
|
return
|
|
}
|
|
fields := strings.Fields(command)
|
|
if len(fields) == 0 {
|
|
return
|
|
}
|
|
bin := fields[0]
|
|
if !filepath.IsAbs(bin) {
|
|
return
|
|
}
|
|
add(bin, pathROFile)
|
|
parent := filepath.Dir(bin)
|
|
if parent != "" && parent != "." && parent != "/" {
|
|
add(parent, pathRODir)
|
|
}
|
|
}
|