mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 05:08:13 +00:00
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.
This commit is contained in:
parent
f5f136931a
commit
ce3b548077
3 changed files with 20 additions and 8 deletions
|
@ -1217,10 +1217,9 @@ int Process::sys$lstat(const char* path, stat* statbuf)
|
||||||
if (!validate_write_typed(statbuf))
|
if (!validate_write_typed(statbuf))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
int error;
|
int error;
|
||||||
auto descriptor = VFS::the().open(move(path), error, O_NOFOLLOW_NOERROR | O_DONT_OPEN_DEVICE, 0, *cwd_inode());
|
if (!VFS::the().stat(move(path), error, O_NOFOLLOW_NOERROR, *cwd_inode(), *statbuf))
|
||||||
if (!descriptor)
|
|
||||||
return error;
|
return error;
|
||||||
return descriptor->fstat(statbuf);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::sys$stat(const char* path, stat* statbuf)
|
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))
|
if (!validate_write_typed(statbuf))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
int error;
|
int error;
|
||||||
auto descriptor = VFS::the().open(move(path), error, O_DONT_OPEN_DEVICE, 0, *cwd_inode());
|
if (!VFS::the().stat(move(path), error, 0, *cwd_inode(), *statbuf))
|
||||||
if (!descriptor)
|
|
||||||
return error;
|
return error;
|
||||||
return descriptor->fstat(statbuf);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::sys$readlink(const char* path, char* buffer, size_t size)
|
int Process::sys$readlink(const char* path, char* buffer, size_t size)
|
||||||
|
|
|
@ -131,6 +131,17 @@ RetainPtr<FileDescriptor> VFS::open(RetainPtr<Device>&& device, int& error, int
|
||||||
return FileDescriptor::create(move(device));
|
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)
|
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);
|
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)
|
if (!inode)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto metadata = inode->metadata();
|
auto metadata = inode->metadata();
|
||||||
|
|
||||||
// NOTE: Read permission is a bit weird, since O_RDONLY == 0,
|
// NOTE: Read permission is a bit weird, since O_RDONLY == 0,
|
||||||
// so we check if (NOT write_only OR read_and_write)
|
// so we check if (NOT write_only OR read_and_write)
|
||||||
if (!(options & O_WRONLY) || (options & O_RDWR)) {
|
if (!(options & O_WRONLY) || (options & O_RDWR)) {
|
||||||
|
@ -160,7 +173,8 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
|
||||||
return nullptr;
|
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));
|
auto it = m_devices.find(encoded_device(metadata.major_device, metadata.minor_device));
|
||||||
if (it == m_devices.end()) {
|
if (it == m_devices.end()) {
|
||||||
kprintf("VFS::open: no such device %u,%u\n", metadata.major_device, metadata.minor_device);
|
kprintf("VFS::open: no such device %u,%u\n", metadata.major_device, metadata.minor_device);
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#define O_NOFOLLOW 00400000
|
#define O_NOFOLLOW 00400000
|
||||||
#define O_CLOEXEC 02000000
|
#define O_CLOEXEC 02000000
|
||||||
#define O_NOFOLLOW_NOERROR 0x4000000
|
#define O_NOFOLLOW_NOERROR 0x4000000
|
||||||
#define O_DONT_OPEN_DEVICE 0x8000000
|
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
class FileDescriptor;
|
class FileDescriptor;
|
||||||
|
@ -70,6 +69,7 @@ public:
|
||||||
bool unlink(const String& path, Inode& base, int& error);
|
bool unlink(const String& path, Inode& base, int& error);
|
||||||
bool rmdir(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 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 register_device(Device&);
|
||||||
void unregister_device(Device&);
|
void unregister_device(Device&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue