carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1// Package rootstate opens local authority through root-owned directories.
2package rootstate
3
4import (
5 "context"
6 "os"
7 "path"
8 "strings"
9)
10
11const MaxRecord = 1 << 20
12
13// Store retains the directory descriptor. Close it after the last operation.
14type Store interface {
15 Read(string) ([]byte, error)
16 Write(string, []byte) error
17 Remove(string) error
18 Names() ([]string, error)
19 Lock(context.Context, string) (func(), error)
20 Close() error
21}
22
23// Sync makes a checked directory's visible entries durable. A read-only
24// projection consumer uses it before acknowledging a newly observed record.
25func Sync(s Store) error {
26 if d, ok := s.(interface{ Sync() error }); ok {
27 return d.Sync()
28 }
29 return os.ErrPermission
30}
31
32func component(s string) bool {
33 if s == "" || s == "." || s == ".." || len(s) > 255 {
34 return false
35 }
36 for _, r := range s {
37 if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '.' || r == '-' || r == '_') {
38 return false
39 }
40 }
41 return true
42}
43
44func fileMode(public bool) os.FileMode {
45 if public {
46 return 0644
47 }
48 return 0600
49}
50
51type FileIdentity struct {
52 Device uint64
53 Inode uint64
54 Boot, Filesystem, Handle, MountRoot, MountPoint, MountNamespace string `json:",omitempty"`
55 MountLineage string `json:",omitempty"`
56 HandleType int32 `json:",omitempty"`
57 Mount uint64 `json:",omitempty"`
58 MountUnique, NamespaceUnique uint64 `json:",omitempty"`
59 UID, GID, Mode uint32 `json:",omitempty"`
60}
61
62func (a FileIdentity) Same(b FileIdentity) bool {
63 if a.Boot == "" || b.Boot == "" {
64 return false
65 }
66 if a.Filesystem == "" || a.Handle == "" || a.MountRoot == "" || a.MountPoint == "" || a.MountNamespace == "" || b.MountNamespace == "" {
67 return false
68 }
69 if a.Inode != b.Inode || a.Filesystem != b.Filesystem || a.Handle != b.Handle || a.HandleType != b.HandleType || a.UID != b.UID || a.GID != b.GID || a.Mode != b.Mode || a.MountRoot != b.MountRoot || a.MountPoint != b.MountPoint {
70 return false
71 }
72 if (a.MountLineage != "" || b.MountLineage != "") && (a.MountUnique == 0 || b.MountUnique == 0 || a.NamespaceUnique == 0 || b.NamespaceUnique == 0) {
73 return false
74 }
75 if a.SameMountNamespace(b) && a.MountUnique != b.MountUnique {
76 return false
77 }
78 if a.MountLineage != b.MountLineage && (a.SameMountNamespace(b) || !sameMountLayers(a, b)) {
79 return false
80 }
81 return a.Boot != b.Boot || a.Device == b.Device
82}
83
84func (a FileIdentity) SameMountNamespace(b FileIdentity) bool {
85 return a.Boot != "" && a.Boot == b.Boot && a.NamespaceUnique != 0 && a.NamespaceUnique == b.NamespaceUnique
86}
87
88func sameMountLayers(a, b FileIdentity) bool {
89 layers := func(id FileIdentity) (string, []string, bool) {
90 if id.MountLineage == "" {
91 return "", nil, false
92 }
93 var out strings.Builder
94 rows := strings.Split(strings.TrimSuffix(id.MountLineage, "\n"), "\n")
95 for i, row := range rows {
96 fields := strings.Split(row, "\t")
97 if len(fields) != 2 {
98 return "", nil, false
99 }
100 if fields[1] != id.MountPoint {
101 return out.String(), rows[i:], out.Len() != 0
102 }
103 out.WriteString(row + "\n")
104 }
105 return out.String(), nil, out.Len() != 0
106 }
107 left, before, ok1 := layers(a)
108 right, after, ok2 := layers(b)
109 if !ok1 || !ok2 || left != right {
110 return false
111 }
112 for i, row := range before {
113 if len(after) != 0 && row == after[0] {
114 after = after[1:]
115 continue
116 }
117 fields := strings.Split(row, "\t")
118 if len(fields) != 2 || i+1 == len(before) || fields[1] == "/" {
119 return false
120 }
121 parent := strings.Split(before[i+1], "\t")
122 if len(parent) != 2 {
123 return false
124 }
125 for _, name := range append(fields, parent...) {
126 if !path.IsAbs(name) || path.Clean(name) != name {
127 return false
128 }
129 }
130 rel, below := strings.CutPrefix(fields[1], strings.TrimSuffix(parent[1], "/")+"/")
131 if !below || rel == "" || path.Join(parent[0], rel) != fields[0] {
132 return false
133 }
134 }
135 return len(after) == 0
136}
137