浏览代码

FileSystem: Merge symlink following logic into path resolution.

When encountering a symlink, we abandon the custody chain we've been working
on and start over with a new one (by recursing into a new resolution call.)
Caching symlinks in the custody model would be incredibly difficult to get
right with all the extra invalidation it would require, so let's just not.
Andreas Kling 6 年之前
父节点
当前提交
e6a8133b0c
共有 2 个文件被更改,包括 14 次插入16 次删除
  1. 14 15
      Kernel/FileSystem/VirtualFileSystem.cpp
  2. 0 1
      Kernel/FileSystem/VirtualFileSystem.h

+ 14 - 15
Kernel/FileSystem/VirtualFileSystem.cpp

@@ -545,18 +545,6 @@ KResult VFS::rmdir(StringView path, Custody& base)
     return parent_inode.remove_child(FileSystemPath(path).basename());
 }
 
-KResultOr<Retained<Custody>> VFS::resolve_symbolic_link(Custody& base, Inode& symlink_inode)
-{
-    auto symlink_contents = symlink_inode.read_entire();
-    if (!symlink_contents)
-        return KResult(-ENOENT);
-    auto linkee = StringView(symlink_contents.pointer(), symlink_contents.size());
-#ifdef VFS_DEBUG
-    kprintf("linkee (%s)(%u) from %u:%u\n", linkee.characters(), linkee.length(), base.fsid(), base.index());
-#endif
-    return resolve_path_to_custody(linkee, base);
-}
-
 RetainPtr<Inode> VFS::get_inode(InodeIdentifier inode_id)
 {
     if (!inode_id.is_valid())
@@ -659,6 +647,7 @@ KResultOr<Retained<Custody>> VFS::resolve_path_to_custody(StringView path, Custo
             return KResult(-ENOTDIR);
         if (!metadata.may_execute(current->process()))
             return KResult(-EACCES);
+        auto current_parent = custody_chain.last();
         crumb_id = crumb_inode->lookup(part);
         if (!crumb_id.is_valid())
             return KResult(-ENOENT);
@@ -672,7 +661,9 @@ KResultOr<Retained<Custody>> VFS::resolve_path_to_custody(StringView path, Custo
         }
         crumb_inode = get_inode(crumb_id);
         ASSERT(crumb_inode);
+
         custody_chain.append(Custody::create(custody_chain.last().ptr(), part, *crumb_inode));
+
         metadata = crumb_inode->metadata();
         if (metadata.is_directory()) {
             if (i != parts.size() - 1) {
@@ -687,10 +678,18 @@ KResultOr<Retained<Custody>> VFS::resolve_path_to_custody(StringView path, Custo
                 if (options & O_NOFOLLOW_NOERROR)
                     return custody_chain.last();
             }
-            auto result = resolve_symbolic_link(*custody_chain.last(), *crumb_inode);
-            if (result.is_error())
+            auto symlink_contents = crumb_inode->read_entire();
+            if (!symlink_contents)
                 return KResult(-ENOENT);
-            crumb_id = result.value()->inode().identifier();
+
+            // FIXME: We should limit the recursion here and return -ELOOP if it goes to deep.
+            return resolve_path_to_custody(
+                StringView(symlink_contents.pointer(),
+                symlink_contents.size()),
+                *current_parent,
+                parent_custody,
+                options
+            );
         }
     }
     return custody_chain.last();

+ 0 - 1
Kernel/FileSystem/VirtualFileSystem.h

@@ -108,7 +108,6 @@ private:
     bool is_vfs_root(InodeIdentifier) const;
 
     void traverse_directory_inode(Inode&, Function<bool(const FS::DirectoryEntry&)>);
-    KResultOr<Retained<Custody>> resolve_symbolic_link(Custody& base, Inode& symlink_inode);
 
     Mount* find_mount_for_host(InodeIdentifier);
     Mount* find_mount_for_guest(InodeIdentifier);