aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/outcome/hsu.go1
-rw-r--r--internal/outcome/outcome.go84
-rw-r--r--internal/outcome/process.go53
-rw-r--r--internal/outcome/shim.go30
-rw-r--r--internal/outcome/spcontainer.go22
-rw-r--r--internal/outcome/spdbus.go1
-rw-r--r--internal/outcome/sppipewire.go5
-rw-r--r--internal/outcome/sppulse.go49
-rw-r--r--internal/outcome/spruntime.go4
-rw-r--r--internal/outcome/spwayland.go5
-rw-r--r--internal/outcome/spx11.go5
11 files changed, 189 insertions, 70 deletions
diff --git a/internal/outcome/hsu.go b/internal/outcome/hsu.go
index c1be6761..84751b45 100644
--- a/internal/outcome/hsu.go
+++ b/internal/outcome/hsu.go
@@ -38,6 +38,7 @@ func (h *Hsu) ensureDispatcher() {
}
// ID returns the current user hsurc identifier.
+//
// [ErrHsuAccess] is returned if the current user is not in hsurc.
func (h *Hsu) ID() (int, error) {
h.ensureDispatcher()
diff --git a/internal/outcome/outcome.go b/internal/outcome/outcome.go
index 3516eaef..42b50389 100644
--- a/internal/outcome/outcome.go
+++ b/internal/outcome/outcome.go
@@ -1,4 +1,5 @@
-// Package outcome implements the outcome of the privileged and container sides of a hakurei container.
+// Package outcome implements the outcome of the privileged and container sides
+// of a hakurei container.
package outcome
import (
@@ -27,8 +28,9 @@ func Info() *hst.Info {
return &hi
}
-// envAllocSize is the initial size of the env map pre-allocated when the configured env map is nil.
-// It should be large enough to fit all insertions by outcomeOp.toContainer.
+// envAllocSize is the initial size of the env map pre-allocated when the
+// configured env map is nil. It should be large enough to fit all insertions by
+// outcomeOp.toContainer.
const envAllocSize = 1 << 6
func newInt(v int) *stringPair[int] { return &stringPair[int]{v, strconv.Itoa(v)} }
@@ -43,7 +45,8 @@ func (s *stringPair[T]) unwrap() T { return s.v }
func (s *stringPair[T]) String() string { return s.s }
// outcomeState is copied to the shim process and available while applying outcomeOp.
-// This is transmitted from the priv side to the shim, so exported fields should be kept to a minimum.
+// This is transmitted from the priv side to the shim, so exported fields should
+// be kept to a minimum.
type outcomeState struct {
// Params only used by the shim process. Populated by populateEarly.
Shim *shimParams
@@ -89,10 +92,15 @@ func (s *outcomeState) valid() bool {
s.Paths != nil
}
-// newOutcomeState returns the address of a new outcomeState with its exported fields populated via syscallDispatcher.
+// newOutcomeState returns the address of a new outcomeState with its exported
+// fields populated via syscallDispatcher.
func newOutcomeState(k syscallDispatcher, msg message.Msg, id *hst.ID, config *hst.Config, hsu *Hsu) *outcomeState {
s := outcomeState{
- Shim: &shimParams{PrivPID: k.getpid(), Verbose: msg.IsVerbose()},
+ Shim: &shimParams{
+ PrivPID: k.getpid(),
+ Verbose: msg.IsVerbose(),
+ },
+
ID: id,
Identity: config.Identity,
UserID: hsu.MustID(msg),
@@ -121,6 +129,7 @@ func newOutcomeState(k syscallDispatcher, msg message.Msg, id *hst.ID, config *h
}
// populateLocal populates unexported fields from transmitted exported fields.
+//
// These fields are cheaper to recompute per-process.
func (s *outcomeState) populateLocal(k syscallDispatcher, msg message.Msg) error {
if !s.valid() || k == nil || msg == nil {
@@ -136,7 +145,10 @@ func (s *outcomeState) populateLocal(k syscallDispatcher, msg message.Msg) error
s.id = &stringPair[hst.ID]{*s.ID, s.ID.String()}
s.Copy(&s.sc, s.UserID)
- msg.Verbosef("process share directory at %q, runtime directory at %q", s.sc.SharePath, s.sc.RunDirPath)
+ msg.Verbosef(
+ "process share directory at %q, runtime directory at %q",
+ s.sc.SharePath, s.sc.RunDirPath,
+ )
s.identity = newInt(s.Identity)
s.mapuid, s.mapgid = newInt(s.Mapuid), newInt(s.Mapgid)
@@ -146,17 +158,25 @@ func (s *outcomeState) populateLocal(k syscallDispatcher, msg message.Msg) error
}
// instancePath returns a path formatted for outcomeStateSys.instance.
+//
// This method must only be called from outcomeOp.toContainer if
// outcomeOp.toSystem has already called outcomeStateSys.instance.
-func (s *outcomeState) instancePath() *check.Absolute { return s.sc.SharePath.Append(s.id.String()) }
+func (s *outcomeState) instancePath() *check.Absolute {
+ return s.sc.SharePath.Append(s.id.String())
+}
// runtimePath returns a path formatted for outcomeStateSys.runtime.
+//
// This method must only be called from outcomeOp.toContainer if
// outcomeOp.toSystem has already called outcomeStateSys.runtime.
-func (s *outcomeState) runtimePath() *check.Absolute { return s.sc.RunDirPath.Append(s.id.String()) }
+func (s *outcomeState) runtimePath() *check.Absolute {
+ return s.sc.RunDirPath.Append(s.id.String())
+}
// outcomeStateSys wraps outcomeState and [system.I]. Used on the priv side only.
-// Implementations of outcomeOp must not access fields other than sys unless explicitly stated.
+//
+// Implementations of outcomeOp must not access fields other than sys unless
+// explicitly stated.
type outcomeStateSys struct {
// Whether XDG_RUNTIME_DIR is used post hsu.
useRuntimeDir bool
@@ -219,6 +239,7 @@ func (state *outcomeStateSys) ensureRuntimeDir() {
}
// instance returns the pathname to a process-specific directory within TMPDIR.
+//
// This directory must only hold entries bound to [system.Process].
func (state *outcomeStateSys) instance() *check.Absolute {
if state.sharePath != nil {
@@ -230,6 +251,7 @@ func (state *outcomeStateSys) instance() *check.Absolute {
}
// runtime returns the pathname to a process-specific directory within XDG_RUNTIME_DIR.
+//
// This directory must only hold entries bound to [system.Process].
func (state *outcomeStateSys) runtime() *check.Absolute {
if state.runtimeSharePath != nil {
@@ -242,22 +264,29 @@ func (state *outcomeStateSys) runtime() *check.Absolute {
return state.runtimeSharePath
}
-// outcomeStateParams wraps outcomeState and [container.Params]. Used on the shim side only.
+// outcomeStateParams wraps outcomeState and [container.Params].
+//
+// Used on the shim side only.
type outcomeStateParams struct {
- // Overrides the embedded [container.Params] in [container.Container]. The Env field must not be used.
+ // Overrides the embedded [container.Params] in [container.Container].
+ //
+ // The Env field must not be used.
params *container.Params
// Collapsed into the Env slice in [container.Params] by the final outcomeOp.
env map[string]string
- // Filesystems with the optional root sliced off if present. Populated by spParamsOp.
- // Safe for use by spFilesystemOp.
+ // Filesystems with the optional root sliced off if present.
+ //
+ // Populated by spParamsOp. Safe for use by spFilesystemOp.
filesystem []hst.FilesystemConfigJSON
// Inner XDG_RUNTIME_DIR default formatting of `/run/user/%d` via mapped uid.
+ //
// Populated by spRuntimeOp.
runtimeDir *check.Absolute
// Path to pipewire-pulse server.
+ //
// Populated by spPipeWireOp if DirectPipeWire is false.
pipewirePulsePath *check.Absolute
@@ -265,25 +294,32 @@ type outcomeStateParams struct {
*outcomeState
}
-// errNotEnabled is returned by outcomeOp.toSystem and used internally to exclude an outcomeOp from transmission.
+// errNotEnabled is returned by outcomeOp.toSystem and used internally to
+// exclude an outcomeOp from transmission.
var errNotEnabled = errors.New("op not enabled in the configuration")
-// An outcomeOp inflicts an outcome on [system.I] and contains enough information to
-// inflict it on [container.Params] in a separate process.
-// An implementation of outcomeOp must store cross-process states in exported fields only.
+// An outcomeOp inflicts an outcome on [system.I] and contains enough
+// information to inflict it on [container.Params] in a separate process.
+//
+// An implementation of outcomeOp must store cross-process states in exported
+// fields only.
type outcomeOp interface {
// toSystem inflicts the current outcome on [system.I] in the priv side process.
toSystem(state *outcomeStateSys) error
- // toContainer inflicts the current outcome on [container.Params] in the shim process.
- // The implementation must not write to the Env field of [container.Params] as it will be overwritten
- // by flattened env map.
+ // toContainer inflicts the current outcome on [container.Params] in the
+ // shim process.
+ //
+ // Implementations must not write to the Env field of [container.Params]
+ // as it will be overwritten by flattened env map.
toContainer(state *outcomeStateParams) error
}
-// toSystem calls the outcomeOp.toSystem method on all outcomeOp implementations and populates shimParams.Ops.
-// This function assumes the caller has already called the Validate method on [hst.Config]
-// and checked that it returns nil.
+// toSystem calls the outcomeOp.toSystem method on all outcomeOp implementations
+// and populates shimParams.Ops.
+//
+// This function assumes the caller has already called the Validate method on
+// [hst.Config] and checked that it returns nil.
func (state *outcomeStateSys) toSystem() error {
if state.Shim == nil || state.Shim.Ops != nil {
return newWithMessage("invalid ops state reached")
diff --git a/internal/outcome/process.go b/internal/outcome/process.go
index e7b7113d..be919a63 100644
--- a/internal/outcome/process.go
+++ b/internal/outcome/process.go
@@ -30,7 +30,9 @@ const (
)
// NewStore returns the address of a new instance of [store.Store].
-func NewStore(sc *hst.Paths) *store.Store { return store.New(sc.SharePath.Append("state")) }
+func NewStore(sc *hst.Paths) *store.Store {
+ return store.New(sc.SharePath.Append("state"))
+}
// main carries out outcome and terminates. main does not return.
func (k *outcome) main(msg message.Msg, identifierFd int) {
@@ -116,7 +118,11 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
processStatePrev, processStateCur = processStateCur, processState
if !processTime.IsZero() && processStatePrev != processLifecycle {
- msg.Verbosef("state %d took %.2f ms", processStatePrev, float64(time.Since(processTime).Nanoseconds())/1e6)
+ msg.Verbosef(
+ "state %d took %.2f ms",
+ processStatePrev,
+ float64(time.Since(processTime).Nanoseconds())/1e6,
+ )
}
processTime = time.Now()
@@ -141,7 +147,10 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
case processCommit:
if isBeforeRevert {
- perrorFatal(newWithMessage("invalid transition to commit state"), "commit", processLifecycle)
+ perrorFatal(
+ newWithMessage("invalid transition to commit state"),
+ "commit", processLifecycle,
+ )
continue
}
@@ -238,15 +247,26 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
case <-func() chan struct{} {
w := make(chan struct{})
- // this ties processLifecycle to ctx with the additional compensated timeout duration
- // to allow transition to the next state on a locked up shim
- go func() { <-ctx.Done(); time.Sleep(k.state.Shim.WaitDelay + shimWaitTimeout); close(w) }()
+ // This ties processLifecycle to ctx with the additional
+ // compensated timeout duration to allow transition to the next
+ // state on a locked up shim.
+ go func() {
+ <-ctx.Done()
+ time.Sleep(k.state.Shim.WaitDelay + shimWaitTimeout)
+ close(w)
+ }()
return w
}():
- // this is only reachable when wait did not return within shimWaitTimeout, after its WaitDelay has elapsed.
- // This is different from the container failing to terminate within its timeout period, as that is enforced
- // by the shim. This path is instead reached when there is a lockup in shim preventing it from completing.
- msg.GetLogger().Printf("process %d did not terminate", shimCmd.Process.Pid)
+ // This is only reachable when wait did not return within
+ // shimWaitTimeout, after its WaitDelay has elapsed. This is
+ // different from the container failing to terminate within its
+ // timeout period, as that is enforced by the shim. This path is
+ // instead reached when there is a lockup in shim preventing it
+ // from completing.
+ msg.GetLogger().Printf(
+ "process %d did not terminate",
+ shimCmd.Process.Pid,
+ )
}
msg.Resume()
@@ -271,8 +291,8 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
ec := system.Process
if entries, _, err := handle.Entries(); err != nil {
- // it is impossible to continue from this point,
- // per-process state will be reverted to limit damage
+ // it is impossible to continue from this point, per-process
+ // state will be reverted to limit damage
perror(err, "read store segment entries")
} else {
// accumulate enablements of remaining instances
@@ -295,7 +315,10 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
if n == 0 {
ec |= system.User
} else {
- msg.Verbosef("found %d instances, cleaning up without user-scoped operations", n)
+ msg.Verbosef(
+ "found %d instances, cleaning up without user-scoped operations",
+ n,
+ )
}
ec |= rt ^ (hst.EWayland | hst.EX11 | hst.EDBus | hst.EPulse)
if msg.IsVerbose() {
@@ -335,7 +358,9 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
// start starts the shim via cmd/hsu.
//
-// If successful, a [time.Time] value for [hst.State] is stored in the value pointed to by startTime.
+// If successful, a [time.Time] value for [hst.State] is stored in the value
+// pointed to by startTime.
+//
// The resulting [exec.Cmd] and write end of the shim setup pipe is returned.
func (k *outcome) start(ctx context.Context, msg message.Msg,
hsuPath *check.Absolute,
diff --git a/internal/outcome/shim.go b/internal/outcome/shim.go
index a569e7a6..8fc46f2a 100644
--- a/internal/outcome/shim.go
+++ b/internal/outcome/shim.go
@@ -37,9 +37,12 @@ const (
shimMsgBadPID = C.HAKUREI_SHIM_BAD_PID
)
-// setupContSignal sets up the SIGCONT signal handler for the cross-uid shim exit hack.
-// The signal handler is implemented in C, signals can be processed by reading from the returned reader.
-// The returned function must be called after all signal processing concludes.
+// setupContSignal sets up the SIGCONT signal handler for the cross-uid shim
+// exit hack.
+//
+// The signal handler is implemented in C, signals can be processed by reading
+// from the returned reader. The returned function must be called after all
+// signal processing concludes.
func setupContSignal(pid int) (io.ReadCloser, func(), error) {
if r, w, err := os.Pipe(); err != nil {
return nil, nil, err
@@ -51,22 +54,28 @@ func setupContSignal(pid int) (io.ReadCloser, func(), error) {
}
}
-// shimEnv is the name of the environment variable storing decimal representation of
-// setup pipe fd for [container.Receive].
+// shimEnv is the name of the environment variable storing decimal representation
+// of setup pipe fd for [container.Receive].
const shimEnv = "HAKUREI_SHIM"
// shimParams is embedded in outcomeState and transmitted from priv side to shim.
type shimParams struct {
- // Priv side pid, checked against ppid in signal handler for the syscall.SIGCONT hack.
+ // Priv side pid, checked against ppid in signal handler for the
+ // syscall.SIGCONT hack.
PrivPID int
- // Duration to wait for after the initial process receives os.Interrupt before the container is killed.
+ // Duration to wait for after the initial process receives os.Interrupt
+ // before the container is killed.
+ //
// Limits are enforced on the priv side.
WaitDelay time.Duration
// Verbosity pass through from [message.Msg].
Verbose bool
+ // Copied from [hst.Config].
+ SchedPolicy std.SchedPolicy
+
// Outcome setup ops, contains setup state. Populated by outcome.finalise.
Ops []outcomeOp
}
@@ -77,7 +86,9 @@ func (p *shimParams) valid() bool { return p != nil && p.PrivPID > 0 }
// shimName is the prefix used by log.std in the shim process.
const shimName = "shim"
-// Shim is called by the main function of the shim process and runs as the unconstrained target user.
+// Shim is called by the main function of the shim process and runs as the
+// unconstrained target user.
+//
// Shim does not return.
func Shim(msg message.Msg) {
if msg == nil {
@@ -131,7 +142,8 @@ func (sp *shimPrivate) destroy() {
}
const (
- // shimPipeWireTimeout is the duration pipewire-pulse is allowed to run before its socket becomes available.
+ // shimPipeWireTimeout is the duration pipewire-pulse is allowed to run
+ // before its socket becomes available.
shimPipeWireTimeout = 5 * time.Second
)
diff --git a/internal/outcome/spcontainer.go b/internal/outcome/spcontainer.go
index 768e6bc5..2d6bb78b 100644
--- a/internal/outcome/spcontainer.go
+++ b/internal/outcome/spcontainer.go
@@ -27,7 +27,9 @@ const varRunNscd = fhs.Var + "run/nscd"
func init() { gob.Register(new(spParamsOp)) }
-// spParamsOp initialises unordered fields of [container.Params] and the optional root filesystem.
+// spParamsOp initialises unordered fields of [container.Params] and the
+// optional root filesystem.
+//
// This outcomeOp is hardcoded to always run first.
type spParamsOp struct {
// Value of $TERM, stored during toSystem.
@@ -67,8 +69,8 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
state.params.Args = state.Container.Args
}
- // the container is canceled when shim is requested to exit or receives an interrupt or termination signal;
- // this behaviour is implemented in the shim
+ // The container is cancelled when shim is requested to exit or receives an
+ // interrupt or termination signal. This behaviour is implemented in the shim.
state.params.ForwardCancel = state.Shim.WaitDelay > 0
if state.Container.Flags&hst.FMultiarch != 0 {
@@ -115,7 +117,8 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
} else {
state.params.Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice)
}
- // /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it
+ // /dev is mounted readonly later on, this prevents /dev/shm from going
+ // readonly with it
state.params.Tmpfs(fhs.AbsDevShm, 0, 01777)
return nil
@@ -123,7 +126,9 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
func init() { gob.Register(new(spFilesystemOp)) }
-// spFilesystemOp applies configured filesystems to [container.Params], excluding the optional root filesystem.
+// spFilesystemOp applies configured filesystems to [container.Params],
+// excluding the optional root filesystem.
+//
// This outcomeOp is hardcoded to always run last.
type spFilesystemOp struct {
// Matched paths to cover. Stored during toSystem.
@@ -297,8 +302,8 @@ func (s *spFilesystemOp) toContainer(state *outcomeStateParams) error {
return nil
}
-// resolveRoot handles the root filesystem special case for [hst.FilesystemConfig] and additionally resolves autoroot
-// as it requires special handling during path hiding.
+// resolveRoot handles the root filesystem special case for [hst.FilesystemConfig]
+// and additionally resolves autoroot as it requires special handling during path hiding.
func resolveRoot(c *hst.ContainerConfig) (rootfs hst.FilesystemConfig, filesystem []hst.FilesystemConfigJSON, autoroot *hst.FSBind) {
// root filesystem special case
filesystem = c.Filesystem
@@ -316,7 +321,8 @@ func resolveRoot(c *hst.ContainerConfig) (rootfs hst.FilesystemConfig, filesyste
return
}
-// evalSymlinks calls syscallDispatcher.evalSymlinks but discards errors unwrapping to [fs.ErrNotExist].
+// evalSymlinks calls syscallDispatcher.evalSymlinks but discards errors
+// unwrapping to [fs.ErrNotExist].
func evalSymlinks(msg message.Msg, k syscallDispatcher, v *string) error {
if p, err := k.evalSymlinks(*v); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
diff --git a/internal/outcome/spdbus.go b/internal/outcome/spdbus.go
index 8b3fbdbc..5939ede9 100644
--- a/internal/outcome/spdbus.go
+++ b/internal/outcome/spdbus.go
@@ -12,6 +12,7 @@ import (
func init() { gob.Register(new(spDBusOp)) }
// spDBusOp maintains an xdg-dbus-proxy instance for the container.
+//
// Runs after spRuntimeOp.
type spDBusOp struct {
// Whether to bind the system bus socket. Populated during toSystem.
diff --git a/internal/outcome/sppipewire.go b/internal/outcome/sppipewire.go
index 8c5760bd..96675ebf 100644
--- a/internal/outcome/sppipewire.go
+++ b/internal/outcome/sppipewire.go
@@ -13,9 +13,12 @@ const pipewirePulseName = "pipewire-pulse"
func init() { gob.Register(new(spPipeWireOp)) }
// spPipeWireOp exports the PipeWire server to the container via SecurityContext.
+//
// Runs after spRuntimeOp.
type spPipeWireOp struct {
- // Path to pipewire-pulse server. Populated during toSystem if DirectPipeWire is false.
+ // Path to pipewire-pulse server.
+ //
+ // Populated during toSystem if DirectPipeWire is false.
CompatServerPath *check.Absolute
}
diff --git a/internal/outcome/sppulse.go b/internal/outcome/sppulse.go
index e86fb3f8..386800bb 100644
--- a/internal/outcome/sppulse.go
+++ b/internal/outcome/sppulse.go
@@ -20,6 +20,7 @@ const pulseCookieSizeMax = 1 << 8
func init() { gob.Register(new(spPulseOp)) }
// spPulseOp exports the PulseAudio server to the container.
+//
// Runs after spRuntimeOp.
type spPulseOp struct {
// PulseAudio cookie data, populated during toSystem if a cookie is present.
@@ -37,24 +38,40 @@ func (s *spPulseOp) toSystem(state *outcomeStateSys) error {
if _, err := state.k.stat(pulseRuntimeDir.String()); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
- return &hst.AppError{Step: fmt.Sprintf("access PulseAudio directory %q", pulseRuntimeDir), Err: err}
+ return &hst.AppError{Step: fmt.Sprintf(
+ "access PulseAudio directory %q",
+ pulseRuntimeDir,
+ ), Err: err}
}
- return newWithMessageError(fmt.Sprintf("PulseAudio directory %q not found", pulseRuntimeDir), err)
+ return newWithMessageError(fmt.Sprintf(
+ "PulseAudio directory %q not found",
+ pulseRuntimeDir,
+ ), err)
}
if fi, err := state.k.stat(pulseSocket.String()); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
- return &hst.AppError{Step: fmt.Sprintf("access PulseAudio socket %q", pulseSocket), Err: err}
+ return &hst.AppError{Step: fmt.Sprintf(
+ "access PulseAudio socket %q",
+ pulseSocket,
+ ), Err: err}
}
- return newWithMessageError(fmt.Sprintf("PulseAudio directory %q found but socket does not exist", pulseRuntimeDir), err)
+ return newWithMessageError(fmt.Sprintf(
+ "PulseAudio directory %q found but socket does not exist",
+ pulseRuntimeDir,
+ ), err)
} else {
if m := fi.Mode(); m&0o006 != 0o006 {
- return newWithMessage(fmt.Sprintf("unexpected permissions on %q: %s", pulseSocket, m))
+ return newWithMessage(fmt.Sprintf(
+ "unexpected permissions on %q: %s",
+ pulseSocket, m,
+ ))
}
}
- // pulse socket is world writable and its parent directory DAC permissions prevents access;
- // hard link to target-executable share directory to grant access
+ // PulseAudio socket is world writable and its parent directory DAC
+ // permissions prevents access. Hard link to target-executable share
+ // directory to grant access
state.sys.Link(pulseSocket, state.runtime().Append("pulse"))
// load up to pulseCookieSizeMax bytes of pulse cookie for transmission to shim
@@ -62,7 +79,13 @@ func (s *spPulseOp) toSystem(state *outcomeStateSys) error {
return err
} else if a != nil {
s.Cookie = new([pulseCookieSizeMax]byte)
- if s.CookieSize, err = loadFile(state.msg, state.k, "PulseAudio cookie", a.String(), s.Cookie[:]); err != nil {
+ if s.CookieSize, err = loadFile(
+ state.msg,
+ state.k,
+ "PulseAudio cookie",
+ a.String(),
+ s.Cookie[:],
+ ); err != nil {
return err
}
} else {
@@ -101,8 +124,9 @@ func (s *spPulseOp) commonPaths(state *outcomeState) (pulseRuntimeDir, pulseSock
return
}
-// discoverPulseCookie attempts to discover the pathname of the PulseAudio cookie of the current user.
-// If both returned pathname and error are nil, the cookie is likely unavailable and can be silently skipped.
+// discoverPulseCookie attempts to discover the pathname of the PulseAudio
+// cookie of the current user. If both returned pathname and error are nil, the
+// cookie is likely unavailable and can be silently skipped.
func discoverPulseCookie(k syscallDispatcher) (*check.Absolute, error) {
const paLocateStep = "locate PulseAudio cookie"
@@ -186,7 +210,10 @@ func loadFile(
&os.PathError{Op: "stat", Path: pathname, Err: syscall.ENOMEM},
)
} else if s < int64(n) {
- msg.Verbosef("%s at %q is %d bytes shorter than expected", description, pathname, int64(n)-s)
+ msg.Verbosef(
+ "%s at %q is %d bytes shorter than expected",
+ description, pathname, int64(n)-s,
+ )
} else {
msg.Verbosef("loading %d bytes from %q", n, pathname)
}
diff --git a/internal/outcome/spruntime.go b/internal/outcome/spruntime.go
index 6ec532bb..727a5be0 100644
--- a/internal/outcome/spruntime.go
+++ b/internal/outcome/spruntime.go
@@ -67,7 +67,9 @@ const (
// spRuntimeOp sets up XDG_RUNTIME_DIR inside the container.
type spRuntimeOp struct {
- // SessionType determines the value of envXDGSessionType. Populated during toSystem.
+ // SessionType determines the value of envXDGSessionType.
+ //
+ // Populated during toSystem.
SessionType uintptr
}
diff --git a/internal/outcome/spwayland.go b/internal/outcome/spwayland.go
index 7eccce2f..55066611 100644
--- a/internal/outcome/spwayland.go
+++ b/internal/outcome/spwayland.go
@@ -12,9 +12,12 @@ import (
func init() { gob.Register(new(spWaylandOp)) }
// spWaylandOp exports the Wayland display server to the container.
+//
// Runs after spRuntimeOp.
type spWaylandOp struct {
- // Path to host wayland socket. Populated during toSystem if DirectWayland is true.
+ // Path to host wayland socket.
+ //
+ // Populated during toSystem if DirectWayland is true.
SocketPath *check.Absolute
}
diff --git a/internal/outcome/spx11.go b/internal/outcome/spx11.go
index fd2b273a..70ab2421 100644
--- a/internal/outcome/spx11.go
+++ b/internal/outcome/spx11.go
@@ -50,7 +50,10 @@ func (s *spX11Op) toSystem(state *outcomeStateSys) error {
if socketPath != nil {
if _, err := state.k.stat(socketPath.String()); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
- return &hst.AppError{Step: fmt.Sprintf("access X11 socket %q", socketPath), Err: err}
+ return &hst.AppError{Step: fmt.Sprintf(
+ "access X11 socket %q",
+ socketPath,
+ ), Err: err}
}
} else {
state.sys.UpdatePermType(hst.EX11, socketPath, acl.Read, acl.Write, acl.Execute)