All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 35s
				
			Test / Sandbox (push) Successful in 2m19s
				
			Test / Hakurei (push) Successful in 3m15s
				
			Test / Hpkg (push) Successful in 4m19s
				
			Test / Sandbox (race detector) (push) Successful in 4m34s
				
			Test / Hakurei (race detector) (push) Successful in 5m11s
				
			Test / Flake checks (push) Successful in 1m46s
				
			This is used for ensuring persistent data directories specific to the container. Signed-off-by: Ophestra <cat@gensokyo.uk>
		
			
				
	
	
		
			114 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package container
 | |
| 
 | |
| import (
 | |
| 	"encoding/gob"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"syscall"
 | |
| )
 | |
| 
 | |
| func init() { gob.Register(new(BindMountOp)) }
 | |
| 
 | |
| // Bind appends an [Op] that bind mounts host path [BindMountOp.Source] on container path [BindMountOp.Target].
 | |
| func (f *Ops) Bind(source, target *Absolute, flags int) *Ops {
 | |
| 	*f = append(*f, &BindMountOp{nil, source, target, flags})
 | |
| 	return f
 | |
| }
 | |
| 
 | |
| // BindMountOp bind mounts host path Source on container path Target.
 | |
| // Note that Flags uses bits declared in this package and should not be set with constants in [syscall].
 | |
| type BindMountOp struct {
 | |
| 	sourceFinal, Source, Target *Absolute
 | |
| 
 | |
| 	Flags int
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	// BindOptional skips nonexistent host paths.
 | |
| 	BindOptional = 1 << iota
 | |
| 	// BindWritable mounts filesystem read-write.
 | |
| 	BindWritable
 | |
| 	// BindDevice allows access to devices (special files) on this filesystem.
 | |
| 	BindDevice
 | |
| 	// BindEnsure attempts to create the host path if it does not exist.
 | |
| 	BindEnsure
 | |
| )
 | |
| 
 | |
| func (b *BindMountOp) Valid() bool {
 | |
| 	return b != nil &&
 | |
| 		b.Source != nil && b.Target != nil &&
 | |
| 		b.Flags&(BindOptional|BindEnsure) != (BindOptional|BindEnsure)
 | |
| }
 | |
| 
 | |
| func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error {
 | |
| 	if b.Flags&BindEnsure != 0 {
 | |
| 		if err := k.mkdirAll(b.Source.String(), 0700); err != nil {
 | |
| 			return wrapErrSelf(err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if pathname, err := k.evalSymlinks(b.Source.String()); err != nil {
 | |
| 		if os.IsNotExist(err) && b.Flags&BindOptional != 0 {
 | |
| 			// leave sourceFinal as nil
 | |
| 			return nil
 | |
| 		}
 | |
| 		return wrapErrSelf(err)
 | |
| 	} else {
 | |
| 		b.sourceFinal, err = NewAbs(pathname)
 | |
| 		return err
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (b *BindMountOp) apply(_ *setupState, k syscallDispatcher) error {
 | |
| 	if b.sourceFinal == nil {
 | |
| 		if b.Flags&BindOptional == 0 {
 | |
| 			// unreachable
 | |
| 			return msg.WrapErr(os.ErrClosed, "impossible bind state reached")
 | |
| 		}
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	source := toHost(b.sourceFinal.String())
 | |
| 	target := toSysroot(b.Target.String())
 | |
| 
 | |
| 	// this perm value emulates bwrap behaviour as it clears bits from 0755 based on
 | |
| 	// op->perms which is never set for any bind setup op so always results in 0700
 | |
| 	if fi, err := k.stat(source); err != nil {
 | |
| 		return wrapErrSelf(err)
 | |
| 	} else if fi.IsDir() {
 | |
| 		if err = k.mkdirAll(target, 0700); err != nil {
 | |
| 			return wrapErrSelf(err)
 | |
| 		}
 | |
| 	} else if err = k.ensureFile(target, 0444, 0700); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	var flags uintptr = syscall.MS_REC
 | |
| 	if b.Flags&BindWritable == 0 {
 | |
| 		flags |= syscall.MS_RDONLY
 | |
| 	}
 | |
| 	if b.Flags&BindDevice == 0 {
 | |
| 		flags |= syscall.MS_NODEV
 | |
| 	}
 | |
| 
 | |
| 	return k.bindMount(source, target, flags, b.sourceFinal == b.Target)
 | |
| }
 | |
| 
 | |
| func (b *BindMountOp) Is(op Op) bool {
 | |
| 	vb, ok := op.(*BindMountOp)
 | |
| 	return ok && b.Valid() && vb.Valid() &&
 | |
| 		b.Source.Is(vb.Source) &&
 | |
| 		b.Target.Is(vb.Target) &&
 | |
| 		b.Flags == vb.Flags
 | |
| }
 | |
| func (*BindMountOp) prefix() string { return "mounting" }
 | |
| func (b *BindMountOp) String() string {
 | |
| 	if b.Source == nil || b.Target == nil {
 | |
| 		return "<invalid>"
 | |
| 	}
 | |
| 	if b.Source.String() == b.Target.String() {
 | |
| 		return fmt.Sprintf("%q flags %#x", b.Source, b.Flags)
 | |
| 	}
 | |
| 	return fmt.Sprintf("%q on %q flags %#x", b.Source, b.Target, b.Flags)
 | |
| }
 |