aboutsummaryrefslogtreecommitdiffhomepage
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/acl/acl.go5
-rw-r--r--system/acl/libacl-helper.c29
-rw-r--r--system/acl/libacl-helper.go40
-rw-r--r--system/acl/libacl-helper_test.go60
4 files changed, 125 insertions, 9 deletions
diff --git a/system/acl/acl.go b/system/acl/acl.go
index bc590db2..366ad533 100644
--- a/system/acl/acl.go
+++ b/system/acl/acl.go
@@ -29,8 +29,5 @@ func Update(name string, uid int, perms ...Perm) error {
(*C.acl_perm_t)(p),
C.size_t(len(perms)),
)
- if r == 0 {
- return nil
- }
- return err
+ return newAclPathError(name, int(r), err)
}
diff --git a/system/acl/libacl-helper.c b/system/acl/libacl-helper.c
index 905cfa52..d1df8167 100644
--- a/system/acl/libacl-helper.c
+++ b/system/acl/libacl-helper.c
@@ -6,7 +6,7 @@
int hakurei_acl_update_file_by_uid(const char *path_p, uid_t uid,
acl_perm_t *perms, size_t plen) {
- int ret = -1;
+ int ret;
bool v;
int i;
acl_t acl;
@@ -15,51 +15,70 @@ int hakurei_acl_update_file_by_uid(const char *path_p, uid_t uid,
void *qualifier_p;
acl_permset_t permset;
+ ret = -1; /* acl_get_file */
acl = acl_get_file(path_p, ACL_TYPE_ACCESS);
if (acl == NULL)
goto out;
- // prune entries by uid
+ /* prune entries by uid */
for (i = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); i == 1;
i = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) {
+ ret = -2; /* acl_get_tag_type */
if (acl_get_tag_type(entry, &tag_type) != 0)
- return -1;
+ goto out;
if (tag_type != ACL_USER)
continue;
+ ret = -3; /* acl_get_qualifier */
qualifier_p = acl_get_qualifier(entry);
if (qualifier_p == NULL)
- return -1;
+ goto out;
v = *(uid_t *)qualifier_p == uid;
acl_free(qualifier_p);
if (!v)
continue;
- acl_delete_entry(acl, entry);
+ ret = -4; /* acl_delete_entry */
+ if (acl_delete_entry(acl, entry) != 0)
+ goto out;
}
if (plen == 0)
goto set;
+ ret = -5; /* acl_create_entry */
if (acl_create_entry(&acl, &entry) != 0)
goto out;
+
+ ret = -6; /* acl_get_permset */
if (acl_get_permset(entry, &permset) != 0)
goto out;
+
+ ret = -7; /* acl_add_perm */
for (i = 0; i < plen; i++) {
if (acl_add_perm(permset, perms[i]) != 0)
goto out;
}
+
+ ret = -8; /* acl_set_tag_type */
if (acl_set_tag_type(entry, ACL_USER) != 0)
goto out;
+
+ ret = -9; /* acl_set_qualifier */
if (acl_set_qualifier(entry, (void *)&uid) != 0)
goto out;
set:
+ ret = -10; /* acl_calc_mask */
if (acl_calc_mask(&acl) != 0)
goto out;
+
+ ret = -11; /* acl_valid */
if (acl_valid(acl) != 0)
goto out;
+
+ ret = -12; /* acl_set_file */
if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) == 0)
ret = 0;
diff --git a/system/acl/libacl-helper.go b/system/acl/libacl-helper.go
new file mode 100644
index 00000000..22575296
--- /dev/null
+++ b/system/acl/libacl-helper.go
@@ -0,0 +1,40 @@
+package acl
+
+import "os"
+
+func newAclPathError(name string, r int, err error) error {
+ pathError := &os.PathError{Path: name, Err: err}
+ switch r {
+ case 0:
+ return nil
+
+ case -1:
+ pathError.Op = "acl_get_file"
+ case -2:
+ pathError.Op = "acl_get_tag_type"
+ case -3:
+ pathError.Op = "acl_get_qualifier"
+ case -4:
+ pathError.Op = "acl_delete_entry"
+ case -5:
+ pathError.Op = "acl_create_entry"
+ case -6:
+ pathError.Op = "acl_get_permset"
+ case -7:
+ pathError.Op = "acl_add_perm"
+ case -8:
+ pathError.Op = "acl_set_tag_type"
+ case -9:
+ pathError.Op = "acl_set_qualifier"
+ case -10:
+ pathError.Op = "acl_calc_mask"
+ case -11:
+ pathError.Op = "acl_valid"
+ case -12:
+ pathError.Op = "acl_set_file"
+
+ default: // unreachable
+ pathError.Op = "setfacl"
+ }
+ return pathError
+}
diff --git a/system/acl/libacl-helper_test.go b/system/acl/libacl-helper_test.go
new file mode 100644
index 00000000..78e5776f
--- /dev/null
+++ b/system/acl/libacl-helper_test.go
@@ -0,0 +1,60 @@
+package acl
+
+import (
+ "os"
+ "reflect"
+ "syscall"
+ "testing"
+
+ "hakurei.app/container"
+)
+
+func TestNewAclPathError(t *testing.T) {
+ testCases := []struct {
+ name string
+ path string
+ r int
+ err error
+ want error
+ }{
+ {"nil", container.Nonexistent, 0, syscall.ENOTRECOVERABLE, nil},
+
+ {"acl_get_file", container.Nonexistent, -1, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_get_file", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_get_tag_type", container.Nonexistent, -2, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_get_tag_type", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_get_qualifier", container.Nonexistent, -3, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_get_qualifier", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_delete_entry", container.Nonexistent, -4, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_delete_entry", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_create_entry", container.Nonexistent, -5, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_create_entry", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_get_permset", container.Nonexistent, -6, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_get_permset", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_add_perm", container.Nonexistent, -7, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_add_perm", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_set_tag_type", container.Nonexistent, -8, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_set_tag_type", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_set_qualifier", container.Nonexistent, -9, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_set_qualifier", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_calc_mask", container.Nonexistent, -10, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_calc_mask", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_valid", container.Nonexistent, -11, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_valid", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"acl_set_file", container.Nonexistent, -12, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "acl_set_file", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+
+ {"acl", container.Nonexistent, -13, syscall.ENOTRECOVERABLE,
+ &os.PathError{Op: "setfacl", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
+ {"invalid", container.Nonexistent, -0xdeadbeef, nil,
+ &os.PathError{Op: "setfacl", Path: container.Nonexistent}},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ err := newAclPathError(tc.path, tc.r, tc.err)
+ if !reflect.DeepEqual(err, tc.want) {
+ t.Errorf("newAclPathError: %v, want %v", err, tc.want)
+ }
+ })
+ }
+}