diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-08-12 04:38:45 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-08-14 04:52:49 +0900 |
| commit | 99ac96511bed17f48d908db3d00a1f48579ba011 (patch) | |
| tree | 30d404efb7256c9f053f64192068637d6b846db4 /hst/fsbind.go | |
| parent | e99d7affb0c128fa82722f9b3d79c99b5e5918cd (diff) | |
hst/fs: interface filesystem config
This allows mount points to be represented by different underlying structs.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'hst/fsbind.go')
| -rw-r--r-- | hst/fsbind.go | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/hst/fsbind.go b/hst/fsbind.go new file mode 100644 index 00000000..e95eb7b7 --- /dev/null +++ b/hst/fsbind.go @@ -0,0 +1,102 @@ +package hst + +import ( + "encoding/gob" + "strings" + + "hakurei.app/container" +) + +func init() { gob.Register(new(FSBind)) } + +// FilesystemBind is the [FilesystemConfig.Type] name of a bind mount point. +const FilesystemBind = "bind" + +// FSBind represents a host to container bind mount. +type FSBind struct { + // mount point in container, same as src if empty + Dst *container.Absolute `json:"dst,omitempty"` + // host filesystem path to make available to the container + Src *container.Absolute `json:"src"` + // do not mount filesystem read-only + Write bool `json:"write,omitempty"` + // do not disable device files, implies Write + Device bool `json:"dev,omitempty"` + // skip this mount point if the host path does not exist + Optional bool `json:"optional,omitempty"` +} + +func (b *FSBind) Type() string { return FilesystemBind } + +func (b *FSBind) Target() *container.Absolute { + if b == nil || b.Src == nil { + return nil + } + if b.Dst == nil { + return b.Src + } + return b.Dst +} + +func (b *FSBind) Host() []*container.Absolute { + if b == nil || b.Src == nil { + return nil + } + return []*container.Absolute{b.Src} +} + +func (b *FSBind) Apply(ops *container.Ops) { + if b == nil || b.Src == nil { + return + } + + dst := b.Dst + if dst == nil { + dst = b.Src + } + var flags int + if b.Write { + flags |= container.BindWritable + } + if b.Device { + flags |= container.BindDevice | container.BindWritable + } + if b.Optional { + flags |= container.BindOptional + } + ops.Bind(b.Src, dst, flags) +} + +func (b *FSBind) String() string { + g := 4 + if b == nil || b.Src == nil { + return "<invalid>" + } + + g += len(b.Src.String()) + if b.Dst != nil { + g += len(b.Dst.String()) + } + + expr := new(strings.Builder) + expr.Grow(g) + + if b.Device { + expr.WriteString("d") + } else if b.Write { + expr.WriteString("w") + } + + if !b.Optional { + expr.WriteString("*") + } else { + expr.WriteString("+") + } + + expr.WriteString(b.Src.String()) + if b.Dst != nil { + expr.WriteString(":" + b.Dst.String()) + } + + return expr.String() +} |
