2#include "pedigree/kernel/syscallError.h"
3#include "pedigree/kernel/utilities/utility.h"
5#include "MountView-internal.h"
7#if THREADS && !defined(STANDALONE_MUTEXES)
8#include "pedigree/kernel/process/Thread.h"
9#include "pedigree/kernel/processor/Processor.h"
10#include "pedigree/kernel/processor/ProcessorInformation.h"
15class ResolutionAttempt {
17#if THREADS && !defined(STANDALONE_MUTEXES)
19 : m_Thread(
Processor::information().getCurrentThread()),
20 m_Error(m_Thread ? m_Thread->getErrno() : 0) {}
21 ~ResolutionAttempt() {
23 m_Thread->setErrno(m_Error);
27 m_Error = m_Thread->getErrno();
41 auto* current = path(reference);
47 auto* row = at(*current);
49 target = row->attachment;
52 return makePath(target, target->root, result);
59 auto* current = path(reference);
62 if (current->node() == current->attachment->root) {
67 auto* row = find(current->attachment->id);
69 parentAttachment = row->parent;
70 covered = row->covered;
73 if (!parentAttachment) {
79 if (!covered || !makePath(parentAttachment, covered->
get(), mountpoint))
81 if (view.samePath(mountpoint, boundary)) {
82 result = pedigree_std::move(mountpoint);
85 return parent(mountpoint, result, boundary);
89 current->node()->getNamespace(retained, unused);
90 if (!retained.get()) {
94 return makePath(current->attachment, retained.get(), result);
101 for (
size_t depth = 0; depth < 4096; ++depth) {
102 if (view.samePath(current, ancestor))
105 if (!parent(current, next) || view.samePath(current, next))
107 current = pedigree_std::move(next);
116 return walk(context, selected,
String(),
options, result, links);
123 const bool selectedOnly = !pathname.length();
124 FilesystemPathRef current = !selectedOnly && pathname[0] ==
'/' ? context.root : start;
125 if (!nodePath(current) || !path(context.root)) {
126 SYSCALL_ERROR(DoesNotExist);
129 if (!selectedOnly && !path(current)) {
130 SYSCALL_ERROR(NotADirectory);
133 bool trailingSlash = !selectedOnly && pathname[pathname.length() - 1] ==
'/';
134 bool followCurrent = selectedOnly;
135 bool crossCurrent =
false;
140 if (followCurrent && current->node()->
isSymlink()) {
142 SYSCALL_ERROR(LoopExists);
146 if (link->isPathLink()) {
148 if (!link->followPath(target))
150 if (!nodePath(target)) {
151 SYSCALL_ERROR(CrossDeviceLink);
154 current = pedigree_std::move(target);
156 crossCurrent =
false;
159 if (!path(current)) {
160 SYSCALL_ERROR(LoopExists);
166 SYSCALL_ERROR(OutOfMemory);
170 const int length = link->followLink(linkStorage.get(), 4096);
174 SYSCALL_ERROR(DoesNotExist);
177 if (length >= 4096) {
178 SYSCALL_ERROR(NameTooLong);
182 if (!parent(current, relative))
184 const size_t targetLength =
static_cast<size_t>(length);
185 const size_t remaining = pending.length() - offset;
186 const size_t separator = remaining ? 1 : 0;
187 if (remaining > ~
size_t(0) - targetLength - separator) {
188 SYSCALL_ERROR(NameTooLong);
191 const size_t combined = targetLength + separator + remaining;
194 SYSCALL_ERROR(OutOfMemory);
197 MemoryCopy(expanded.get(), linkStorage.get(), targetLength);
199 expanded.get()[targetLength] =
'/';
200 MemoryCopy(expanded.get() + targetLength + 1, pending.str() + offset, remaining);
201 }
else if (linkStorage.get()[targetLength - 1] ==
'/') {
202 trailingSlash =
true;
204 current = linkStorage.get()[0] ==
'/' ? context.root : relative;
206 pendingStorage = pedigree_std::move(expanded);
207 pending =
StringView(pendingStorage.get(), combined);
209 followCurrent =
false;
210 crossCurrent =
false;
213 if (crossCurrent && path(current)) {
215 if (!cross(current, crossed))
217 current = pedigree_std::move(crossed);
219 crossCurrent =
false;
220 while (offset < pending.length() && pending[offset] ==
'/')
222 if (offset == pending.length())
224 const size_t begin = offset;
225 while (offset < pending.length() && pending[offset] !=
'/')
228 size_t next = offset;
229 while (next < pending.length() && pending[next] ==
'/')
231 const bool final = next == pending.length();
232 if (!path(current) || !current->node()->
isDirectory()) {
233 SYSCALL_ERROR(NotADirectory);
238 followCurrent =
false;
239 if (component ==
".") {
243 if (component ==
"..") {
244 if (!view.samePath(current, context.root)) {
246 if (!parent(current, above, context.root))
248 current = pedigree_std::move(above);
256 if (status != Directory::LookupStatus::Found) {
257 syscallError(status == Directory::LookupStatus::IoError ? Error::IoError
258 : status ==
Directory::LookupStatus::Retry ? Error::NoMoreProcesses
259 : Error::DoesNotExist);
263 if (!makePath(path(current)->attachment, child.get(), candidate))
265 current = pedigree_std::move(candidate);
267 followCurrent = !
final ||
options.followFinal || trailingSlash;
268 crossCurrent = !
final ||
options.crossFinalMount;
271 SYSCALL_ERROR(NotADirectory);
274 result = pedigree_std::move(current);
282 if (!pathname.length()) {
283 SYSCALL_ERROR(DoesNotExist);
286 if (writer && !writer->protects(view.m_Vfs)) {
287 SYSCALL_ERROR(InvalidArgument);
291 ResolutionAttempt attempt;
292 const uint64_t generation = view.m_Vfs.namespaceGeneration();
293 if (!writer && (generation & 1)) {
300 const bool success = walk(context, start, pathname,
options, found, links);
301 if (generation != view.m_Vfs.namespaceGeneration())
307 result = pedigree_std::move(found);
315 if (!m_State || !context) {
316 SYSCALL_ERROR(DoesNotExist);
320 ResolutionAttempt attempt;
322 if (!context->snapshot(snapshot)) {
323 SYSCALL_ERROR(DoesNotExist);
329 m_State->resolve(snapshot, start ? start : snapshot.cwd, pathname,
options, found);
334 coherent = m_State->context(context, live) &&
335 live->generation == snapshot.contextGeneration &&
336 m_State->topology == snapshot.topologyGeneration;
344 result = pedigree_std::move(found);
351 if (!m_State || !context || !m_State->nodePath(selected)) {
352 SYSCALL_ERROR(DoesNotExist);
356 ResolutionAttempt attempt;
358 if (generation & 1) {
363 if (!context->snapshot(snapshot)) {
364 SYSCALL_ERROR(DoesNotExist);
371 const bool success = m_State->follow(snapshot, selected,
options, found, links);
378 coherent = m_State->context(context, live) &&
379 live->generation == snapshot.contextGeneration &&
380 m_State->topology == snapshot.topologyGeneration;
388 result = pedigree_std::move(found);
396 if (!pathname.length()) {
397 SYSCALL_ERROR(DoesNotExist);
400 size_t end = pathname.length();
401 while (end > 1 && pathname[end - 1] ==
'/')
404 while (slash && pathname[slash - 1] !=
'/')
407 if (name.length() > 255) {
408 SYSCALL_ERROR(NameTooLong);
413 options.requireDirectory =
true;
415 if (!resolve(context, start, prefix,
options, resolved))
417 parent = pedigree_std::move(resolved);
418 basename = pedigree_std::move(name);
static Directory * fromFile(File *pF)
MUST_USE_RESULT LookupStatus lookupChild(const HashedStringView &s, ChildLease &child) const
virtual bool isDirectory()
StringView substring(size_t start, size_t end, bool hashed=HASH_STRINGVIEWS_BY_DEFAULT) const
static Symlink * fromFile(File *pF)
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)
uint64_t namespaceGeneration() const