Restructure modules (#1572)
* Move portbase into monorepo * Add new simple module mgr * [WIP] Switch to new simple module mgr * Add StateMgr and more worker variants * [WIP] Switch more modules * [WIP] Switch more modules * [WIP] swtich more modules * [WIP] switch all SPN modules * [WIP] switch all service modules * [WIP] Convert all workers to the new module system * [WIP] add new task system to module manager * [WIP] Add second take for scheduling workers * [WIP] Add FIXME for bugs in new scheduler * [WIP] Add minor improvements to scheduler * [WIP] Add new worker scheduler * [WIP] Fix more bug related to new module system * [WIP] Fix start handing of the new module system * [WIP] Improve startup process * [WIP] Fix minor issues * [WIP] Fix missing subsystem in settings * [WIP] Initialize managers in constructor * [WIP] Move module event initialization to constrictors * [WIP] Fix setting for enabling and disabling the SPN module * [WIP] Move API registeration into module construction * [WIP] Update states mgr for all modules * [WIP] Add CmdLine operation support * Add state helper methods to module group and instance * Add notification and module status handling to status package * Fix starting issues * Remove pilot widget and update security lock to new status data * Remove debug logs * Improve http server shutdown * Add workaround for cleanly shutting down firewall+netquery * Improve logging * Add syncing states with notifications for new module system * Improve starting, stopping, shutdown; resolve FIXMEs/TODOs * [WIP] Fix most unit tests * Review new module system and fix minor issues * Push shutdown and restart events again via API * Set sleep mode via interface * Update example/template module * [WIP] Fix spn/cabin unit test * Remove deprecated UI elements * Make log output more similar for the logging transition phase * Switch spn hub and observer cmds to new module system * Fix log sources * Make worker mgr less error prone * Fix tests and minor issues * Fix observation hub * Improve shutdown and restart handling * Split up big connection.go source file * Move varint and dsd packages to structures repo * Improve expansion test * Fix linter warnings * Fix interception module on windows * Fix linter errors --------- Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
This commit is contained in:
139
base/utils/structure.go
Normal file
139
base/utils/structure.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// DirStructure represents a directory structure with permissions that should be enforced.
|
||||
type DirStructure struct {
|
||||
sync.Mutex
|
||||
|
||||
Path string
|
||||
Dir string
|
||||
Perm os.FileMode
|
||||
Parent *DirStructure
|
||||
Children map[string]*DirStructure
|
||||
}
|
||||
|
||||
// NewDirStructure returns a new DirStructure.
|
||||
func NewDirStructure(path string, perm os.FileMode) *DirStructure {
|
||||
return &DirStructure{
|
||||
Path: path,
|
||||
Perm: perm,
|
||||
Children: make(map[string]*DirStructure),
|
||||
}
|
||||
}
|
||||
|
||||
// ChildDir adds a new child DirStructure and returns it. Should the child already exist, the existing child is returned and the permissions are updated.
|
||||
func (ds *DirStructure) ChildDir(dirName string, perm os.FileMode) (child *DirStructure) {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
|
||||
// if exists, update
|
||||
child, ok := ds.Children[dirName]
|
||||
if ok {
|
||||
child.Perm = perm
|
||||
return child
|
||||
}
|
||||
|
||||
// create new
|
||||
newDir := &DirStructure{
|
||||
Path: filepath.Join(ds.Path, dirName),
|
||||
Dir: dirName,
|
||||
Perm: perm,
|
||||
Parent: ds,
|
||||
Children: make(map[string]*DirStructure),
|
||||
}
|
||||
ds.Children[dirName] = newDir
|
||||
return newDir
|
||||
}
|
||||
|
||||
// Ensure ensures that the specified directory structure (from the first parent on) exists.
|
||||
func (ds *DirStructure) Ensure() error {
|
||||
return ds.EnsureAbsPath(ds.Path)
|
||||
}
|
||||
|
||||
// EnsureRelPath ensures that the specified directory structure (from the first parent on) and the given relative path (to the DirStructure) exists.
|
||||
func (ds *DirStructure) EnsureRelPath(dirPath string) error {
|
||||
return ds.EnsureAbsPath(filepath.Join(ds.Path, dirPath))
|
||||
}
|
||||
|
||||
// EnsureRelDir ensures that the specified directory structure (from the first parent on) and the given relative path (to the DirStructure) exists.
|
||||
func (ds *DirStructure) EnsureRelDir(dirNames ...string) error {
|
||||
return ds.EnsureAbsPath(filepath.Join(append([]string{ds.Path}, dirNames...)...))
|
||||
}
|
||||
|
||||
// EnsureAbsPath ensures that the specified directory structure (from the first parent on) and the given absolute path exists.
|
||||
// If the given path is outside the DirStructure, an error will be returned.
|
||||
func (ds *DirStructure) EnsureAbsPath(dirPath string) error {
|
||||
// always start at the top
|
||||
if ds.Parent != nil {
|
||||
return ds.Parent.EnsureAbsPath(dirPath)
|
||||
}
|
||||
|
||||
// check if root
|
||||
if dirPath == ds.Path {
|
||||
return ds.ensure(nil)
|
||||
}
|
||||
|
||||
// check scope
|
||||
slashedPath := ds.Path
|
||||
// add slash to end
|
||||
if !strings.HasSuffix(slashedPath, string(filepath.Separator)) {
|
||||
slashedPath += string(filepath.Separator)
|
||||
}
|
||||
// check if given path is in scope
|
||||
if !strings.HasPrefix(dirPath, slashedPath) {
|
||||
return fmt.Errorf(`path "%s" is outside of DirStructure scope`, dirPath)
|
||||
}
|
||||
|
||||
// get relative path
|
||||
relPath, err := filepath.Rel(ds.Path, dirPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get relative path: %w", err)
|
||||
}
|
||||
|
||||
// split to path elements
|
||||
pathDirs := strings.Split(filepath.ToSlash(relPath), "/")
|
||||
|
||||
// start checking
|
||||
return ds.ensure(pathDirs)
|
||||
}
|
||||
|
||||
func (ds *DirStructure) ensure(pathDirs []string) error {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
|
||||
// check current dir
|
||||
err := EnsureDirectory(ds.Path, ds.Perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(pathDirs) == 0 {
|
||||
// we reached the end!
|
||||
return nil
|
||||
}
|
||||
|
||||
child, ok := ds.Children[pathDirs[0]]
|
||||
if !ok {
|
||||
// we have reached the end of the defined dir structure
|
||||
// ensure all remaining dirs
|
||||
dirPath := ds.Path
|
||||
for _, dir := range pathDirs {
|
||||
dirPath = filepath.Join(dirPath, dir)
|
||||
err := EnsureDirectory(dirPath, ds.Perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// we got a child, continue
|
||||
return child.ensure(pathDirs[1:])
|
||||
}
|
||||
Reference in New Issue
Block a user