aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/autoetc.go
blob: 3be4ec3897bb9a81cac2b72077ca206a91217934 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package container

import (
	"encoding/gob"
	"fmt"
)

func init() { gob.Register(new(AutoEtcOp)) }

// Etc appends an [Op] that expands host /etc into a toplevel symlink mirror with /etc semantics.
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
func (f *Ops) Etc(host *Absolute, prefix string) *Ops {
	e := &AutoEtcOp{prefix}
	f.Mkdir(AbsFHSEtc, 0755)
	f.Bind(host, e.hostPath(), 0)
	*f = append(*f, e)
	return f
}

type AutoEtcOp struct{ Prefix string }

func (e *AutoEtcOp) Valid() bool                                { return e != nil }
func (e *AutoEtcOp) early(*setupState, syscallDispatcher) error { return nil }
func (e *AutoEtcOp) apply(state *setupState, k syscallDispatcher) error {
	if state.nonrepeatable&nrAutoEtc != 0 {
		return OpRepeatError("autoetc")
	}
	state.nonrepeatable |= nrAutoEtc

	const target = sysrootPath + FHSEtc
	rel := e.hostRel() + "/"

	if err := k.mkdirAll(target, 0755); err != nil {
		return err
	}
	if d, err := k.readdir(toSysroot(e.hostPath().String())); err != nil {
		return err
	} else {
		for _, ent := range d {
			n := ent.Name()
			switch n {
			case ".host", "passwd", "group":

			case "mtab":
				if err = k.symlink(FHSProc+"mounts", target+n); err != nil {
					return err
				}

			default:
				if err = k.symlink(rel+n, target+n); err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func (e *AutoEtcOp) hostPath() *Absolute { return AbsFHSEtc.Append(e.hostRel()) }
func (e *AutoEtcOp) hostRel() string     { return ".host/" + e.Prefix }

func (e *AutoEtcOp) Is(op Op) bool {
	ve, ok := op.(*AutoEtcOp)
	return ok && e.Valid() && ve.Valid() && *e == *ve
}
func (*AutoEtcOp) prefix() string   { return "setting up" }
func (e *AutoEtcOp) String() string { return fmt.Sprintf("auto etc %s", e.Prefix) }