aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/vfs/unfold.go
diff options
context:
space:
mode:
Diffstat (limited to 'container/vfs/unfold.go')
-rw-r--r--container/vfs/unfold.go115
1 files changed, 0 insertions, 115 deletions
diff --git a/container/vfs/unfold.go b/container/vfs/unfold.go
deleted file mode 100644
index 37c4cef3..00000000
--- a/container/vfs/unfold.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package vfs
-
-import (
- "iter"
- "path"
- "strings"
-)
-
-// UnfoldTargetError is a pathname that never appeared in a mount hierarchy.
-type UnfoldTargetError string
-
-func (e UnfoldTargetError) Error() string {
- return "mount point " + string(e) + " never appeared in mountinfo"
-}
-
-// MountInfoNode positions a [MountInfoEntry] in its mount hierarchy.
-type MountInfoNode struct {
- *MountInfoEntry
- FirstChild *MountInfoNode `json:"first_child"`
- NextSibling *MountInfoNode `json:"next_sibling"`
-
- Clean string `json:"clean"`
- Covered bool `json:"covered"`
-}
-
-// Collective returns an iterator over visible mountinfo nodes.
-func (n *MountInfoNode) Collective() iter.Seq[*MountInfoNode] {
- return func(yield func(*MountInfoNode) bool) { n.visit(yield) }
-}
-
-// visit recursively visits all visible mountinfo nodes.
-func (n *MountInfoNode) visit(yield func(*MountInfoNode) bool) bool {
- if !n.Covered && !yield(n) {
- return false
- }
- for cur := n.FirstChild; cur != nil; cur = cur.NextSibling {
- if !cur.visit(yield) {
- return false
- }
- }
- return true
-}
-
-// Unfold unfolds the mount hierarchy and resolves covered paths.
-func (d *MountInfoDecoder) Unfold(target string) (*MountInfoNode, error) {
- targetClean := path.Clean(target)
-
- var mountinfoSize int
- for range d.Entries() {
- mountinfoSize++
- }
- if err := d.Err(); err != nil {
- return nil, err
- }
-
- mountinfo := make([]*MountInfoNode, mountinfoSize)
- // mount ID to index lookup
- idIndex := make(map[int]int, mountinfoSize)
- // final entry to match target
- targetIndex := -1
- {
- i := 0
- for ent := range d.Entries() {
- mountinfo[i] = &MountInfoNode{Clean: path.Clean(ent.Target), MountInfoEntry: ent}
- idIndex[ent.ID] = i
- if mountinfo[i].Clean == targetClean {
- targetIndex = i
- }
-
- i++
- }
- }
-
- if targetIndex == -1 {
- // target does not exist in parsed mountinfo
- return nil, &DecoderError{Op: "unfold", Line: -1, Err: UnfoldTargetError(targetClean)}
- }
-
- for _, cur := range mountinfo {
- var parent *MountInfoNode
- if p, ok := idIndex[cur.Parent]; !ok {
- continue
- } else {
- parent = mountinfo[p]
- }
-
- if !strings.HasPrefix(cur.Clean, targetClean) {
- continue
- }
- if parent.Clean == cur.Clean {
- parent.Covered = true
- }
-
- covered := false
- nsp := &parent.FirstChild
- for s := parent.FirstChild; s != nil; s = s.NextSibling {
- if strings.HasPrefix(cur.Clean, s.Clean) {
- covered = true
- break
- }
-
- if strings.HasPrefix(s.Clean, cur.Clean) {
- *nsp = s.NextSibling
- } else {
- nsp = &s.NextSibling
- }
- }
- if covered {
- continue
- }
- *nsp = cur
- }
-
- return mountinfo[targetIndex], nil
-}