system: unexport Op implementations
All checks were successful
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 3m30s
Test / Hakurei (push) Successful in 5m40s
Test / Sandbox (race detector) (push) Successful in 6m30s
Test / Hpkg (push) Successful in 7m21s
Test / Hakurei (race detector) (push) Successful in 3m22s
Test / Flake checks (push) Successful in 2m2s
All checks were successful
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 3m30s
Test / Hakurei (push) Successful in 5m40s
Test / Sandbox (race detector) (push) Successful in 6m30s
Test / Hpkg (push) Successful in 7m21s
Test / Hakurei (race detector) (push) Successful in 3m22s
Test / Flake checks (push) Successful in 2m2s
None of these are valid with their zero value, and the implementations assume they are created by the builder methods. They are by all means an implementation detail and exporting them makes no sense. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
ac81cfbedc
commit
e68db7fbfc
@ -9,33 +9,33 @@ import (
|
||||
"hakurei.app/system/acl"
|
||||
)
|
||||
|
||||
// UpdatePerm appends [ACLUpdateOp] to [I] with the [Process] criteria.
|
||||
// UpdatePerm calls UpdatePermType with the [Process] criteria.
|
||||
func (sys *I) UpdatePerm(path string, perms ...acl.Perm) *I {
|
||||
sys.UpdatePermType(Process, path, perms...)
|
||||
return sys
|
||||
}
|
||||
|
||||
// UpdatePermType appends [ACLUpdateOp] to [I].
|
||||
// UpdatePermType maintains [acl.Perms] on a file until its [Enablement] is no longer satisfied.
|
||||
func (sys *I) UpdatePermType(et Enablement, path string, perms ...acl.Perm) *I {
|
||||
sys.ops = append(sys.ops, &ACLUpdateOp{et, path, perms})
|
||||
sys.ops = append(sys.ops, &aclUpdateOp{et, path, perms})
|
||||
return sys
|
||||
}
|
||||
|
||||
// ACLUpdateOp maintains [acl.Perms] on a file until its [Enablement] is no longer satisfied.
|
||||
type ACLUpdateOp struct {
|
||||
// aclUpdateOp implements [I.UpdatePermType].
|
||||
type aclUpdateOp struct {
|
||||
et Enablement
|
||||
path string
|
||||
perms acl.Perms
|
||||
}
|
||||
|
||||
func (a *ACLUpdateOp) Type() Enablement { return a.et }
|
||||
func (a *aclUpdateOp) Type() Enablement { return a.et }
|
||||
|
||||
func (a *ACLUpdateOp) apply(sys *I) error {
|
||||
func (a *aclUpdateOp) apply(sys *I) error {
|
||||
sys.verbose("applying ACL", a)
|
||||
return newOpError("acl", sys.aclUpdate(a.path, sys.uid, a.perms...), false)
|
||||
}
|
||||
|
||||
func (a *ACLUpdateOp) revert(sys *I, ec *Criteria) error {
|
||||
func (a *aclUpdateOp) revert(sys *I, ec *Criteria) error {
|
||||
if ec.hasType(a.Type()) {
|
||||
sys.verbose("stripping ACL", a)
|
||||
err := sys.aclUpdate(a.path, sys.uid)
|
||||
@ -51,17 +51,17 @@ func (a *ACLUpdateOp) revert(sys *I, ec *Criteria) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *ACLUpdateOp) Is(o Op) bool {
|
||||
target, ok := o.(*ACLUpdateOp)
|
||||
func (a *aclUpdateOp) Is(o Op) bool {
|
||||
target, ok := o.(*aclUpdateOp)
|
||||
return ok && a != nil && target != nil &&
|
||||
a.et == target.et &&
|
||||
a.path == target.path &&
|
||||
slices.Equal(a.perms, target.perms)
|
||||
}
|
||||
|
||||
func (a *ACLUpdateOp) Path() string { return a.path }
|
||||
func (a *aclUpdateOp) Path() string { return a.path }
|
||||
|
||||
func (a *ACLUpdateOp) String() string {
|
||||
func (a *aclUpdateOp) String() string {
|
||||
return fmt.Sprintf("%s type: %s path: %q",
|
||||
a.perms, TypeString(a.et), a.path)
|
||||
}
|
||||
|
@ -12,44 +12,44 @@ import (
|
||||
func TestACLUpdateOp(t *testing.T) {
|
||||
checkOpBehaviour(t, []opBehaviourTestCase{
|
||||
{"apply aclUpdate", 0xdeadbeef, 0xff,
|
||||
&ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, stub.UniqueError(1)),
|
||||
}, &OpError{Op: "acl", Err: stub.UniqueError(1)}, nil, nil},
|
||||
|
||||
{"revert aclUpdate", 0xdeadbeef, 0xff,
|
||||
&ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
|
||||
}, nil, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, ([]acl.Perm)(nil)}, nil, stub.UniqueError(0)),
|
||||
}, &OpError{Op: "acl", Err: stub.UniqueError(0), Revert: true}},
|
||||
|
||||
{"success revert skip", 0xdeadbeef, Process,
|
||||
&ACLUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &ACLUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
&aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
|
||||
}, nil, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"skipping ACL", &ACLUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("verbose", stub.ExpectArgs{[]any{"skipping ACL", &aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
}, nil},
|
||||
|
||||
{"success revert aclUpdate ENOENT", 0xdeadbeef, 0xff,
|
||||
&ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
|
||||
}, nil, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, ([]acl.Perm)(nil)}, nil, &os.PathError{Op: "acl_get_file", Path: "/proc/nonexistent", Err: syscall.ENOENT}),
|
||||
call("verbosef", stub.ExpectArgs{"target of ACL %s no longer exists", []any{&ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("verbosef", stub.ExpectArgs{"target of ACL %s no longer exists", []any{&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
}, nil},
|
||||
|
||||
{"success", 0xdeadbeef, 0xff,
|
||||
&ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
|
||||
}, nil, []stub.Call{
|
||||
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
|
||||
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, ([]acl.Perm)(nil)}, nil, nil),
|
||||
}, nil},
|
||||
})
|
||||
@ -62,27 +62,27 @@ func TestACLUpdateOp(t *testing.T) {
|
||||
UpdatePerm("/run/user/1971/hakurei", acl.Execute).
|
||||
UpdatePerm("/tmp/hakurei.0/tmpdir/150", acl.Read, acl.Write, acl.Execute)
|
||||
}, []Op{
|
||||
&ACLUpdateOp{Process, "/run/user/1971/hakurei", []acl.Perm{acl.Execute}},
|
||||
&ACLUpdateOp{Process, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
&aclUpdateOp{Process, "/run/user/1971/hakurei", []acl.Perm{acl.Execute}},
|
||||
&aclUpdateOp{Process, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
}, stub.Expect{}},
|
||||
})
|
||||
checkOpsBuilder(t, "UpdatePermType", []opsBuilderTestCase{
|
||||
{"tmpdirp", 0xdeadbeef, func(_ *testing.T, sys *I) {
|
||||
sys.UpdatePermType(User, "/tmp/hakurei.0/tmpdir", acl.Execute)
|
||||
}, []Op{
|
||||
&ACLUpdateOp{User, "/tmp/hakurei.0/tmpdir", []acl.Perm{acl.Execute}},
|
||||
&aclUpdateOp{User, "/tmp/hakurei.0/tmpdir", []acl.Perm{acl.Execute}},
|
||||
}, stub.Expect{}},
|
||||
|
||||
{"tmpdir", 0xdeadbeef, func(_ *testing.T, sys *I) {
|
||||
sys.UpdatePermType(User, "/tmp/hakurei.0/tmpdir/150", acl.Read, acl.Write, acl.Execute)
|
||||
}, []Op{
|
||||
&ACLUpdateOp{User, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
&aclUpdateOp{User, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
}, stub.Expect{}},
|
||||
|
||||
{"share", 0xdeadbeef, func(_ *testing.T, sys *I) {
|
||||
sys.UpdatePermType(Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", acl.Execute)
|
||||
}, []Op{
|
||||
&ACLUpdateOp{Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", []acl.Perm{acl.Execute}},
|
||||
&aclUpdateOp{Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", []acl.Perm{acl.Execute}},
|
||||
}, stub.Expect{}},
|
||||
|
||||
{"passwd", 0xdeadbeef, func(_ *testing.T, sys *I) {
|
||||
@ -90,50 +90,50 @@ func TestACLUpdateOp(t *testing.T) {
|
||||
UpdatePermType(Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd", acl.Read).
|
||||
UpdatePermType(Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", acl.Read)
|
||||
}, []Op{
|
||||
&ACLUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd", []acl.Perm{acl.Read}},
|
||||
&ACLUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", []acl.Perm{acl.Read}},
|
||||
&aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd", []acl.Perm{acl.Read}},
|
||||
&aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", []acl.Perm{acl.Read}},
|
||||
}, stub.Expect{}},
|
||||
|
||||
{"wayland", 0xdeadbeef, func(_ *testing.T, sys *I) {
|
||||
sys.UpdatePermType(EWayland, "/run/user/1971/wayland-0", acl.Read, acl.Write, acl.Execute)
|
||||
}, []Op{
|
||||
&ACLUpdateOp{EWayland, "/run/user/1971/wayland-0", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
&aclUpdateOp{EWayland, "/run/user/1971/wayland-0", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
}, stub.Expect{}},
|
||||
})
|
||||
|
||||
checkOpIs(t, []opIsTestCase{
|
||||
{"nil", (*ACLUpdateOp)(nil), (*ACLUpdateOp)(nil), false},
|
||||
{"zero", new(ACLUpdateOp), new(ACLUpdateOp), true},
|
||||
{"nil", (*aclUpdateOp)(nil), (*aclUpdateOp)(nil), false},
|
||||
{"zero", new(aclUpdateOp), new(aclUpdateOp), true},
|
||||
|
||||
{"et differs",
|
||||
&ACLUpdateOp{
|
||||
&aclUpdateOp{
|
||||
EWayland, "/run/user/1971/wayland-0",
|
||||
[]acl.Perm{acl.Read, acl.Write, acl.Execute},
|
||||
}, &ACLUpdateOp{
|
||||
}, &aclUpdateOp{
|
||||
EX11, "/run/user/1971/wayland-0",
|
||||
[]acl.Perm{acl.Read, acl.Write, acl.Execute},
|
||||
}, false},
|
||||
|
||||
{"path differs", &ACLUpdateOp{
|
||||
{"path differs", &aclUpdateOp{
|
||||
EWayland, "/run/user/1971/wayland-0",
|
||||
[]acl.Perm{acl.Read, acl.Write, acl.Execute},
|
||||
}, &ACLUpdateOp{
|
||||
}, &aclUpdateOp{
|
||||
EWayland, "/run/user/1971/wayland-1",
|
||||
[]acl.Perm{acl.Read, acl.Write, acl.Execute},
|
||||
}, false},
|
||||
|
||||
{"perms differs", &ACLUpdateOp{
|
||||
{"perms differs", &aclUpdateOp{
|
||||
EWayland, "/run/user/1971/wayland-0",
|
||||
[]acl.Perm{acl.Read, acl.Write, acl.Execute},
|
||||
}, &ACLUpdateOp{
|
||||
}, &aclUpdateOp{
|
||||
EWayland, "/run/user/1971/wayland-0",
|
||||
[]acl.Perm{acl.Read, acl.Write},
|
||||
}, false},
|
||||
|
||||
{"equals", &ACLUpdateOp{
|
||||
{"equals", &aclUpdateOp{
|
||||
EWayland, "/run/user/1971/wayland-0",
|
||||
[]acl.Perm{acl.Read, acl.Write, acl.Execute},
|
||||
}, &ACLUpdateOp{
|
||||
}, &aclUpdateOp{
|
||||
EWayland, "/run/user/1971/wayland-0",
|
||||
[]acl.Perm{acl.Read, acl.Write, acl.Execute},
|
||||
}, true},
|
||||
@ -141,42 +141,42 @@ func TestACLUpdateOp(t *testing.T) {
|
||||
|
||||
checkOpMeta(t, []opMetaTestCase{
|
||||
{"clear",
|
||||
&ACLUpdateOp{Process, "/proc/nonexistent", []acl.Perm{}},
|
||||
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{}},
|
||||
Process, "/proc/nonexistent",
|
||||
`--- type: process path: "/proc/nonexistent"`},
|
||||
|
||||
{"read",
|
||||
&ACLUpdateOp{User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/0", []acl.Perm{acl.Read}},
|
||||
&aclUpdateOp{User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/0", []acl.Perm{acl.Read}},
|
||||
User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/0",
|
||||
`r-- type: user path: "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/0"`},
|
||||
|
||||
{"write",
|
||||
&ACLUpdateOp{User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/1", []acl.Perm{acl.Write}},
|
||||
&aclUpdateOp{User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/1", []acl.Perm{acl.Write}},
|
||||
User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/1",
|
||||
`-w- type: user path: "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/1"`},
|
||||
|
||||
{"execute",
|
||||
&ACLUpdateOp{User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/2", []acl.Perm{acl.Execute}},
|
||||
&aclUpdateOp{User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/2", []acl.Perm{acl.Execute}},
|
||||
User, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/2",
|
||||
`--x type: user path: "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/2"`},
|
||||
|
||||
{"wayland",
|
||||
&ACLUpdateOp{EWayland, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/wayland", []acl.Perm{acl.Read, acl.Write}},
|
||||
&aclUpdateOp{EWayland, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/wayland", []acl.Perm{acl.Read, acl.Write}},
|
||||
EWayland, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/wayland",
|
||||
`rw- type: wayland path: "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/wayland"`},
|
||||
|
||||
{"x11",
|
||||
&ACLUpdateOp{EX11, "/tmp/.X11-unix/X0", []acl.Perm{acl.Read, acl.Execute}},
|
||||
&aclUpdateOp{EX11, "/tmp/.X11-unix/X0", []acl.Perm{acl.Read, acl.Execute}},
|
||||
EX11, "/tmp/.X11-unix/X0",
|
||||
`r-x type: x11 path: "/tmp/.X11-unix/X0"`},
|
||||
|
||||
{"dbus",
|
||||
&ACLUpdateOp{EDBus, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/bus", []acl.Perm{acl.Write, acl.Execute}},
|
||||
&aclUpdateOp{EDBus, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/bus", []acl.Perm{acl.Write, acl.Execute}},
|
||||
EDBus, "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/bus",
|
||||
`-wx type: dbus path: "/tmp/hakurei.0/27d81d567f8fae7f33278eec45da9446/bus"`},
|
||||
|
||||
{"pulseaudio",
|
||||
&ACLUpdateOp{EPulse, "/run/user/1971/hakurei/27d81d567f8fae7f33278eec45da9446/pulse", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
&aclUpdateOp{EPulse, "/run/user/1971/hakurei/27d81d567f8fae7f33278eec45da9446/pulse", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
|
||||
EPulse, "/run/user/1971/hakurei/27d81d567f8fae7f33278eec45da9446/pulse",
|
||||
`rwx type: pulseaudio path: "/run/user/1971/hakurei/27d81d567f8fae7f33278eec45da9446/pulse"`},
|
||||
})
|
||||
|
@ -28,9 +28,10 @@ func (sys *I) MustProxyDBus(sessionPath string, session *dbus.Config, systemPath
|
||||
}
|
||||
}
|
||||
|
||||
// ProxyDBus finalises configuration and appends [DBusProxyOp] to [I].
|
||||
// ProxyDBus finalises configuration ahead of time and starts xdg-dbus-proxy via [dbus] and terminates it on revert.
|
||||
// This [Op] is always [Process] scoped.
|
||||
func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath string) (func(), error) {
|
||||
d := new(DBusProxyOp)
|
||||
d := new(dbusProxyOp)
|
||||
|
||||
// session bus is required as otherwise this is effectively a very expensive noop
|
||||
if session == nil {
|
||||
@ -70,9 +71,8 @@ func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath st
|
||||
return d.out.Dump, nil
|
||||
}
|
||||
|
||||
// DBusProxyOp starts xdg-dbus-proxy via [dbus] and terminates it on revert.
|
||||
// This [Op] is always [Process] scoped.
|
||||
type DBusProxyOp struct {
|
||||
// dbusProxyOp implements [I.ProxyDBus].
|
||||
type dbusProxyOp struct {
|
||||
proxy *dbus.Proxy // populated during apply
|
||||
|
||||
final *dbus.Final
|
||||
@ -81,9 +81,9 @@ type DBusProxyOp struct {
|
||||
system bool
|
||||
}
|
||||
|
||||
func (d *DBusProxyOp) Type() Enablement { return Process }
|
||||
func (d *dbusProxyOp) Type() Enablement { return Process }
|
||||
|
||||
func (d *DBusProxyOp) apply(sys *I) error {
|
||||
func (d *dbusProxyOp) apply(sys *I) error {
|
||||
sys.verbosef("session bus proxy on %q for upstream %q", d.final.Session[1], d.final.Session[0])
|
||||
if d.system {
|
||||
sys.verbosef("system bus proxy on %q for upstream %q", d.final.System[1], d.final.System[0])
|
||||
@ -99,7 +99,7 @@ func (d *DBusProxyOp) apply(sys *I) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DBusProxyOp) revert(sys *I, _ *Criteria) error {
|
||||
func (d *dbusProxyOp) revert(sys *I, _ *Criteria) error {
|
||||
// criteria ignored here since dbus is always process-scoped
|
||||
sys.verbose("terminating message bus proxy")
|
||||
sys.dbusProxyClose(d.proxy)
|
||||
@ -116,8 +116,8 @@ func (d *DBusProxyOp) revert(sys *I, _ *Criteria) error {
|
||||
fmt.Sprintf("message bus proxy error: %v", err), true)
|
||||
}
|
||||
|
||||
func (d *DBusProxyOp) Is(o Op) bool {
|
||||
target, ok := o.(*DBusProxyOp)
|
||||
func (d *dbusProxyOp) Is(o Op) bool {
|
||||
target, ok := o.(*dbusProxyOp)
|
||||
return ok && d != nil && target != nil &&
|
||||
d.system == target.system &&
|
||||
d.final != nil && target.final != nil &&
|
||||
@ -128,8 +128,8 @@ func (d *DBusProxyOp) Is(o Op) bool {
|
||||
reflect.DeepEqual(d.final.WriterTo, target.final.WriterTo)
|
||||
}
|
||||
|
||||
func (d *DBusProxyOp) Path() string { return container.Nonexistent }
|
||||
func (d *DBusProxyOp) String() string { return d.proxy.String() }
|
||||
func (d *dbusProxyOp) Path() string { return container.Nonexistent }
|
||||
func (d *dbusProxyOp) String() string { return d.proxy.String() }
|
||||
|
||||
const (
|
||||
// lpwSizeThreshold is the threshold of bytes written to linePrefixWriter which,
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
|
||||
func TestDBusProxyOp(t *testing.T) {
|
||||
checkOpBehaviour(t, []opBehaviourTestCase{
|
||||
{"dbusProxyStart", 0xdeadbeef, 0xff, &DBusProxyOp{
|
||||
{"dbusProxyStart", 0xdeadbeef, 0xff, &dbusProxyOp{
|
||||
final: dbusNewFinalSample(4),
|
||||
out: new(linePrefixWriter), // panics on write
|
||||
system: true,
|
||||
@ -29,7 +29,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
Msg: "cannot start message bus proxy: unique error 2 injected by the test suite",
|
||||
}, nil, nil},
|
||||
|
||||
{"dbusProxyWait", 0xdeadbeef, 0xff, &DBusProxyOp{
|
||||
{"dbusProxyWait", 0xdeadbeef, 0xff, &dbusProxyOp{
|
||||
final: dbusNewFinalSample(3),
|
||||
}, []stub.Call{
|
||||
call("verbosef", stub.ExpectArgs{"session bus proxy on %q for upstream %q", []any{"/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus", "unix:path=/run/user/1000/bus"}}, nil, nil),
|
||||
@ -45,7 +45,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
Msg: "message bus proxy error: unique error 1 injected by the test suite",
|
||||
}},
|
||||
|
||||
{"success dbusProxyWait cancel", 0xdeadbeef, 0xff, &DBusProxyOp{
|
||||
{"success dbusProxyWait cancel", 0xdeadbeef, 0xff, &dbusProxyOp{
|
||||
final: dbusNewFinalSample(2),
|
||||
system: true,
|
||||
}, []stub.Call{
|
||||
@ -60,7 +60,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
call("verbose", stub.ExpectArgs{[]any{"message bus proxy canceled upstream"}}, nil, nil),
|
||||
}, nil},
|
||||
|
||||
{"success", 0xdeadbeef, 0xff, &DBusProxyOp{
|
||||
{"success", 0xdeadbeef, 0xff, &dbusProxyOp{
|
||||
final: dbusNewFinalSample(1),
|
||||
system: true,
|
||||
}, []stub.Call{
|
||||
@ -154,7 +154,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
Talk: []string{"system\x00"}, Filter: true,
|
||||
})
|
||||
}, []Op{
|
||||
&DBusProxyOp{
|
||||
&dbusProxyOp{
|
||||
final: dbusNewFinalSample(0),
|
||||
system: true,
|
||||
},
|
||||
@ -174,10 +174,10 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
})
|
||||
|
||||
checkOpIs(t, []opIsTestCase{
|
||||
{"nil", (*DBusProxyOp)(nil), (*DBusProxyOp)(nil), false},
|
||||
{"zero", new(DBusProxyOp), new(DBusProxyOp), false},
|
||||
{"nil", (*dbusProxyOp)(nil), (*dbusProxyOp)(nil), false},
|
||||
{"zero", new(dbusProxyOp), new(dbusProxyOp), false},
|
||||
|
||||
{"system differs", &DBusProxyOp{final: &dbus.Final{
|
||||
{"system differs", &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -189,7 +189,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
"--filter", "unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket",
|
||||
}),
|
||||
}, system: false,
|
||||
}, &DBusProxyOp{final: &dbus.Final{
|
||||
}, &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -203,7 +203,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
}, system: true,
|
||||
}, false},
|
||||
|
||||
{"wt differs", &DBusProxyOp{final: &dbus.Final{
|
||||
{"wt differs", &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -215,7 +215,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
"--filter", "unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket",
|
||||
}),
|
||||
}, system: true,
|
||||
}, &DBusProxyOp{final: &dbus.Final{
|
||||
}, &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -229,7 +229,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
}, system: true,
|
||||
}, false},
|
||||
|
||||
{"final system upstream differs", &DBusProxyOp{final: &dbus.Final{
|
||||
{"final system upstream differs", &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -241,7 +241,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
"--filter", "unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket",
|
||||
}),
|
||||
}, system: true,
|
||||
}, &DBusProxyOp{final: &dbus.Final{
|
||||
}, &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -255,7 +255,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
}, system: true,
|
||||
}, false},
|
||||
|
||||
{"final session upstream differs", &DBusProxyOp{final: &dbus.Final{
|
||||
{"final session upstream differs", &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -267,7 +267,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
"--filter", "unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket",
|
||||
}),
|
||||
}, system: true,
|
||||
}, &DBusProxyOp{final: &dbus.Final{
|
||||
}, &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -281,7 +281,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
}, system: true,
|
||||
}, false},
|
||||
|
||||
{"final system differs", &DBusProxyOp{final: &dbus.Final{
|
||||
{"final system differs", &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.1/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -293,7 +293,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
"--filter", "unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket",
|
||||
}),
|
||||
}, system: true,
|
||||
}, &DBusProxyOp{final: &dbus.Final{
|
||||
}, &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -307,7 +307,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
}, system: true,
|
||||
}, false},
|
||||
|
||||
{"final session differs", &DBusProxyOp{final: &dbus.Final{
|
||||
{"final session differs", &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1001/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -319,7 +319,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
"--filter", "unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket",
|
||||
}),
|
||||
}, system: true,
|
||||
}, &DBusProxyOp{final: &dbus.Final{
|
||||
}, &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -333,7 +333,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
}, system: true,
|
||||
}, false},
|
||||
|
||||
{"equals", &DBusProxyOp{final: &dbus.Final{
|
||||
{"equals", &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -345,7 +345,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
"--filter", "unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket",
|
||||
}),
|
||||
}, system: true,
|
||||
}, &DBusProxyOp{final: &dbus.Final{
|
||||
}, &dbusProxyOp{final: &dbus.Final{
|
||||
Session: dbus.ProxyPair{"unix:path=/run/user/1000/bus", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/bus"},
|
||||
System: dbus.ProxyPair{"unix:path=/run/dbus/system_bus_socket", "/tmp/hakurei.0/b186c281d9e83a39afdc66d964ef99c6/system_bus_socket"},
|
||||
|
||||
@ -361,7 +361,7 @@ func TestDBusProxyOp(t *testing.T) {
|
||||
})
|
||||
|
||||
checkOpMeta(t, []opMetaTestCase{
|
||||
{"dbus", new(DBusProxyOp),
|
||||
{"dbus", new(dbusProxyOp),
|
||||
Process, "/proc/nonexistent",
|
||||
"(invalid dbus proxy)"},
|
||||
})
|
||||
|
@ -5,29 +5,29 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Link appends [HardlinkOp] to [I] the [Process] criteria.
|
||||
// Link calls LinkFileType with the [Process] criteria.
|
||||
func (sys *I) Link(oldname, newname string) *I { return sys.LinkFileType(Process, oldname, newname) }
|
||||
|
||||
// LinkFileType appends [HardlinkOp] to [I].
|
||||
// LinkFileType maintains a hardlink until its [Enablement] is no longer satisfied.
|
||||
func (sys *I) LinkFileType(et Enablement, oldname, newname string) *I {
|
||||
sys.ops = append(sys.ops, &HardlinkOp{et, newname, oldname})
|
||||
sys.ops = append(sys.ops, &hardlinkOp{et, newname, oldname})
|
||||
return sys
|
||||
}
|
||||
|
||||
// HardlinkOp maintains a hardlink until its [Enablement] is no longer satisfied.
|
||||
type HardlinkOp struct {
|
||||
// hardlinkOp implements [I.LinkFileType].
|
||||
type hardlinkOp struct {
|
||||
et Enablement
|
||||
dst, src string
|
||||
}
|
||||
|
||||
func (l *HardlinkOp) Type() Enablement { return l.et }
|
||||
func (l *hardlinkOp) Type() Enablement { return l.et }
|
||||
|
||||
func (l *HardlinkOp) apply(*I) error {
|
||||
func (l *hardlinkOp) apply(*I) error {
|
||||
msg.Verbose("linking", l)
|
||||
return newOpError("hardlink", os.Link(l.src, l.dst), false)
|
||||
}
|
||||
|
||||
func (l *HardlinkOp) revert(_ *I, ec *Criteria) error {
|
||||
func (l *hardlinkOp) revert(_ *I, ec *Criteria) error {
|
||||
if ec.hasType(l.Type()) {
|
||||
msg.Verbosef("removing hard link %q", l.dst)
|
||||
return newOpError("hardlink", os.Remove(l.dst), true)
|
||||
@ -37,10 +37,10 @@ func (l *HardlinkOp) revert(_ *I, ec *Criteria) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *HardlinkOp) Is(o Op) bool {
|
||||
target, ok := o.(*HardlinkOp)
|
||||
func (l *hardlinkOp) Is(o Op) bool {
|
||||
target, ok := o.(*hardlinkOp)
|
||||
return ok && l != nil && target != nil && *l == *target
|
||||
}
|
||||
|
||||
func (l *HardlinkOp) Path() string { return l.src }
|
||||
func (l *HardlinkOp) String() string { return fmt.Sprintf("%q from %q", l.dst, l.src) }
|
||||
func (l *hardlinkOp) Path() string { return l.src }
|
||||
func (l *hardlinkOp) String() string { return fmt.Sprintf("%q from %q", l.dst, l.src) }
|
||||
|
@ -6,30 +6,29 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Ensure appends [MkdirOp] to [I] with its [Enablement] ignored.
|
||||
// Ensure ensures the existence of a directory.
|
||||
func (sys *I) Ensure(name string, perm os.FileMode) *I {
|
||||
sys.ops = append(sys.ops, &MkdirOp{User, name, perm, false})
|
||||
sys.ops = append(sys.ops, &mkdirOp{User, name, perm, false})
|
||||
return sys
|
||||
}
|
||||
|
||||
// Ephemeral appends an ephemeral [MkdirOp] to [I].
|
||||
// Ephemeral ensures the existence of a directory until its [Enablement] is no longer satisfied.
|
||||
func (sys *I) Ephemeral(et Enablement, name string, perm os.FileMode) *I {
|
||||
sys.ops = append(sys.ops, &MkdirOp{et, name, perm, true})
|
||||
sys.ops = append(sys.ops, &mkdirOp{et, name, perm, true})
|
||||
return sys
|
||||
}
|
||||
|
||||
// MkdirOp ensures the existence of a directory.
|
||||
// For ephemeral, the directory is destroyed once [Enablement] is no longer satisfied.
|
||||
type MkdirOp struct {
|
||||
// mkdirOp implements [I.Ensure] and [I.Ephemeral].
|
||||
type mkdirOp struct {
|
||||
et Enablement
|
||||
path string
|
||||
perm os.FileMode
|
||||
ephemeral bool
|
||||
}
|
||||
|
||||
func (m *MkdirOp) Type() Enablement { return m.et }
|
||||
func (m *mkdirOp) Type() Enablement { return m.et }
|
||||
|
||||
func (m *MkdirOp) apply(*I) error {
|
||||
func (m *mkdirOp) apply(*I) error {
|
||||
msg.Verbose("ensuring directory", m)
|
||||
|
||||
// create directory
|
||||
@ -44,7 +43,7 @@ func (m *MkdirOp) apply(*I) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MkdirOp) revert(_ *I, ec *Criteria) error {
|
||||
func (m *mkdirOp) revert(_ *I, ec *Criteria) error {
|
||||
if !m.ephemeral {
|
||||
// skip non-ephemeral dir and do not log anything
|
||||
return nil
|
||||
@ -59,14 +58,14 @@ func (m *MkdirOp) revert(_ *I, ec *Criteria) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MkdirOp) Is(o Op) bool {
|
||||
target, ok := o.(*MkdirOp)
|
||||
func (m *mkdirOp) Is(o Op) bool {
|
||||
target, ok := o.(*mkdirOp)
|
||||
return ok && m != nil && target != nil && *m == *target
|
||||
}
|
||||
|
||||
func (m *MkdirOp) Path() string { return m.path }
|
||||
func (m *mkdirOp) Path() string { return m.path }
|
||||
|
||||
func (m *MkdirOp) String() string {
|
||||
func (m *mkdirOp) String() string {
|
||||
t := "ensure"
|
||||
if m.ephemeral {
|
||||
t = TypeString(m.Type())
|
||||
|
@ -21,7 +21,7 @@ func TestEnsure(t *testing.T) {
|
||||
t.Run(tc.name+"_"+tc.perm.String(), func(t *testing.T) {
|
||||
sys := New(t.Context(), 150)
|
||||
sys.Ensure(tc.name, tc.perm)
|
||||
(&tcOp{User, tc.name}).test(t, sys.ops, []Op{&MkdirOp{User, tc.name, tc.perm, false}}, "Ensure")
|
||||
(&tcOp{User, tc.name}).test(t, sys.ops, []Op{&mkdirOp{User, tc.name, tc.perm, false}}, "Ensure")
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ func TestEphemeral(t *testing.T) {
|
||||
t.Run(tc.path+"_"+tc.perm.String()+"_"+TypeString(tc.et), func(t *testing.T) {
|
||||
sys := New(t.Context(), 150)
|
||||
sys.Ephemeral(tc.et, tc.path, tc.perm)
|
||||
tc.test(t, sys.ops, []Op{&MkdirOp{tc.et, tc.path, tc.perm, true}}, "Ephemeral")
|
||||
tc.test(t, sys.ops, []Op{&mkdirOp{tc.et, tc.path, tc.perm, true}}, "Ephemeral")
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -60,7 +60,7 @@ func TestMkdirString(t *testing.T) {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.want, func(t *testing.T) {
|
||||
m := &MkdirOp{
|
||||
m := &mkdirOp{
|
||||
et: tc.et,
|
||||
path: container.Nonexistent,
|
||||
perm: 0701,
|
||||
|
@ -9,16 +9,16 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// CopyFile appends [TmpfileOp] to [I].
|
||||
func (sys *I) CopyFile(payload *[]byte, src string, cap int, n int64) *I {
|
||||
// CopyFile reads up to n bytes from src and writes the resulting byte slice to payloadP.
|
||||
func (sys *I) CopyFile(payloadP *[]byte, src string, cap int, n int64) *I {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.Grow(cap)
|
||||
sys.ops = append(sys.ops, &TmpfileOp{payload, src, n, buf})
|
||||
sys.ops = append(sys.ops, &tmpfileOp{payloadP, src, n, buf})
|
||||
return sys
|
||||
}
|
||||
|
||||
// TmpfileOp reads up to n bytes from src and writes the resulting byte slice to payload.
|
||||
type TmpfileOp struct {
|
||||
// tmpfileOp implements [I.CopyFile].
|
||||
type tmpfileOp struct {
|
||||
payload *[]byte
|
||||
src string
|
||||
|
||||
@ -26,8 +26,9 @@ type TmpfileOp struct {
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
func (t *TmpfileOp) Type() Enablement { return Process }
|
||||
func (t *TmpfileOp) apply(*I) error {
|
||||
func (t *tmpfileOp) Type() Enablement { return Process }
|
||||
|
||||
func (t *tmpfileOp) apply(*I) error {
|
||||
msg.Verbose("copying", t)
|
||||
|
||||
if t.payload == nil {
|
||||
@ -55,12 +56,12 @@ func (t *TmpfileOp) apply(*I) error {
|
||||
*t.payload = t.buf.Bytes()
|
||||
return nil
|
||||
}
|
||||
func (t *TmpfileOp) revert(*I, *Criteria) error { t.buf.Reset(); return nil }
|
||||
func (t *tmpfileOp) revert(*I, *Criteria) error { t.buf.Reset(); return nil }
|
||||
|
||||
func (t *TmpfileOp) Is(o Op) bool {
|
||||
target, ok := o.(*TmpfileOp)
|
||||
func (t *tmpfileOp) Is(o Op) bool {
|
||||
target, ok := o.(*tmpfileOp)
|
||||
return ok && t != nil && target != nil &&
|
||||
t.src == target.src && t.n == target.n
|
||||
}
|
||||
func (t *TmpfileOp) Path() string { return t.src }
|
||||
func (t *TmpfileOp) String() string { return fmt.Sprintf("up to %d bytes from %q", t.n, t.src) }
|
||||
func (t *tmpfileOp) Path() string { return t.src }
|
||||
func (t *tmpfileOp) String() string { return fmt.Sprintf("up to %d bytes from %q", t.n, t.src) }
|
||||
|
@ -18,7 +18,7 @@ func TestCopyFile(t *testing.T) {
|
||||
sys := New(t.Context(), 150)
|
||||
sys.CopyFile(new([]byte), tc.path, tc.cap, tc.n)
|
||||
tc.test(t, sys.ops, []Op{
|
||||
&TmpfileOp{nil, tc.path, tc.n, nil},
|
||||
&tmpfileOp{nil, tc.path, tc.n, nil},
|
||||
}, "CopyFile")
|
||||
})
|
||||
}
|
||||
@ -36,7 +36,7 @@ func TestLink(t *testing.T) {
|
||||
sys := New(t.Context(), 150)
|
||||
sys.Link(tc.src, tc.dst)
|
||||
(&tcOp{Process, tc.src}).test(t, sys.ops, []Op{
|
||||
&HardlinkOp{Process, tc.dst, tc.src},
|
||||
&hardlinkOp{Process, tc.dst, tc.src},
|
||||
}, "Link")
|
||||
})
|
||||
}
|
||||
@ -55,7 +55,7 @@ func TestLinkFileType(t *testing.T) {
|
||||
sys := New(t.Context(), 150)
|
||||
sys.LinkFileType(tc.et, tc.path, tc.dst)
|
||||
tc.test(t, sys.ops, []Op{
|
||||
&HardlinkOp{tc.et, tc.dst, tc.path},
|
||||
&hardlinkOp{tc.et, tc.dst, tc.path},
|
||||
}, "LinkFileType")
|
||||
})
|
||||
}
|
||||
@ -73,7 +73,7 @@ func TestTmpfile_String(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.want, func(t *testing.T) {
|
||||
if got := (&TmpfileOp{src: tc.src, n: tc.n}).String(); got != tc.want {
|
||||
if got := (&tmpfileOp{src: tc.src, n: tc.n}).String(); got != tc.want {
|
||||
t.Errorf("String() = %v, want %v", got, tc.want)
|
||||
}
|
||||
})
|
||||
|
@ -9,16 +9,16 @@ import (
|
||||
"hakurei.app/system/wayland"
|
||||
)
|
||||
|
||||
// Wayland appends [WaylandOp] to [I].
|
||||
// Wayland maintains a wayland socket with security-context-v1 attached via [wayland].
|
||||
// The socket stops accepting connections once the pipe referred to by sync is closed.
|
||||
// The socket is pathname only and is destroyed on revert.
|
||||
func (sys *I) Wayland(syncFd **os.File, dst, src, appID, instanceID string) *I {
|
||||
sys.ops = append(sys.ops, &WaylandOp{syncFd, dst, src, appID, instanceID, wayland.Conn{}})
|
||||
sys.ops = append(sys.ops, &waylandOp{syncFd, dst, src, appID, instanceID, wayland.Conn{}})
|
||||
return sys
|
||||
}
|
||||
|
||||
// WaylandOp maintains a wayland socket with security-context-v1 attached via [wayland].
|
||||
// The socket stops accepting connections once the pipe referred to by sync is closed.
|
||||
// The socket is pathname only and is destroyed on revert.
|
||||
type WaylandOp struct {
|
||||
// waylandOp implements [I.Wayland].
|
||||
type waylandOp struct {
|
||||
sync **os.File
|
||||
dst, src string
|
||||
appID, instanceID string
|
||||
@ -26,9 +26,9 @@ type WaylandOp struct {
|
||||
conn wayland.Conn
|
||||
}
|
||||
|
||||
func (w *WaylandOp) Type() Enablement { return Process }
|
||||
func (w *waylandOp) Type() Enablement { return Process }
|
||||
|
||||
func (w *WaylandOp) apply(sys *I) error {
|
||||
func (w *waylandOp) apply(sys *I) error {
|
||||
if w.sync == nil {
|
||||
// this is a misuse of the API; do not return a wrapped error
|
||||
return errors.New("invalid sync")
|
||||
@ -58,7 +58,7 @@ func (w *WaylandOp) apply(sys *I) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WaylandOp) revert(_ *I, ec *Criteria) error {
|
||||
func (w *waylandOp) revert(_ *I, ec *Criteria) error {
|
||||
if ec.hasType(w.Type()) {
|
||||
msg.Verbosef("removing wayland socket on %q", w.dst)
|
||||
if err := os.Remove(w.dst); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
@ -73,12 +73,12 @@ func (w *WaylandOp) revert(_ *I, ec *Criteria) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WaylandOp) Is(o Op) bool {
|
||||
target, ok := o.(*WaylandOp)
|
||||
func (w *waylandOp) Is(o Op) bool {
|
||||
target, ok := o.(*waylandOp)
|
||||
return ok && w != nil && target != nil &&
|
||||
w.dst == target.dst && w.src == target.src &&
|
||||
w.appID == target.appID && w.instanceID == target.instanceID
|
||||
}
|
||||
|
||||
func (w *WaylandOp) Path() string { return w.dst }
|
||||
func (w *WaylandOp) String() string { return fmt.Sprintf("wayland socket at %q", w.dst) }
|
||||
func (w *waylandOp) Path() string { return w.dst }
|
||||
func (w *waylandOp) String() string { return fmt.Sprintf("wayland socket at %q", w.dst) }
|
||||
|
@ -4,24 +4,24 @@ import (
|
||||
"hakurei.app/system/internal/xcb"
|
||||
)
|
||||
|
||||
// ChangeHosts appends [XHostOp] to [I].
|
||||
// ChangeHosts inserts the target user into X11 hosts and deletes it once its [Enablement] is no longer satisfied.
|
||||
func (sys *I) ChangeHosts(username string) *I {
|
||||
sys.ops = append(sys.ops, XHostOp(username))
|
||||
sys.ops = append(sys.ops, xhostOp(username))
|
||||
return sys
|
||||
}
|
||||
|
||||
// XHostOp inserts the target user into X11 hosts and deletes it once its [Enablement] is no longer satisfied.
|
||||
type XHostOp string
|
||||
// xhostOp implements [I.ChangeHosts].
|
||||
type xhostOp string
|
||||
|
||||
func (x XHostOp) Type() Enablement { return EX11 }
|
||||
func (x xhostOp) Type() Enablement { return EX11 }
|
||||
|
||||
func (x XHostOp) apply(*I) error {
|
||||
func (x xhostOp) apply(*I) error {
|
||||
msg.Verbosef("inserting entry %s to X11", x)
|
||||
return newOpError("xhost",
|
||||
xcb.ChangeHosts(xcb.HostModeInsert, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)), false)
|
||||
}
|
||||
|
||||
func (x XHostOp) revert(_ *I, ec *Criteria) error {
|
||||
func (x xhostOp) revert(_ *I, ec *Criteria) error {
|
||||
if ec.hasType(x.Type()) {
|
||||
msg.Verbosef("deleting entry %s from X11", x)
|
||||
return newOpError("xhost",
|
||||
@ -32,6 +32,6 @@ func (x XHostOp) revert(_ *I, ec *Criteria) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (x XHostOp) Is(o Op) bool { target, ok := o.(XHostOp); return ok && x == target }
|
||||
func (x XHostOp) Path() string { return string(x) }
|
||||
func (x XHostOp) String() string { return string("SI:localuser:" + x) }
|
||||
func (x xhostOp) Is(o Op) bool { target, ok := o.(xhostOp); return ok && x == target }
|
||||
func (x xhostOp) Path() string { return string(x) }
|
||||
func (x xhostOp) String() string { return string("SI:localuser:" + x) }
|
||||
|
@ -11,7 +11,7 @@ func TestChangeHosts(t *testing.T) {
|
||||
sys := New(t.Context(), 150)
|
||||
sys.ChangeHosts(tc)
|
||||
(&tcOp{EX11, tc}).test(t, sys.ops, []Op{
|
||||
XHostOp(tc),
|
||||
xhostOp(tc),
|
||||
}, "ChangeHosts")
|
||||
})
|
||||
}
|
||||
@ -26,7 +26,7 @@ func TestXHost_String(t *testing.T) {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.want, func(t *testing.T) {
|
||||
if got := XHostOp(tc.username).String(); got != tc.want {
|
||||
if got := xhostOp(tc.username).String(); got != tc.want {
|
||||
t.Errorf("String() = %v, want %v", got, tc.want)
|
||||
}
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user