All checks were successful
Test / Create distribution (push) Successful in 47s
Test / Sandbox (push) Successful in 2m48s
Test / ShareFS (push) Successful in 4m51s
Test / Sandbox (race detector) (push) Successful in 5m11s
Test / Hpkg (push) Successful in 5m24s
Test / Hakurei (push) Successful in 5m43s
Test / Hakurei (race detector) (push) Successful in 7m36s
Test / Flake checks (push) Successful in 1m57s
The struct turned out not necessary during initial implementation but was not unwrapped into its single string field. This change replaces it with the underlying string and removes the indirection. 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"
|
|
|
|
"hakurei.app/container/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 !path.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(path.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)
|
|
}
|