From 03c24c51224e85eb96527a512f5f0483464fc810 Mon Sep 17 00:00:00 2001 From: Ophestra Umiker Date: Mon, 16 Sep 2024 20:32:07 +0900 Subject: move acl and xcb binding packages to top level These packages are reasonably clean and do not interact with other packages. Signed-off-by: Ophestra Umiker --- acl/c.go | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ acl/export.go | 86 ++++++++++++++++++++++++++++++++++++++++++ internal/acl/c.go | 99 ------------------------------------------------- internal/acl/export.go | 86 ------------------------------------------ internal/app/dbus.go | 4 +- internal/app/ensure.go | 7 ++-- internal/app/pulse.go | 4 +- internal/app/wayland.go | 4 +- internal/app/x.go | 4 +- internal/final/exit.go | 9 +++-- internal/xcb/c.go | 33 ----------------- internal/xcb/export.go | 47 ----------------------- xcb/c.go | 33 +++++++++++++++++ xcb/export.go | 47 +++++++++++++++++++++++ 14 files changed, 282 insertions(+), 280 deletions(-) create mode 100644 acl/c.go create mode 100644 acl/export.go delete mode 100644 internal/acl/c.go delete mode 100644 internal/acl/export.go delete mode 100644 internal/xcb/c.go delete mode 100644 internal/xcb/export.go create mode 100644 xcb/c.go create mode 100644 xcb/export.go diff --git a/acl/c.go b/acl/c.go new file mode 100644 index 00000000..89bc0469 --- /dev/null +++ b/acl/c.go @@ -0,0 +1,99 @@ +package acl + +import ( + "errors" + "fmt" + "syscall" + "unsafe" +) + +//#include +//#include +//#include +//#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 +} diff --git a/acl/export.go b/acl/export.go new file mode 100644 index 00000000..aeb8ed96 --- /dev/null +++ b/acl/export.go @@ -0,0 +1,86 @@ +package acl + +import "unsafe" + +//#include +//#include +//#include +//#cgo linux LDFLAGS: -lacl +import "C" + +const ( + Read = C.ACL_READ + Write = C.ACL_WRITE + Execute = C.ACL_EXECUTE + + TypeDefault = C.ACL_TYPE_DEFAULT + TypeAccess = C.ACL_TYPE_ACCESS + + UndefinedTag = C.ACL_UNDEFINED_TAG + UserObj = C.ACL_USER_OBJ + User = C.ACL_USER + GroupObj = C.ACL_GROUP_OBJ + Group = C.ACL_GROUP + Mask = C.ACL_MASK + Other = C.ACL_OTHER +) + +func UpdatePerm(path string, uid int, perms ...C.acl_perm_t) error { + // read acl from file + a, err := aclGetFile(path, TypeAccess) + if err != nil { + return err + } + // free acl on return if get is successful + defer a.free() + + // remove existing entry + if err = a.removeEntry(User, uid); err != nil { + return err + } + + // create new entry if perms are passed + if len(perms) > 0 { + // create new acl entry + var e C.acl_entry_t + if _, err = C.acl_create_entry(&a.val, &e); err != nil { + return err + } + + // get perm set of new entry + var p C.acl_permset_t + if _, err = C.acl_get_permset(e, &p); err != nil { + return err + } + + // add target perms + for _, perm := range perms { + if _, err = C.acl_add_perm(p, perm); err != nil { + return err + } + } + + // set perm set to new entry + if _, err = C.acl_set_permset(e, p); err != nil { + return err + } + + // set user tag to new entry + if _, err = C.acl_set_tag_type(e, User); err != nil { + return err + } + + // set qualifier (uid) to new entry + if _, err = C.acl_set_qualifier(e, unsafe.Pointer(&uid)); err != nil { + return err + } + } + + // calculate mask after update + if _, err = C.acl_calc_mask(&a.val); err != nil { + return err + } + + // write acl to file + return a.setFile(path, TypeAccess) +} diff --git a/internal/acl/c.go b/internal/acl/c.go deleted file mode 100644 index 89bc0469..00000000 --- a/internal/acl/c.go +++ /dev/null @@ -1,99 +0,0 @@ -package acl - -import ( - "errors" - "fmt" - "syscall" - "unsafe" -) - -//#include -//#include -//#include -//#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 -} diff --git a/internal/acl/export.go b/internal/acl/export.go deleted file mode 100644 index aeb8ed96..00000000 --- a/internal/acl/export.go +++ /dev/null @@ -1,86 +0,0 @@ -package acl - -import "unsafe" - -//#include -//#include -//#include -//#cgo linux LDFLAGS: -lacl -import "C" - -const ( - Read = C.ACL_READ - Write = C.ACL_WRITE - Execute = C.ACL_EXECUTE - - TypeDefault = C.ACL_TYPE_DEFAULT - TypeAccess = C.ACL_TYPE_ACCESS - - UndefinedTag = C.ACL_UNDEFINED_TAG - UserObj = C.ACL_USER_OBJ - User = C.ACL_USER - GroupObj = C.ACL_GROUP_OBJ - Group = C.ACL_GROUP - Mask = C.ACL_MASK - Other = C.ACL_OTHER -) - -func UpdatePerm(path string, uid int, perms ...C.acl_perm_t) error { - // read acl from file - a, err := aclGetFile(path, TypeAccess) - if err != nil { - return err - } - // free acl on return if get is successful - defer a.free() - - // remove existing entry - if err = a.removeEntry(User, uid); err != nil { - return err - } - - // create new entry if perms are passed - if len(perms) > 0 { - // create new acl entry - var e C.acl_entry_t - if _, err = C.acl_create_entry(&a.val, &e); err != nil { - return err - } - - // get perm set of new entry - var p C.acl_permset_t - if _, err = C.acl_get_permset(e, &p); err != nil { - return err - } - - // add target perms - for _, perm := range perms { - if _, err = C.acl_add_perm(p, perm); err != nil { - return err - } - } - - // set perm set to new entry - if _, err = C.acl_set_permset(e, p); err != nil { - return err - } - - // set user tag to new entry - if _, err = C.acl_set_tag_type(e, User); err != nil { - return err - } - - // set qualifier (uid) to new entry - if _, err = C.acl_set_qualifier(e, unsafe.Pointer(&uid)); err != nil { - return err - } - } - - // calculate mask after update - if _, err = C.acl_calc_mask(&a.val); err != nil { - return err - } - - // write acl to file - return a.setFile(path, TypeAccess) -} diff --git a/internal/app/dbus.go b/internal/app/dbus.go index 06523e88..a327e2cd 100644 --- a/internal/app/dbus.go +++ b/internal/app/dbus.go @@ -3,13 +3,13 @@ package app import ( "errors" "fmt" - "git.ophivana.moe/cat/fortify/internal/final" "os" "path" "strconv" + "git.ophivana.moe/cat/fortify/acl" "git.ophivana.moe/cat/fortify/dbus" - "git.ophivana.moe/cat/fortify/internal/acl" + "git.ophivana.moe/cat/fortify/internal/final" "git.ophivana.moe/cat/fortify/internal/state" "git.ophivana.moe/cat/fortify/internal/util" "git.ophivana.moe/cat/fortify/internal/verbose" diff --git a/internal/app/ensure.go b/internal/app/ensure.go index 9ab63ff2..ada6349f 100644 --- a/internal/app/ensure.go +++ b/internal/app/ensure.go @@ -3,12 +3,13 @@ package app import ( "errors" "fmt" - "git.ophivana.moe/cat/fortify/internal/acl" - "git.ophivana.moe/cat/fortify/internal/final" - "git.ophivana.moe/cat/fortify/internal/verbose" "io/fs" "os" "path" + + "git.ophivana.moe/cat/fortify/acl" + "git.ophivana.moe/cat/fortify/internal/final" + "git.ophivana.moe/cat/fortify/internal/verbose" ) func (a *App) EnsureRunDir() { diff --git a/internal/app/pulse.go b/internal/app/pulse.go index 4b67ff2e..7c360252 100644 --- a/internal/app/pulse.go +++ b/internal/app/pulse.go @@ -3,12 +3,12 @@ package app import ( "errors" "fmt" - "git.ophivana.moe/cat/fortify/internal/final" "io/fs" "os" "path" - "git.ophivana.moe/cat/fortify/internal/acl" + "git.ophivana.moe/cat/fortify/acl" + "git.ophivana.moe/cat/fortify/internal/final" "git.ophivana.moe/cat/fortify/internal/state" "git.ophivana.moe/cat/fortify/internal/util" "git.ophivana.moe/cat/fortify/internal/verbose" diff --git a/internal/app/wayland.go b/internal/app/wayland.go index 9834fea9..3b12e3ec 100644 --- a/internal/app/wayland.go +++ b/internal/app/wayland.go @@ -2,11 +2,11 @@ package app import ( "fmt" - "git.ophivana.moe/cat/fortify/internal/final" "os" "path" - "git.ophivana.moe/cat/fortify/internal/acl" + "git.ophivana.moe/cat/fortify/acl" + "git.ophivana.moe/cat/fortify/internal/final" "git.ophivana.moe/cat/fortify/internal/state" "git.ophivana.moe/cat/fortify/internal/verbose" ) diff --git a/internal/app/x.go b/internal/app/x.go index 07034026..f198fee3 100644 --- a/internal/app/x.go +++ b/internal/app/x.go @@ -2,12 +2,12 @@ package app import ( "fmt" - "git.ophivana.moe/cat/fortify/internal/final" "os" + "git.ophivana.moe/cat/fortify/internal/final" "git.ophivana.moe/cat/fortify/internal/state" "git.ophivana.moe/cat/fortify/internal/verbose" - "git.ophivana.moe/cat/fortify/internal/xcb" + "git.ophivana.moe/cat/fortify/xcb" ) const display = "DISPLAY" diff --git a/internal/final/exit.go b/internal/final/exit.go index 86cc2e71..063d8d04 100644 --- a/internal/final/exit.go +++ b/internal/final/exit.go @@ -3,12 +3,13 @@ package final import ( "errors" "fmt" - "git.ophivana.moe/cat/fortify/internal/acl" - "git.ophivana.moe/cat/fortify/internal/state" - "git.ophivana.moe/cat/fortify/internal/verbose" - "git.ophivana.moe/cat/fortify/internal/xcb" "io/fs" "os" + + "git.ophivana.moe/cat/fortify/acl" + "git.ophivana.moe/cat/fortify/internal/state" + "git.ophivana.moe/cat/fortify/internal/verbose" + "git.ophivana.moe/cat/fortify/xcb" ) func Fatal(msg ...any) { diff --git a/internal/xcb/c.go b/internal/xcb/c.go deleted file mode 100644 index 8fe59d8c..00000000 --- a/internal/xcb/c.go +++ /dev/null @@ -1,33 +0,0 @@ -package xcb - -import ( - "errors" -) - -//#include -//#include -//#cgo linux LDFLAGS: -lxcb -import "C" - -func xcbHandleConnectionError(c *C.xcb_connection_t) error { - if errno := C.xcb_connection_has_error(c); errno != 0 { - switch errno { - case C.XCB_CONN_ERROR: - return errors.New("connection error") - case C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED: - return errors.New("extension not supported") - case C.XCB_CONN_CLOSED_MEM_INSUFFICIENT: - return errors.New("memory not available") - case C.XCB_CONN_CLOSED_REQ_LEN_EXCEED: - return errors.New("request length exceeded") - case C.XCB_CONN_CLOSED_PARSE_ERR: - return errors.New("invalid display string") - case C.XCB_CONN_CLOSED_INVALID_SCREEN: - return errors.New("server has no screen matching display") - default: - return errors.New("generic X11 failure") - } - } else { - return nil - } -} diff --git a/internal/xcb/export.go b/internal/xcb/export.go deleted file mode 100644 index 72a74131..00000000 --- a/internal/xcb/export.go +++ /dev/null @@ -1,47 +0,0 @@ -package xcb - -//#include -//#include -//#cgo linux LDFLAGS: -lxcb -import "C" -import ( - "errors" - "unsafe" -) - -const ( - HostModeInsert = C.XCB_HOST_MODE_INSERT - HostModeDelete = C.XCB_HOST_MODE_DELETE - - FamilyInternet = C.XCB_FAMILY_INTERNET - FamilyDecnet = C.XCB_FAMILY_DECNET - FamilyChaos = C.XCB_FAMILY_CHAOS - FamilyServerInterpreted = C.XCB_FAMILY_SERVER_INTERPRETED - FamilyInternet6 = C.XCB_FAMILY_INTERNET_6 -) - -func ChangeHosts(mode, family C.uint8_t, address string) error { - var c *C.xcb_connection_t - c = C.xcb_connect(nil, nil) - defer C.xcb_disconnect(c) - - if err := xcbHandleConnectionError(c); err != nil { - return err - } - - addr := C.CString(address) - cookie := C.xcb_change_hosts_checked(c, mode, family, C.ushort(len(address)), (*C.uchar)(unsafe.Pointer(addr))) - C.free(unsafe.Pointer(addr)) - - if err := xcbHandleConnectionError(c); err != nil { - return err - } - - e := C.xcb_request_check(c, cookie) - if e != nil { - defer C.free(unsafe.Pointer(e)) - return errors.New("xcb_change_hosts() failed") - } - - return nil -} diff --git a/xcb/c.go b/xcb/c.go new file mode 100644 index 00000000..8fe59d8c --- /dev/null +++ b/xcb/c.go @@ -0,0 +1,33 @@ +package xcb + +import ( + "errors" +) + +//#include +//#include +//#cgo linux LDFLAGS: -lxcb +import "C" + +func xcbHandleConnectionError(c *C.xcb_connection_t) error { + if errno := C.xcb_connection_has_error(c); errno != 0 { + switch errno { + case C.XCB_CONN_ERROR: + return errors.New("connection error") + case C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED: + return errors.New("extension not supported") + case C.XCB_CONN_CLOSED_MEM_INSUFFICIENT: + return errors.New("memory not available") + case C.XCB_CONN_CLOSED_REQ_LEN_EXCEED: + return errors.New("request length exceeded") + case C.XCB_CONN_CLOSED_PARSE_ERR: + return errors.New("invalid display string") + case C.XCB_CONN_CLOSED_INVALID_SCREEN: + return errors.New("server has no screen matching display") + default: + return errors.New("generic X11 failure") + } + } else { + return nil + } +} diff --git a/xcb/export.go b/xcb/export.go new file mode 100644 index 00000000..72a74131 --- /dev/null +++ b/xcb/export.go @@ -0,0 +1,47 @@ +package xcb + +//#include +//#include +//#cgo linux LDFLAGS: -lxcb +import "C" +import ( + "errors" + "unsafe" +) + +const ( + HostModeInsert = C.XCB_HOST_MODE_INSERT + HostModeDelete = C.XCB_HOST_MODE_DELETE + + FamilyInternet = C.XCB_FAMILY_INTERNET + FamilyDecnet = C.XCB_FAMILY_DECNET + FamilyChaos = C.XCB_FAMILY_CHAOS + FamilyServerInterpreted = C.XCB_FAMILY_SERVER_INTERPRETED + FamilyInternet6 = C.XCB_FAMILY_INTERNET_6 +) + +func ChangeHosts(mode, family C.uint8_t, address string) error { + var c *C.xcb_connection_t + c = C.xcb_connect(nil, nil) + defer C.xcb_disconnect(c) + + if err := xcbHandleConnectionError(c); err != nil { + return err + } + + addr := C.CString(address) + cookie := C.xcb_change_hosts_checked(c, mode, family, C.ushort(len(address)), (*C.uchar)(unsafe.Pointer(addr))) + C.free(unsafe.Pointer(addr)) + + if err := xcbHandleConnectionError(c); err != nil { + return err + } + + e := C.xcb_request_check(c, cookie) + if e != nil { + defer C.free(unsafe.Pointer(e)) + return errors.New("xcb_change_hosts() failed") + } + + return nil +} -- cgit v1.3.1