aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/system/acl.go
diff options
context:
space:
mode:
authorOphestra Umiker <cat@ophivana.moe>2024-10-16 01:31:23 +0900
committerOphestra Umiker <cat@ophivana.moe>2024-10-16 01:31:23 +0900
commit430f1a5b4e4e2b164297391390e3a0cbe2ad2eb2 (patch)
tree76aab87e648c6e8fd6c8afc3d314bc73563ee552 /internal/system/acl.go
parent0fd63e85e730d44abd488c892be377b332f5458e (diff)
system: isolate app/system into generic implementation
This improves maintainability and extensibility of system operations, makes writing tests for them possible, and operations now apply and revert in order, instead of being bunched up into their own categories. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
Diffstat (limited to 'internal/system/acl.go')
-rw-r--r--internal/system/acl.go78
1 files changed, 78 insertions, 0 deletions
diff --git a/internal/system/acl.go b/internal/system/acl.go
new file mode 100644
index 00000000..9c89752b
--- /dev/null
+++ b/internal/system/acl.go
@@ -0,0 +1,78 @@
+package system
+
+import (
+ "fmt"
+ "slices"
+
+ "git.ophivana.moe/cat/fortify/acl"
+ "git.ophivana.moe/cat/fortify/internal/fmsg"
+ "git.ophivana.moe/cat/fortify/internal/state"
+ "git.ophivana.moe/cat/fortify/internal/verbose"
+)
+
+// UpdatePerm appends an ephemeral acl update Op.
+func (sys *I) UpdatePerm(path string, perms ...acl.Perm) {
+ sys.UpdatePermType(Process, path, perms...)
+}
+
+// UpdatePermType appends an acl update Op.
+func (sys *I) UpdatePermType(et state.Enablement, path string, perms ...acl.Perm) {
+ sys.lock.Lock()
+ defer sys.lock.Unlock()
+
+ sys.ops = append(sys.ops, &ACL{et, path, perms})
+}
+
+type ACL struct {
+ et state.Enablement
+ path string
+ perms []acl.Perm
+}
+
+func (a *ACL) Type() state.Enablement {
+ return a.et
+}
+
+func (a *ACL) apply(sys *I) error {
+ verbose.Println("applying ACL", a, "uid:", sys.uid, "type:", TypeString(a.et), "path:", a.path)
+ return fmsg.WrapErrorSuffix(acl.UpdatePerm(a.path, sys.uid, a.perms...),
+ fmt.Sprintf("cannot apply ACL entry to %q:", a.path))
+}
+
+func (a *ACL) revert(sys *I, ec *Criteria) error {
+ if ec.hasType(a) {
+ verbose.Println("stripping ACL", a, "uid:", sys.uid, "type:", TypeString(a.et), "path:", a.path)
+ return fmsg.WrapErrorSuffix(acl.UpdatePerm(a.path, sys.uid),
+ fmt.Sprintf("cannot strip ACL entry from %q:", a.path))
+ } else {
+ verbose.Println("skipping ACL", a, "uid:", sys.uid, "tag:", TypeString(a.et), "path:", a.path)
+ return nil
+ }
+}
+
+func (a *ACL) Is(o Op) bool {
+ a0, ok := o.(*ACL)
+ return ok && a0 != nil &&
+ a.et == a0.et &&
+ a.path == a0.path &&
+ slices.Equal(a.perms, a0.perms)
+}
+
+func (a *ACL) Path() string {
+ return a.path
+}
+
+func (a *ACL) String() string {
+ var s = []byte("---")
+ for _, p := range a.perms {
+ switch p {
+ case acl.Read:
+ s[0] = 'r'
+ case acl.Write:
+ s[1] = 'w'
+ case acl.Execute:
+ s[2] = 'x'
+ }
+ }
+ return string(s)
+}