Browse Source

Kernel: Separate VFS stat() from open().

It was very confusing that you had to open a FileDescriptor in order to stat
a file. This patch gives VFS a separate stat() function and uses it to
implement the stat() and lstat() syscalls.
Andreas Kling 6 years ago
parent
commit
ce3b548077
3 changed files with 20 additions and 8 deletions
  1. 4 6
      Kernel/Process.cpp
  2. 15 1
      Kernel/VirtualFileSystem.cpp
  3. 1 1
      Kernel/VirtualFileSystem.h

+ 4 - 6
Kernel/Process.cpp

@@ -1217,10 +1217,9 @@ int Process::sys$lstat(const char* path, stat* statbuf)
     if (!validate_write_typed(statbuf))
         return -EFAULT;
     int error;
-    auto descriptor = VFS::the().open(move(path), error, O_NOFOLLOW_NOERROR | O_DONT_OPEN_DEVICE, 0, *cwd_inode());
-    if (!descriptor)
+    if (!VFS::the().stat(move(path), error, O_NOFOLLOW_NOERROR, *cwd_inode(), *statbuf))
         return error;
-    return descriptor->fstat(statbuf);
+    return 0;
 }
 
 int Process::sys$stat(const char* path, stat* statbuf)
@@ -1228,10 +1227,9 @@ int Process::sys$stat(const char* path, stat* statbuf)
     if (!validate_write_typed(statbuf))
         return -EFAULT;
     int error;
-    auto descriptor = VFS::the().open(move(path), error, O_DONT_OPEN_DEVICE, 0, *cwd_inode());
-    if (!descriptor)
+    if (!VFS::the().stat(move(path), error, 0, *cwd_inode(), *statbuf))
         return error;
-    return descriptor->fstat(statbuf);
+    return 0;
 }
 
 int Process::sys$readlink(const char* path, char* buffer, size_t size)

+ 15 - 1
Kernel/VirtualFileSystem.cpp

@@ -131,6 +131,17 @@ RetainPtr<FileDescriptor> VFS::open(RetainPtr<Device>&& device, int& error, int
     return FileDescriptor::create(move(device));
 }
 
+bool VFS::stat(const String& path, int& error, int options, Inode& base, struct stat& statbuf)
+{
+    auto inode_id = resolve_path(path, base.identifier(), error, options);
+    if (!inode_id.is_valid())
+        return false;
+    error = FileDescriptor::create(get_inode(inode_id))->fstat(&statbuf);
+    if (error)
+        return false;
+    return true;
+}
+
 RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options, mode_t mode, Inode& base)
 {
     auto inode_id = resolve_path(path, base.identifier(), error, options);
@@ -145,7 +156,9 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
     }
     if (!inode)
         return nullptr;
+
     auto metadata = inode->metadata();
+
     // NOTE: Read permission is a bit weird, since O_RDONLY == 0,
     //       so we check if (NOT write_only OR read_and_write)
     if (!(options & O_WRONLY) || (options & O_RDWR)) {
@@ -160,7 +173,8 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
             return nullptr;
         }
     }
-    if (!(options & O_DONT_OPEN_DEVICE) && metadata.is_device()) {
+
+    if (metadata.is_device()) {
         auto it = m_devices.find(encoded_device(metadata.major_device, metadata.minor_device));
         if (it == m_devices.end()) {
             kprintf("VFS::open: no such device %u,%u\n", metadata.major_device, metadata.minor_device);

+ 1 - 1
Kernel/VirtualFileSystem.h

@@ -24,7 +24,6 @@
 #define O_NOFOLLOW 00400000
 #define O_CLOEXEC 02000000
 #define O_NOFOLLOW_NOERROR 0x4000000
-#define O_DONT_OPEN_DEVICE 0x8000000
 
 class Device;
 class FileDescriptor;
@@ -70,6 +69,7 @@ public:
     bool unlink(const String& path, Inode& base, int& error);
     bool rmdir(const String& path, Inode& base, int& error);
     bool chmod(const String& path, mode_t, Inode& base, int& error);
+    bool stat(const String& path, int& error, int options, Inode& base, struct stat&);
 
     void register_device(Device&);
     void unregister_device(Device&);