aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/acl/c.go
diff options
context:
space:
mode:
authorOphestra Umiker <cat@ophivana.moe>2024-09-04 01:20:12 +0900
committerOphestra Umiker <cat@ophivana.moe>2024-09-04 01:20:12 +0900
commitd8f76f3b2594db4687c0203c4f2be8d3e4ef7740 (patch)
treeb1d8bfb5250d71094e397f8afa87710de1f1ca2f /internal/acl/c.go
parent7e6eb82195c650bc34829e5cca2d2296e78c0707 (diff)
rename to fortify and restructure
More sandbox features will be added and this will no longer track ego's features and behaviour. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
Diffstat (limited to 'internal/acl/c.go')
-rw-r--r--internal/acl/c.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/internal/acl/c.go b/internal/acl/c.go
new file mode 100644
index 00000000..89bc0469
--- /dev/null
+++ b/internal/acl/c.go
@@ -0,0 +1,99 @@
+package acl
+
+import (
+ "errors"
+ "fmt"
+ "syscall"
+ "unsafe"
+)
+
+//#include <stdlib.h>
+//#include <sys/acl.h>
+//#include <acl/libacl.h>
+//#cgo linux LDFLAGS: -lacl
+import "C"
+
+type acl struct {
+ val C.acl_t
+ freed bool
+}
+
+func aclGetFile(path string, t C.acl_type_t) (*acl, error) {
+ p := C.CString(path)
+ a, err := C.acl_get_file(p, t)
+ C.free(unsafe.Pointer(p))
+
+ if errors.Is(err, syscall.ENODATA) {
+ err = nil
+ }
+ return &acl{val: a, freed: false}, err
+}
+
+func (a *acl) setFile(path string, t C.acl_type_t) error {
+ if C.acl_valid(a.val) != 0 {
+ return fmt.Errorf("invalid acl")
+ }
+
+ p := C.CString(path)
+ _, err := C.acl_set_file(p, t, a.val)
+ C.free(unsafe.Pointer(p))
+ return err
+}
+
+func (a *acl) removeEntry(tt C.acl_tag_t, tq int) error {
+ var e C.acl_entry_t
+
+ // get first entry
+ if r, err := C.acl_get_entry(a.val, C.ACL_FIRST_ENTRY, &e); err != nil {
+ return err
+ } else if r == 0 {
+ // return on acl with no entries
+ return nil
+ }
+
+ for {
+ if r, err := C.acl_get_entry(a.val, C.ACL_NEXT_ENTRY, &e); err != nil {
+ return err
+ } else if r == 0 {
+ // return on drained acl
+ return nil
+ }
+
+ var (
+ q int
+ t C.acl_tag_t
+ )
+
+ // get current entry tag type
+ if _, err := C.acl_get_tag_type(e, &t); err != nil {
+ return err
+ }
+
+ // get current entry qualifier
+ if rq, err := C.acl_get_qualifier(e); err != nil {
+ // neither ACL_USER nor ACL_GROUP
+ if errors.Is(err, syscall.EINVAL) {
+ continue
+ }
+
+ return err
+ } else {
+ q = *(*int)(rq)
+ C.acl_free(rq)
+ }
+
+ // delete on match
+ if t == tt && q == tq {
+ _, err := C.acl_delete_entry(a.val, e)
+ return err
+ }
+ }
+}
+
+func (a *acl) free() {
+ if a.freed {
+ panic("acl already freed")
+ }
+ C.acl_free(unsafe.Pointer(a.val))
+ a.freed = true
+}