2#include "pedigree/kernel/syscallError.h"
3#include "pedigree/kernel/utilities/utility.h"
5#include "MountView-internal.h"
8#include "pedigree/kernel/process/Process.h"
10#if THREADS && !defined(STANDALONE_MUTEXES)
11#include "pedigree/kernel/process/Thread.h"
12#include "pedigree/kernel/processor/Processor.h"
13#include "pedigree/kernel/processor/ProcessorInformation.h"
18class ResolutionAttempt {
20#if THREADS && !defined(STANDALONE_MUTEXES)
22 : m_Thread(
Processor::information().getCurrentThread()),
23 m_Error(m_Thread ? m_Thread->getErrno() : 0) {}
24 ~ResolutionAttempt() {
26 m_Thread->setErrno(m_Error);
30 m_Error = m_Thread->getErrno();
44 auto* owner = VfsMountView::fromPath(reference);
45 if (owner && owner != &view) {
46 return owner->m_State->cross(reference, result);
49 for (
size_t depth = 0; depth < 4096; ++depth) {
50 auto* current = path(selected);
57 auto* row = at(*current);
59 target = row->attachment;
63 result = pedigree_std::move(selected);
66 if (!makePath(target, target->root, selected)) {
70 SYSCALL_ERROR(LoopExists);
76 auto* owner = VfsMountView::fromPath(reference);
77 if (owner && owner != &view) {
78 return owner->m_State->parent(reference, result, boundary);
80 auto* current = path(reference);
83 if (!current->node()->isDirectory() && current->lookupParent) {
84 result = current->lookupParent;
87 if (current->node() == current->attachment->root) {
92 auto* row = find(current->attachment->id);
94 parentAttachment = row->parent;
95 covered = row->covered;
98 if (!parentAttachment) {
104 if (!covered || !makePath(parentAttachment, covered->
get(), mountpoint))
106 if (view.samePath(mountpoint, boundary)) {
107 result = pedigree_std::move(mountpoint);
110 return parent(mountpoint, result, boundary);
114 current->node()->getNamespace(retained, unused);
115 if (!retained.get()) {
119 return makePath(current->attachment, retained.get(), result);
126 for (
size_t depth = 0; depth < 4096; ++depth) {
127 if (view.samePath(current, ancestor))
130 if (!parent(current, next) || view.samePath(current, next))
132 current = pedigree_std::move(next);
141 return walk(context, selected,
String(),
options, result, links);
148 const bool selectedOnly = !pathname.length();
149 FilesystemPathRef current = !selectedOnly && pathname[0] ==
'/' ? context.root : start;
150 auto* currentView = VfsMountView::fromPath(current);
151 if (!currentView || !VfsMountView::fromPath(context.root)) {
152 SYSCALL_ERROR(DoesNotExist);
155 if (!selectedOnly && !currentView->m_State->path(current)) {
156 SYSCALL_ERROR(NotADirectory);
160#ifndef VFS_STANDALONE
161 if (!Process::currentFilesystemCredentials(credentials)) {
162 credentials.valid =
false;
165 bool trailingSlash = !selectedOnly && pathname[pathname.length() - 1] ==
'/';
166 bool followCurrent = selectedOnly;
167 bool crossCurrent = !selectedOnly && pathname[0] ==
'/';
172 if (followCurrent && current->node()->
isSymlink()) {
174 SYSCALL_ERROR(LoopExists);
178 if (link->isPathLink()) {
180 if (!link->followPath(target))
182 if (!VfsMountView::fromPath(target)) {
183 SYSCALL_ERROR(CrossDeviceLink);
186 current = pedigree_std::move(target);
188 crossCurrent =
false;
191 if (!VfsMountView::fromPath(current)->m_State->path(current)) {
192 SYSCALL_ERROR(LoopExists);
198 SYSCALL_ERROR(OutOfMemory);
202 const int length = link->followLink(linkStorage.get(), 4096);
206 SYSCALL_ERROR(DoesNotExist);
209 if (length >= 4096) {
210 SYSCALL_ERROR(NameTooLong);
214 if (!parent(current, relative))
216 const size_t targetLength =
static_cast<size_t>(length);
217 const size_t remaining = pending.length() - offset;
218 const size_t separator = remaining ? 1 : 0;
219 if (remaining > ~
size_t(0) - targetLength - separator) {
220 SYSCALL_ERROR(NameTooLong);
223 const size_t combined = targetLength + separator + remaining;
226 SYSCALL_ERROR(OutOfMemory);
229 MemoryCopy(expanded.get(), linkStorage.get(), targetLength);
231 expanded.get()[targetLength] =
'/';
232 MemoryCopy(expanded.get() + targetLength + 1, pending.str() + offset, remaining);
233 }
else if (linkStorage.get()[targetLength - 1] ==
'/') {
234 trailingSlash =
true;
236 current = linkStorage.get()[0] ==
'/' ? context.root : relative;
238 pendingStorage = pedigree_std::move(expanded);
239 pending =
StringView(pendingStorage.get(), combined);
241 followCurrent =
false;
242 crossCurrent =
false;
245 if (crossCurrent && VfsMountView::fromPath(current)->m_State->path(current)) {
247 if (!cross(current, crossed))
249 current = pedigree_std::move(crossed);
251 crossCurrent =
false;
252 while (offset < pending.length() && pending[offset] ==
'/')
254 if (offset == pending.length())
256 const size_t begin = offset;
257 while (offset < pending.length() && pending[offset] !=
'/')
260 size_t next = offset;
261 while (next < pending.length() && pending[next] ==
'/')
263 const bool final = next == pending.length();
264 auto* selectedState = VfsMountView::fromPath(current)->m_State;
265 if (!selectedState->path(current) || !current->node()->
isDirectory()) {
266 SYSCALL_ERROR(NotADirectory);
272 followCurrent =
false;
273 if (component ==
".") {
277 if (component ==
"..") {
278 if (!view.samePath(current, context.root)) {
280 if (!parent(current, above, context.root))
282 current = pedigree_std::move(above);
290 if (status != Directory::LookupStatus::Found) {
291 syscallError(status == Directory::LookupStatus::IoError ? Error::IoError
292 : status ==
Directory::LookupStatus::Retry ? Error::NoMoreProcesses
293 : Error::DoesNotExist);
297 if (!selectedState->makePath(selectedState->path(current)->attachment,
VfsNodeReference(child),
302 static_cast<VfsPath*
>(candidate.
get())->lookupParent = current;
305 current = pedigree_std::move(candidate);
307 followCurrent = !
final ||
options.followFinal || trailingSlash;
308 crossCurrent = !
final ||
options.crossFinalMount;
311 SYSCALL_ERROR(NotADirectory);
314 result = pedigree_std::move(current);
322 if (!pathname.length()) {
323 SYSCALL_ERROR(DoesNotExist);
326 if (writer && !writer->protects(view.m_Vfs)) {
327 SYSCALL_ERROR(InvalidArgument);
331 ResolutionAttempt attempt;
332 const uint64_t generation = view.m_Vfs.namespaceGeneration();
333 if (!writer && (generation & 1)) {
340 const bool success = walk(context, start, pathname,
options, found, links);
341 if (generation != view.m_Vfs.namespaceGeneration())
347 result = pedigree_std::move(found);
355 if (!m_State || !context) {
356 SYSCALL_ERROR(DoesNotExist);
360 ResolutionAttempt attempt;
362 if (!context->snapshot(snapshot)) {
363 SYSCALL_ERROR(DoesNotExist);
369 m_State->resolve(snapshot, start ? start : snapshot.cwd, pathname,
options, found);
374 coherent = m_State->context(context, live) &&
375 live->generation == snapshot.contextGeneration &&
376 m_State->topology == snapshot.topologyGeneration;
384 result = pedigree_std::move(found);
391 if (!m_State || !context || !VfsMountView::fromPath(selected)) {
392 SYSCALL_ERROR(DoesNotExist);
396 ResolutionAttempt attempt;
398 if (generation & 1) {
403 if (!context->snapshot(snapshot)) {
404 SYSCALL_ERROR(DoesNotExist);
411 const bool success = m_State->follow(snapshot, selected,
options, found, links);
418 coherent = m_State->context(context, live) &&
419 live->generation == snapshot.contextGeneration &&
420 m_State->topology == snapshot.topologyGeneration;
428 result = pedigree_std::move(found);
436 if (!pathname.length()) {
437 SYSCALL_ERROR(DoesNotExist);
440 size_t end = pathname.length();
441 while (end > 1 && pathname[end - 1] ==
'/')
444 while (slash && pathname[slash - 1] !=
'/')
447 if (name.length() > 255) {
448 SYSCALL_ERROR(NameTooLong);
453 options.requireDirectory =
true;
455 if (!resolve(context, start, prefix,
options, resolved))
457 parent = pedigree_std::move(resolved);
458 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