diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 0eb92e2458..60d5340d8e 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -234,11 +234,9 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren cwd = parentTask->m_cwd.copyRef(); } - auto handle = VirtualFileSystem::the().open(path, 0, cwd ? cwd->inode : InodeIdentifier()); - if (!handle) { - error = -ENOENT; // FIXME: Get a more detailed error from VFS. + auto handle = VirtualFileSystem::the().open(path, error, 0, cwd ? cwd->inode : InodeIdentifier()); + if (!handle) return nullptr; - } if (!handle->metadata().mayExecute(uid, gid)) { error = -EACCES; @@ -786,9 +784,10 @@ int Task::sys$close(int fd) int Task::sys$lstat(const char* path, Unix::stat* statbuf) { VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat)); - auto handle = VirtualFileSystem::the().open(move(path), O_NOFOLLOW_NOERROR, cwdInode()); + int error; + auto handle = VirtualFileSystem::the().open(move(path), error, O_NOFOLLOW_NOERROR, cwdInode()); if (!handle) - return -1; + return error; handle->stat(statbuf); return 0; } @@ -798,9 +797,10 @@ int Task::sys$readlink(const char* path, char* buffer, size_t size) VALIDATE_USER_BUFFER(path, strlen(path)); VALIDATE_USER_BUFFER(buffer, size); - auto handle = VirtualFileSystem::the().open(path, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode()); + int error; + auto handle = VirtualFileSystem::the().open(path, error, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode()); if (!handle) - return -ENOENT; // FIXME: Get a more detailed error from VFS. + return error; if (!handle->metadata().isSymbolicLink()) return -EINVAL; @@ -818,9 +818,10 @@ int Task::sys$readlink(const char* path, char* buffer, size_t size) int Task::sys$chdir(const char* path) { VALIDATE_USER_BUFFER(path, strlen(path)); - auto handle = VirtualFileSystem::the().open(path, 0, cwdInode()); + int error; + auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode()); if (!handle) - return -ENOENT; // FIXME: More detailed error. + return error; if (!handle->isDirectory()) return -ENOTDIR; m_cwd = handle->vnode(); @@ -842,9 +843,10 @@ int Task::sys$open(const char* path, int options) VALIDATE_USER_BUFFER(path, strlen(path)); if (m_fileHandles.size() >= m_maxFileHandles) return -EMFILE; - auto handle = VirtualFileSystem::the().open(path, 0, cwdInode()); + int error; + auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode()); if (!handle) - return -ENOENT; // FIXME: Detailed error. + return error; if (options & O_DIRECTORY && !handle->isDirectory()) return -ENOTDIR; // FIXME: This should be handled by VFS::open. diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 4f31ca7daf..5cdcb1cd90 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -131,7 +131,8 @@ static void init_stage2() #ifdef KSYMS { - auto handle = vfs->open("/kernel.map"); + int error; + auto handle = vfs->open("/kernel.map", error); if (!handle) { kprintf("Failed to open /kernel.map\n"); } else { diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index 5145d9a1d1..6da36472a7 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -363,11 +363,10 @@ bool VirtualFileSystem::touch(const String& path) return inode.fileSystem()->setModificationTime(inode, ktime(nullptr)); } -OwnPtr VirtualFileSystem::open(const String& path, int options, InodeIdentifier base) +OwnPtr VirtualFileSystem::open(const String& path, int& error, int options, InodeIdentifier base) { Locker locker(VirtualFileSystem::lock()); - int error; auto inode = resolvePath(path, error, base, options); if (!inode.isValid()) return nullptr; @@ -397,15 +396,12 @@ OwnPtr VirtualFileSystem::mkdir(const String& path, InodeIdentifier return nullptr; } -InodeIdentifier VirtualFileSystem::resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode) +InodeIdentifier VirtualFileSystem::resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error) { auto symlinkContents = symlinkInode.readEntireFile(); if (!symlinkContents) return { }; - char buf[4096]; - ksprintf(buf, "/%s/%s", basePath.characters(), String((const char*)symlinkContents.pointer(), symlinkContents.size()).characters()); - int error; - return resolvePath(buf, error); + return resolvePath((const char*)symlinkContents.pointer(), error, base); } String VirtualFileSystem::absolutePath(InodeIdentifier inode) @@ -474,12 +470,13 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, int& error, I error = -EIO; return { }; } + auto parent = inode; inode = inode.fileSystem()->childOfDirectoryInodeWithName(inode, part); if (!inode.isValid()) { #ifdef VFS_DEBUG kprintf("bad child\n"); #endif - error = -EIO; + error = -ENOENT; return { }; } #ifdef VFS_DEBUG @@ -514,10 +511,9 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, int& error, I for (unsigned j = 0; j < i; ++j) { p += ksprintf(p, "/%s", parts[j].characters()); } - inode = resolveSymbolicLink(buf, inode); + inode = resolveSymbolicLink(parent, inode, error); if (!inode.isValid()) { kprintf("Symbolic link resolution failed :(\n"); - error = -ENOENT; return { }; } } diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index c697b0df4c..183fba5a1c 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -86,7 +86,7 @@ public: bool mountRoot(RetainPtr&&); bool mount(RetainPtr&&, const String& path); - OwnPtr open(const String& path, int options = 0, InodeIdentifier base = InodeIdentifier()); + OwnPtr open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier()); OwnPtr create(const String& path, InodeIdentifier base = InodeIdentifier()); OwnPtr mkdir(const String& path, InodeIdentifier base = InodeIdentifier()); @@ -106,7 +106,7 @@ private: void enumerateDirectoryInode(InodeIdentifier, Function); InodeIdentifier resolvePath(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0); - InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode); + InodeIdentifier resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error); RetainPtr allocateNode(); void freeNode(Node*);