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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package hst
import (
"encoding/gob"
"slices"
"strings"
"hakurei.app/check"
"hakurei.app/fhs"
)
func init() { gob.Register(new(FSOverlay)) }
// FilesystemOverlay is the type string of an overlay mount point.
const FilesystemOverlay = "overlay"
// FSOverlay represents an overlay mount point.
type FSOverlay struct {
// Pathname in the container mount namespace.
Target *check.Absolute `json:"dst"`
// Any filesystem, does not need to be on a writable filesystem, must not be nil.
Lower []*check.Absolute `json:"lower"`
// The upperdir is normally on a writable filesystem, leave as nil to mount
// Lower readonly.
Upper *check.Absolute `json:"upper,omitempty"`
// The workdir needs to be an empty directory on the same filesystem as
// Upper, must not be nil if Upper is populated.
Work *check.Absolute `json:"work,omitempty"`
}
func (o *FSOverlay) Valid() bool {
if o == nil || o.Target == nil {
return false
}
for _, a := range o.Lower {
if a == nil {
return false
}
}
if o.Upper != nil { // rw
return o.Work != nil || len(o.Lower) > 0
} else { // ro
return len(o.Lower) >= 2
}
}
func (o *FSOverlay) Path() *check.Absolute {
if !o.Valid() {
return nil
}
return o.Target
}
func (o *FSOverlay) Host() []*check.Absolute {
if !o.Valid() {
return nil
}
p := make([]*check.Absolute, 0, 2+len(o.Lower))
if o.Upper != nil {
p = append(p, o.Upper)
if o.Work != nil {
p = append(p, o.Work)
}
}
p = append(p, o.Lower...)
return p
}
func (o *FSOverlay) Apply(z *ApplyState) {
if !o.Valid() {
return
}
if o.Upper != nil {
if o.Target.Is(fhs.AbsRoot) {
z.NoRemountRoot = true
}
if o.Work != nil {
z.Overlay(o.Target, o.Upper, o.Work, o.Lower...)
} else {
z.OverlayEphemeral(o.Target, slices.Concat(
[]*check.Absolute{o.Upper},
o.Lower,
)...)
}
} else {
z.OverlayReadonly(o.Target, o.Lower...)
}
}
func (o *FSOverlay) String() string {
if !o.Valid() {
return "<invalid>"
}
lower := make([]string, len(o.Lower))
for i, a := range o.Lower {
lower[i] = check.EscapeOverlayDataSegment(a.String())
}
if o.Upper != nil {
if o.Work != nil {
return "w*" + strings.Join(append([]string{
check.EscapeOverlayDataSegment(o.Target.String()),
check.EscapeOverlayDataSegment(o.Upper.String()),
check.EscapeOverlayDataSegment(o.Work.String())},
lower...), check.SpecialOverlayPath)
}
return "e*" + strings.Join(append([]string{
check.EscapeOverlayDataSegment(o.Target.String()),
check.EscapeOverlayDataSegment(o.Upper.String())},
lower...), check.SpecialOverlayPath)
} else {
return "*" + strings.Join(append([]string{
check.EscapeOverlayDataSegment(o.Target.String())},
lower...), check.SpecialOverlayPath)
}
}
|