The Pedigree Project 0.1
MountView-report.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "pedigree/kernel/syscallError.h"
3
4#include "MountView-internal.h"
5
6bool VfsMountView::State::format(const FilesystemContextSnapshot& context,
7 const FilesystemPathRef& reference, String& result,
8 const VFS::NamespaceMutation& writer) {
9 if (!writer.protects(view.m_Vfs) || !path(reference) || !path(context.root)) {
10 SYSCALL_ERROR(InvalidArgument);
11 return false;
12 }
13 String suffix;
14 FilesystemPathRef current = reference;
15 for (size_t depth = 0; depth < 4096; ++depth) {
16 if (view.samePath(current, context.root)) {
17 result = suffix.length() ? pedigree_std::move(suffix) : String("/");
18 return true;
19 }
20 auto* entry = path(current);
21 if (entry->node() == entry->attachment->root) {
22 VfsAttachmentRef parent;
24 {
25 LockGuard<Mutex> guard(graph);
26 auto* row = find(entry->attachment->id);
27 if (row) {
28 parent = row->parent;
29 covered = row->covered;
30 }
31 }
32 if (!parent || !covered) {
33 SYSCALL_ERROR(DoesNotExist);
34 return false;
35 }
36 FilesystemPathRef mountpoint;
37 if (!makePath(parent, covered->get(), mountpoint))
38 return false;
39 current = pedigree_std::move(mountpoint);
40 continue;
41 }
42 File::ParentLease parent;
43 String name;
44 entry->node()->getNamespace(parent, name);
45 if (!parent.get() || !name.length()) {
46 SYSCALL_ERROR(DoesNotExist);
47 return false;
48 }
49 String component("/");
50 component += name;
51 component += suffix;
52 if (component.length() >= 4096) {
53 SYSCALL_ERROR(NameTooLong);
54 return false;
55 }
56 suffix = pedigree_std::move(component);
58 if (!makePath(entry->attachment, parent.get(), next))
59 return false;
60 current = pedigree_std::move(next);
61 }
62 SYSCALL_ERROR(LoopExists);
63 return false;
64}
65
66bool VfsMountView::formatPath(const FilesystemContextSnapshot& context,
67 const FilesystemPathRef& path, String& result) {
68 if (!m_State)
69 return false;
70 VFS::NamespaceMutation writer(m_Vfs);
71 {
72 LockGuard<Mutex> guard(m_State->graph);
73 if (context.topologyGeneration != m_State->topology) {
74 SYSCALL_ERROR(NoMoreProcesses);
75 return false;
76 }
77 }
78 return m_State->format(context, path, result, writer);
79}
80
81bool VfsMountView::snapshotMounts(const FilesystemContextRef& context,
82 Vector<MountSnapshot>& result) {
83 if (!m_State || !context)
84 return false;
85 struct RetainedRow {
86 VfsAttachmentRef attachment;
87 uint64_t parentId = 0;
88 };
90 Vector<MountSnapshot> snapshots;
92 VFS::NamespaceMutation writer(m_Vfs);
93 if (!context->snapshot(fs))
94 return false;
95 size_t count = 0;
96 {
97 LockGuard<Mutex> guard(m_State->graph);
98 for (auto* row = m_State->attachments; row; row = row->next)
99 ++count;
100 }
101 if (!rows.tryReserve(count) || !snapshots.tryReserve(count)) {
102 SYSCALL_ERROR(OutOfMemory);
103 return false;
104 }
105 {
106 LockGuard<Mutex> guard(m_State->graph);
107 for (auto* row = m_State->attachments; row; row = row->next) {
108 RetainedRow copy;
109 copy.attachment = row->attachment;
110 copy.parentId = row->parent ? row->parent->id : row->attachment->id;
111 rows.pushBack(pedigree_std::move(copy));
112 }
113 }
114 for (auto& row : rows) {
116 MountSnapshot snapshot;
117 if (!m_State->makePath(row.attachment, row.attachment->root, root))
118 return false;
119 if (m_State->path(fs.root)->attachment.get() == row.attachment.get()) {
120 snapshot.path = String("/");
121 } else {
122 if (!m_State->beneath(root, fs.root))
123 continue;
124 if (!m_State->format(fs, root, snapshot.path, writer))
125 return false;
126 }
127 snapshot.id = row.attachment->id;
128 snapshot.parentId = row.parentId;
129 snapshot.backing = row.attachment->backing.identity();
130 snapshots.pushBack(pedigree_std::move(snapshot));
131 }
132 result.swap(snapshots);
133 return true;
134}
T * get() const
A vector / dynamic array.
Definition Vector.h:33
void pushBack(const T &value)
Definition Vector.h:275
void swap(Iterator a, Iterator b)
Definition Vector.h:481