carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package release
2
3import (
4 "github.com/carlosframework/platform/internal/rootstate"
5 "os"
6 "path/filepath"
7 "strings"
8)
9
10func GenerationFileProof(path string, before, after rootstate.FileIdentity) bool {
11 if before.Same(after) {
12 return true
13 }
14 source := func(id rootstate.FileIdentity) (string, bool) {
15 root, e1 := generationProofUnescape(id.MountRoot)
16 point, e2 := generationProofUnescape(id.MountPoint)
17 if e1 != nil || e2 != nil || !filepath.IsAbs(root) || !filepath.IsAbs(point) || filepath.Clean(root) != root || filepath.Clean(point) != point {
18 return "", false
19 }
20 rel, err := filepath.Rel(point, path)
21 if err != nil || !filepath.IsLocal(rel) {
22 return "", false
23 }
24 return filepath.Join(root, rel), true
25 }
26 if before.SameMountNamespace(after) || before.MountLineage == "" || after.MountLineage == "" || before.MountLineage == after.MountLineage || !strings.HasSuffix(before.MountLineage, "\n"+after.MountLineage) {
27 return false
28 }
29 beforePoint, e1 := generationProofUnescape(before.MountPoint)
30 afterPoint, e2 := generationProofUnescape(after.MountPoint)
31 rel, err := filepath.Rel(afterPoint, beforePoint)
32 if e1 != nil || e2 != nil || err != nil || rel == "." || !filepath.IsLocal(rel) {
33 return false
34 }
35 a, ok1 := source(before)
36 b, ok2 := source(after)
37 if !ok1 || !ok2 || a != b {
38 return false
39 }
40 after.MountRoot, after.MountPoint, after.MountLineage = before.MountRoot, before.MountPoint, before.MountLineage
41 return before.Same(after)
42}
43
44func generationProofUnescape(s string) (string, error) {
45 var out strings.Builder
46 for i := 0; i < len(s); i++ {
47 if s[i] != '\\' {
48 out.WriteByte(s[i])
49 continue
50 }
51 if i+3 >= len(s) {
52 return "", os.ErrPermission
53 }
54 switch s[i : i+4] {
55 case "\\040":
56 out.WriteByte(' ')
57 case "\\011":
58 out.WriteByte('\t')
59 case "\\012":
60 out.WriteByte('\n')
61 case "\\134":
62 out.WriteByte('\\')
63 default:
64 return "", os.ErrPermission
65 }
66 i += 3
67 }
68 return out.String(), nil
69}
70