forked from rosa/hakurei
This makes package check portable, and removes nonportable behaviour from package pkg, pipewire, and system. All other packages remain nonportable due to their nature. No latency increase was observed due to this change on amd64 and arm64 linux. Signed-off-by: Ophestra <cat@gensokyo.uk>
66 lines
1.7 KiB
Go
66 lines
1.7 KiB
Go
package container
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"fmt"
|
|
"path/filepath"
|
|
|
|
"hakurei.app/check"
|
|
)
|
|
|
|
func init() { gob.Register(new(SymlinkOp)) }
|
|
|
|
// Link appends an [Op] that creates a symlink in the container filesystem.
|
|
func (f *Ops) Link(target *check.Absolute, linkName string, dereference bool) *Ops {
|
|
*f = append(*f, &SymlinkOp{target, linkName, dereference})
|
|
return f
|
|
}
|
|
|
|
// SymlinkOp optionally dereferences LinkName and creates a symlink at container path Target.
|
|
type SymlinkOp struct {
|
|
Target *check.Absolute
|
|
// LinkName is an arbitrary uninterpreted pathname.
|
|
LinkName string
|
|
|
|
// Dereference causes LinkName to be dereferenced during early.
|
|
Dereference bool
|
|
}
|
|
|
|
func (l *SymlinkOp) Valid() bool { return l != nil && l.Target != nil && l.LinkName != zeroString }
|
|
|
|
func (l *SymlinkOp) early(_ *setupState, k syscallDispatcher) error {
|
|
if l.Dereference {
|
|
if !filepath.IsAbs(l.LinkName) {
|
|
return check.AbsoluteError(l.LinkName)
|
|
}
|
|
if name, err := k.readlink(l.LinkName); err != nil {
|
|
return err
|
|
} else {
|
|
l.LinkName = name
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (l *SymlinkOp) apply(state *setupState, k syscallDispatcher) error {
|
|
target := toSysroot(l.Target.String())
|
|
if err := k.mkdirAll(filepath.Dir(target), state.ParentPerm); err != nil {
|
|
return err
|
|
}
|
|
return k.symlink(l.LinkName, target)
|
|
}
|
|
|
|
func (l *SymlinkOp) late(*setupState, syscallDispatcher) error { return nil }
|
|
|
|
func (l *SymlinkOp) Is(op Op) bool {
|
|
vl, ok := op.(*SymlinkOp)
|
|
return ok && l.Valid() && vl.Valid() &&
|
|
l.Target.Is(vl.Target) &&
|
|
l.LinkName == vl.LinkName &&
|
|
l.Dereference == vl.Dereference
|
|
}
|
|
func (*SymlinkOp) prefix() (string, bool) { return "creating", true }
|
|
func (l *SymlinkOp) String() string {
|
|
return fmt.Sprintf("symlink on %q linkname %q", l.Target, l.LinkName)
|
|
}
|