mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:58:13 +00:00
Kernel: Split the Plan9FileSystem.{cpp,h} file into smaller components
This commit is contained in:
parent
3906dd3aa3
commit
3fc52a6d1c
10 changed files with 1138 additions and 1058 deletions
301
Kernel/FileSystem/Plan9FS/Inode.cpp
Normal file
301
Kernel/FileSystem/Plan9FS/Inode.cpp
Normal file
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/Plan9FS/Inode.h>
|
||||
#include <Kernel/Process.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
Plan9FSInode::Plan9FSInode(Plan9FS& fs, u32 fid)
|
||||
: Inode(fs, fid)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Plan9FSInode>> Plan9FSInode::try_create(Plan9FS& fs, u32 fid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) Plan9FSInode(fs, fid));
|
||||
}
|
||||
|
||||
Plan9FSInode::~Plan9FSInode()
|
||||
{
|
||||
Plan9FSMessage clunk_request { fs(), Plan9FSMessage::Type::Tclunk };
|
||||
clunk_request << fid();
|
||||
// FIXME: Should we observe this error somehow?
|
||||
[[maybe_unused]] auto rc = fs().post_message_and_explicitly_ignore_reply(clunk_request);
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::ensure_open_for_mode(int mode)
|
||||
{
|
||||
bool use_lopen = fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L;
|
||||
u32 l_mode = 0;
|
||||
u8 p9_mode = 0;
|
||||
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
|
||||
// If it's already open in this mode, we're done.
|
||||
if ((m_open_mode & mode) == mode)
|
||||
return {};
|
||||
|
||||
m_open_mode |= mode;
|
||||
|
||||
if ((m_open_mode & O_RDWR) == O_RDWR) {
|
||||
l_mode |= 2;
|
||||
p9_mode |= 2;
|
||||
} else if (m_open_mode & O_WRONLY) {
|
||||
l_mode |= 1;
|
||||
p9_mode |= 1;
|
||||
} else if (m_open_mode & O_RDONLY) {
|
||||
// Leave the values at 0.
|
||||
}
|
||||
}
|
||||
|
||||
if (use_lopen) {
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tlopen };
|
||||
message << fid() << l_mode;
|
||||
return fs().post_message_and_wait_for_a_reply(message);
|
||||
}
|
||||
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Topen };
|
||||
message << fid() << p9_mode;
|
||||
return fs().post_message_and_wait_for_a_reply(message);
|
||||
}
|
||||
|
||||
ErrorOr<size_t> Plan9FSInode::read_bytes_locked(off_t offset, size_t size, UserOrKernelBuffer& buffer, OpenFileDescription*) const
|
||||
{
|
||||
TRY(const_cast<Plan9FSInode&>(*this).ensure_open_for_mode(O_RDONLY));
|
||||
|
||||
size = fs().adjust_buffer_size(size);
|
||||
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Treadlink };
|
||||
StringView data;
|
||||
|
||||
// Try readlink first.
|
||||
bool readlink_succeeded = false;
|
||||
if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L && offset == 0) {
|
||||
message << fid();
|
||||
if (auto result = fs().post_message_and_wait_for_a_reply(message); !result.is_error()) {
|
||||
readlink_succeeded = true;
|
||||
message >> data;
|
||||
}
|
||||
}
|
||||
|
||||
if (!readlink_succeeded) {
|
||||
message = Plan9FSMessage { fs(), Plan9FSMessage::Type::Tread };
|
||||
message << fid() << (u64)offset << (u32)size;
|
||||
TRY(fs().post_message_and_wait_for_a_reply(message));
|
||||
data = message.read_data();
|
||||
}
|
||||
|
||||
// Guard against the server returning more data than requested.
|
||||
size_t nread = min(data.length(), size);
|
||||
TRY(buffer.write(data.characters_without_null_termination(), nread));
|
||||
return nread;
|
||||
}
|
||||
|
||||
ErrorOr<size_t> Plan9FSInode::write_bytes_locked(off_t offset, size_t size, UserOrKernelBuffer const& data, OpenFileDescription*)
|
||||
{
|
||||
TRY(ensure_open_for_mode(O_WRONLY));
|
||||
size = fs().adjust_buffer_size(size);
|
||||
|
||||
auto data_copy = TRY(data.try_copy_into_kstring(size)); // FIXME: this seems ugly
|
||||
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Twrite };
|
||||
message << fid() << (u64)offset;
|
||||
message.append_data(data_copy->view());
|
||||
TRY(fs().post_message_and_wait_for_a_reply(message));
|
||||
|
||||
u32 nwritten;
|
||||
message >> nwritten;
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
InodeMetadata Plan9FSInode::metadata() const
|
||||
{
|
||||
InodeMetadata metadata;
|
||||
metadata.inode = identifier();
|
||||
|
||||
// 9P2000.L; TODO: 9P2000 & 9P2000.u
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tgetattr };
|
||||
message << fid() << (u64)GetAttrMask::Basic;
|
||||
auto result = fs().post_message_and_wait_for_a_reply(message);
|
||||
if (result.is_error()) {
|
||||
// Just return blank metadata; hopefully that's enough to result in an
|
||||
// error at some upper layer. Ideally, there would be a way for
|
||||
// Inode::metadata() to return failure.
|
||||
return metadata;
|
||||
}
|
||||
|
||||
u64 valid;
|
||||
Plan9FSQIdentifier qid;
|
||||
u32 mode;
|
||||
u32 uid;
|
||||
u32 gid;
|
||||
u64 nlink;
|
||||
u64 rdev;
|
||||
u64 size;
|
||||
u64 blksize;
|
||||
u64 blocks;
|
||||
message >> valid >> qid >> mode >> uid >> gid >> nlink >> rdev >> size >> blksize >> blocks;
|
||||
// TODO: times...
|
||||
|
||||
if (valid & (u64)GetAttrMask::Mode)
|
||||
metadata.mode = mode;
|
||||
if (valid & (u64)GetAttrMask::NLink)
|
||||
metadata.link_count = nlink;
|
||||
|
||||
#if 0
|
||||
// FIXME: Map UID/GID somehow? Or what do we do?
|
||||
if (valid & (u64)GetAttrMask::UID)
|
||||
metadata.uid = uid;
|
||||
if (valid & (u64)GetAttrMask::GID)
|
||||
metadata.uid = gid;
|
||||
// FIXME: What about device nodes?
|
||||
if (valid & (u64)GetAttrMask::RDev)
|
||||
metadata.encoded_device = 0; // TODO
|
||||
#endif
|
||||
|
||||
if (valid & (u64)GetAttrMask::Size)
|
||||
metadata.size = size;
|
||||
if (valid & (u64)GetAttrMask::Blocks) {
|
||||
metadata.block_size = blksize;
|
||||
metadata.block_count = blocks;
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::flush_metadata()
|
||||
{
|
||||
// Do nothing.
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||
{
|
||||
// TODO: Should we synthesize "." and ".." here?
|
||||
|
||||
if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L) {
|
||||
// Start by cloning the fid and opening it.
|
||||
auto clone_fid = fs().allocate_fid();
|
||||
{
|
||||
Plan9FSMessage clone_message { fs(), Plan9FSMessage::Type::Twalk };
|
||||
clone_message << fid() << clone_fid << (u16)0;
|
||||
TRY(fs().post_message_and_wait_for_a_reply(clone_message));
|
||||
Plan9FSMessage open_message { fs(), Plan9FSMessage::Type::Tlopen };
|
||||
open_message << clone_fid << (u32)0;
|
||||
auto result = fs().post_message_and_wait_for_a_reply(open_message);
|
||||
if (result.is_error()) {
|
||||
Plan9FSMessage close_message { fs(), Plan9FSMessage::Type::Tclunk };
|
||||
close_message << clone_fid;
|
||||
// FIXME: Should we observe this error?
|
||||
[[maybe_unused]] auto rc = fs().post_message_and_explicitly_ignore_reply(close_message);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
u64 offset = 0;
|
||||
u32 count = fs().adjust_buffer_size(8 * MiB);
|
||||
ErrorOr<void> result;
|
||||
|
||||
while (true) {
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Treaddir };
|
||||
message << clone_fid << offset << count;
|
||||
result = fs().post_message_and_wait_for_a_reply(message);
|
||||
if (result.is_error())
|
||||
break;
|
||||
|
||||
StringView data = message.read_data();
|
||||
if (data.is_empty()) {
|
||||
// We've reached the end.
|
||||
break;
|
||||
}
|
||||
|
||||
for (Plan9FSMessage::Decoder decoder { data }; decoder.has_more_data();) {
|
||||
Plan9FSQIdentifier qid;
|
||||
u8 type;
|
||||
StringView name;
|
||||
decoder >> qid >> offset >> type >> name;
|
||||
result = callback({ name, { fsid(), fs().allocate_fid() }, 0 });
|
||||
if (result.is_error())
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.is_error())
|
||||
break;
|
||||
}
|
||||
|
||||
Plan9FSMessage close_message { fs(), Plan9FSMessage::Type::Tclunk };
|
||||
close_message << clone_fid;
|
||||
// FIXME: Should we observe this error?
|
||||
[[maybe_unused]] auto rc = fs().post_message_and_explicitly_ignore_reply(close_message);
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> Plan9FSInode::lookup(StringView name)
|
||||
{
|
||||
u32 newfid = fs().allocate_fid();
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Twalk };
|
||||
message << fid() << newfid << (u16)1 << name;
|
||||
TRY(fs().post_message_and_wait_for_a_reply(message));
|
||||
return TRY(Plan9FSInode::try_create(fs(), newfid));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> Plan9FSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID)
|
||||
{
|
||||
// TODO
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::add_child(Inode&, StringView, mode_t)
|
||||
{
|
||||
// TODO
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::remove_child(StringView)
|
||||
{
|
||||
// TODO
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::chmod(mode_t)
|
||||
{
|
||||
// TODO
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::chown(UserID, GroupID)
|
||||
{
|
||||
// TODO
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<void> Plan9FSInode::truncate(u64 new_size)
|
||||
{
|
||||
if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L) {
|
||||
Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tsetattr };
|
||||
SetAttrMask valid = SetAttrMask::Size;
|
||||
u32 mode = 0;
|
||||
u32 uid = 0;
|
||||
u32 gid = 0;
|
||||
u64 atime_sec = 0;
|
||||
u64 atime_nsec = 0;
|
||||
u64 mtime_sec = 0;
|
||||
u64 mtime_nsec = 0;
|
||||
message << fid() << (u64)valid << mode << uid << gid << new_size << atime_sec << atime_nsec << mtime_sec << mtime_nsec;
|
||||
return fs().post_message_and_wait_for_a_reply(message);
|
||||
}
|
||||
|
||||
// TODO: wstat version
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue