Explorar el Código

Fix up VFS::resolveSymbolicLink() to use a base inode instead of a base path.

Also more VFS error plumbing.
Andreas Kling hace 6 años
padre
commit
bea106fdb2

+ 14 - 12
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();
             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;
         return nullptr;
-    }
 
 
     if (!handle->metadata().mayExecute(uid, gid)) {
     if (!handle->metadata().mayExecute(uid, gid)) {
         error = -EACCES;
         error = -EACCES;
@@ -786,9 +784,10 @@ int Task::sys$close(int fd)
 int Task::sys$lstat(const char* path, Unix::stat* statbuf)
 int Task::sys$lstat(const char* path, Unix::stat* statbuf)
 {
 {
     VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
     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)
     if (!handle)
-        return -1;
+        return error;
     handle->stat(statbuf);
     handle->stat(statbuf);
     return 0;
     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(path, strlen(path));
     VALIDATE_USER_BUFFER(buffer, size);
     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)
     if (!handle)
-        return -ENOENT; // FIXME: Get a more detailed error from VFS.
+        return error;
 
 
     if (!handle->metadata().isSymbolicLink())
     if (!handle->metadata().isSymbolicLink())
         return -EINVAL;
         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)
 int Task::sys$chdir(const char* path)
 {
 {
     VALIDATE_USER_BUFFER(path, strlen(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)
     if (!handle)
-        return -ENOENT; // FIXME: More detailed error.
+        return error;
     if (!handle->isDirectory())
     if (!handle->isDirectory())
         return -ENOTDIR;
         return -ENOTDIR;
     m_cwd = handle->vnode();
     m_cwd = handle->vnode();
@@ -842,9 +843,10 @@ int Task::sys$open(const char* path, int options)
     VALIDATE_USER_BUFFER(path, strlen(path));
     VALIDATE_USER_BUFFER(path, strlen(path));
     if (m_fileHandles.size() >= m_maxFileHandles)
     if (m_fileHandles.size() >= m_maxFileHandles)
         return -EMFILE;
         return -EMFILE;
-    auto handle = VirtualFileSystem::the().open(path, 0, cwdInode());
+    int error;
+    auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode());
     if (!handle)
     if (!handle)
-        return -ENOENT; // FIXME: Detailed error.
+        return error;
     if (options & O_DIRECTORY && !handle->isDirectory())
     if (options & O_DIRECTORY && !handle->isDirectory())
         return -ENOTDIR; // FIXME: This should be handled by VFS::open.
         return -ENOTDIR; // FIXME: This should be handled by VFS::open.
 
 

+ 2 - 1
Kernel/init.cpp

@@ -131,7 +131,8 @@ static void init_stage2()
 
 
 #ifdef KSYMS
 #ifdef KSYMS
     {
     {
-        auto handle = vfs->open("/kernel.map");
+        int error;
+        auto handle = vfs->open("/kernel.map", error);
         if (!handle) {
         if (!handle) {
             kprintf("Failed to open /kernel.map\n");
             kprintf("Failed to open /kernel.map\n");
         } else {
         } else {

+ 6 - 10
VirtualFileSystem/VirtualFileSystem.cpp

@@ -363,11 +363,10 @@ bool VirtualFileSystem::touch(const String& path)
     return inode.fileSystem()->setModificationTime(inode, ktime(nullptr));
     return inode.fileSystem()->setModificationTime(inode, ktime(nullptr));
 }
 }
 
 
-OwnPtr<FileHandle> VirtualFileSystem::open(const String& path, int options, InodeIdentifier base)
+OwnPtr<FileHandle> VirtualFileSystem::open(const String& path, int& error, int options, InodeIdentifier base)
 {
 {
     Locker locker(VirtualFileSystem::lock());
     Locker locker(VirtualFileSystem::lock());
 
 
-    int error;
     auto inode = resolvePath(path, error, base, options);
     auto inode = resolvePath(path, error, base, options);
     if (!inode.isValid())
     if (!inode.isValid())
         return nullptr;
         return nullptr;
@@ -397,15 +396,12 @@ OwnPtr<FileHandle> VirtualFileSystem::mkdir(const String& path, InodeIdentifier
     return nullptr;
     return nullptr;
 }
 }
 
 
-InodeIdentifier VirtualFileSystem::resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode)
+InodeIdentifier VirtualFileSystem::resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error)
 {
 {
     auto symlinkContents = symlinkInode.readEntireFile();
     auto symlinkContents = symlinkInode.readEntireFile();
     if (!symlinkContents)
     if (!symlinkContents)
         return { };
         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)
 String VirtualFileSystem::absolutePath(InodeIdentifier inode)
@@ -474,12 +470,13 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, int& error, I
             error = -EIO;
             error = -EIO;
             return { };
             return { };
         }
         }
+        auto parent = inode;
         inode = inode.fileSystem()->childOfDirectoryInodeWithName(inode, part);
         inode = inode.fileSystem()->childOfDirectoryInodeWithName(inode, part);
         if (!inode.isValid()) {
         if (!inode.isValid()) {
 #ifdef VFS_DEBUG
 #ifdef VFS_DEBUG
             kprintf("bad child\n");
             kprintf("bad child\n");
 #endif
 #endif
-            error = -EIO;
+            error = -ENOENT;
             return { };
             return { };
         }
         }
 #ifdef VFS_DEBUG
 #ifdef VFS_DEBUG
@@ -514,10 +511,9 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, int& error, I
             for (unsigned j = 0; j < i; ++j) {
             for (unsigned j = 0; j < i; ++j) {
                 p += ksprintf(p, "/%s", parts[j].characters());
                 p += ksprintf(p, "/%s", parts[j].characters());
             }
             }
-            inode = resolveSymbolicLink(buf, inode);
+            inode = resolveSymbolicLink(parent, inode, error);
             if (!inode.isValid()) {
             if (!inode.isValid()) {
                 kprintf("Symbolic link resolution failed :(\n");
                 kprintf("Symbolic link resolution failed :(\n");
-                error = -ENOENT;
                 return { };
                 return { };
             }
             }
         }
         }

+ 2 - 2
VirtualFileSystem/VirtualFileSystem.h

@@ -86,7 +86,7 @@ public:
     bool mountRoot(RetainPtr<FileSystem>&&);
     bool mountRoot(RetainPtr<FileSystem>&&);
     bool mount(RetainPtr<FileSystem>&&, const String& path);
     bool mount(RetainPtr<FileSystem>&&, const String& path);
 
 
-    OwnPtr<FileHandle> open(const String& path, int options = 0, InodeIdentifier base = InodeIdentifier());
+    OwnPtr<FileHandle> open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier());
     OwnPtr<FileHandle> create(const String& path, InodeIdentifier base = InodeIdentifier());
     OwnPtr<FileHandle> create(const String& path, InodeIdentifier base = InodeIdentifier());
     OwnPtr<FileHandle> mkdir(const String& path, InodeIdentifier base = InodeIdentifier());
     OwnPtr<FileHandle> mkdir(const String& path, InodeIdentifier base = InodeIdentifier());
 
 
@@ -106,7 +106,7 @@ private:
 
 
     void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>);
     void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>);
     InodeIdentifier resolvePath(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0);
     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<Node> allocateNode();
     RetainPtr<Node> allocateNode();
     void freeNode(Node*);
     void freeNode(Node*);