hakurei/internal/app/spruntime.go
Ophestra 699c19e972
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Sandbox (push) Successful in 39s
Test / Sandbox (race detector) (push) Successful in 39s
Test / Hakurei (push) Successful in 42s
Test / Hpkg (push) Successful in 40s
Test / Hakurei (race detector) (push) Successful in 44s
Test / Flake checks (push) Successful in 1m23s
hst/container: optional runtime and tmpdir sharing
Sharing and persisting these directories do not always make sense. Make it optional here.

Closes #16.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-10-19 04:11:38 +09:00

126 lines
3.8 KiB
Go

package app
import (
"encoding/gob"
"hakurei.app/container/bits"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
)
const (
/*
Path to a user-private user-writable directory that is bound
to the user login time on the machine. It is automatically
created the first time a user logs in and removed on the
user's final logout. If a user logs in twice at the same time,
both sessions will see the same $XDG_RUNTIME_DIR and the same
contents. If a user logs in once, then logs out again, and
logs in again, the directory contents will have been lost in
between, but applications should not rely on this behavior and
must be able to deal with stale files. To store
session-private data in this directory, the user should
include the value of $XDG_SESSION_ID in the filename. This
directory shall be used for runtime file system objects such
as AF_UNIX sockets, FIFOs, PID files and similar. It is
guaranteed that this directory is local and offers the
greatest possible file system feature set the operating system
provides. For further details, see the XDG Base Directory
Specification[3]. $XDG_RUNTIME_DIR is not set if the current
user is not the original user of the session.
*/
envXDGRuntimeDir = "XDG_RUNTIME_DIR"
/*
The session class. This may be used instead of class= on the
module parameter line, and is usually preferred.
*/
envXDGSessionClass = "XDG_SESSION_CLASS"
/*
A regular interactive user session. This is the default class
for sessions for which a TTY or X display is known at session
registration time.
*/
xdgSessionClassUser = "user"
/*
The session type. This may be used instead of type= on the
module parameter line, and is usually preferred.
One of "unspecified", "tty", "x11", "wayland", "mir", or "web".
*/
envXDGSessionType = "XDG_SESSION_TYPE"
)
func init() { gob.Register(new(spRuntimeOp)) }
const (
sessionTypeUnspec = iota
sessionTypeTTY
sessionTypeX11
sessionTypeWayland
)
// spRuntimeOp sets up XDG_RUNTIME_DIR inside the container.
type spRuntimeOp struct {
// SessionType determines the value of envXDGSessionType. Populated during toSystem.
SessionType uintptr
}
func (s *spRuntimeOp) toSystem(state *outcomeStateSys) error {
if state.Container.Flags&hst.FShareRuntime != 0 {
runtimeDir, runtimeDirInst := s.commonPaths(state.outcomeState)
state.sys.Ensure(runtimeDir, 0700)
state.sys.UpdatePermType(system.User, runtimeDir, acl.Execute)
state.sys.Ensure(runtimeDirInst, 0700)
state.sys.UpdatePermType(system.User, runtimeDirInst, acl.Read, acl.Write, acl.Execute)
}
if state.et&hst.EWayland != 0 {
s.SessionType = sessionTypeWayland
} else if state.et&hst.EX11 != 0 {
s.SessionType = sessionTypeX11
} else {
s.SessionType = sessionTypeTTY
}
return nil
}
func (s *spRuntimeOp) toContainer(state *outcomeStateParams) error {
state.runtimeDir = fhs.AbsRunUser.Append(state.mapuid.String())
state.env[envXDGRuntimeDir] = state.runtimeDir.String()
state.env[envXDGSessionClass] = xdgSessionClassUser
switch s.SessionType {
case sessionTypeUnspec:
state.env[envXDGSessionType] = "unspecified"
case sessionTypeTTY:
state.env[envXDGSessionType] = "tty"
case sessionTypeX11:
state.env[envXDGSessionType] = "x11"
case sessionTypeWayland:
state.env[envXDGSessionType] = "wayland"
}
state.params.Tmpfs(fhs.AbsRunUser, 1<<12, 0755)
if state.Container.Flags&hst.FShareRuntime != 0 {
_, runtimeDirInst := s.commonPaths(state.outcomeState)
state.params.Bind(runtimeDirInst, state.runtimeDir, bits.BindWritable)
} else {
state.params.Mkdir(state.runtimeDir, 0700)
}
return nil
}
func (s *spRuntimeOp) commonPaths(state *outcomeState) (runtimeDir, runtimeDirInst *check.Absolute) {
runtimeDir = state.sc.SharePath.Append("runtime")
runtimeDirInst = runtimeDir.Append(state.identity.String())
return
}