mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05:00
Kernel: Plumb KResult through FileDescription::read_entire_file() implementation.
Allow file system implementation to return meaningful error codes to callers of the FileDescription::read_entire_file(). This allows both Process::sys$readlink() and Process::sys$module_load() to return more detailed errors to the user.
This commit is contained in:
parent
c459e4ecb2
commit
6a74af8063
14 changed files with 54 additions and 36 deletions
|
@ -146,10 +146,10 @@ InodeMetadata DevPtsFSInode::metadata() const
|
|||
return m_metadata;
|
||||
}
|
||||
|
||||
bool DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
KResult DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
{
|
||||
if (identifier().index() > 1)
|
||||
return false;
|
||||
return KResult(-ENOTDIR);
|
||||
|
||||
callback({ ".", 1, identifier(), 0 });
|
||||
callback({ "..", 2, identifier(), 0 });
|
||||
|
@ -160,7 +160,7 @@ bool DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry
|
|||
callback({ name.characters(), name.length(), identifier, 0 });
|
||||
}
|
||||
|
||||
return true;
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
size_t DevPtsFSInode::directory_entry_count() const
|
||||
|
|
|
@ -69,7 +69,7 @@ private:
|
|||
// ^Inode
|
||||
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual RefPtr<Inode> lookup(StringView name) override;
|
||||
virtual void flush_metadata() override;
|
||||
virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
|
||||
|
|
|
@ -849,7 +849,7 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, Fi
|
|||
return nwritten;
|
||||
}
|
||||
|
||||
bool Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
KResult Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
ASSERT(is_directory());
|
||||
|
@ -858,8 +858,12 @@ bool Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)
|
|||
dbg() << "Ext2FS: Traversing as directory: " << identifier();
|
||||
#endif
|
||||
|
||||
auto buffer = read_entire();
|
||||
ASSERT(buffer);
|
||||
auto buffer_or = read_entire();
|
||||
ASSERT(!buffer_or.is_error());
|
||||
if (buffer_or.is_error())
|
||||
return buffer_or.error();
|
||||
|
||||
auto buffer = buffer_or.value();
|
||||
auto* entry = reinterpret_cast<ext2_dir_entry_2*>(buffer.data());
|
||||
|
||||
while (entry < buffer.end_pointer()) {
|
||||
|
@ -872,7 +876,8 @@ bool Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)
|
|||
}
|
||||
entry = (ext2_dir_entry_2*)((char*)entry + entry->rec_len);
|
||||
}
|
||||
return true;
|
||||
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
bool Ext2FSInode::write_directory(const Vector<FS::DirectoryEntry>& entries)
|
||||
|
@ -944,7 +949,7 @@ KResult Ext2FSInode::add_child(InodeIdentifier child_id, const StringView& name,
|
|||
|
||||
Vector<FS::DirectoryEntry> entries;
|
||||
bool name_already_exists = false;
|
||||
traverse_as_directory([&](auto& entry) {
|
||||
KResult result = traverse_as_directory([&](auto& entry) {
|
||||
if (name == entry.name) {
|
||||
name_already_exists = true;
|
||||
return false;
|
||||
|
@ -952,6 +957,10 @@ KResult Ext2FSInode::add_child(InodeIdentifier child_id, const StringView& name,
|
|||
entries.append(entry);
|
||||
return true;
|
||||
});
|
||||
|
||||
if (result.is_error())
|
||||
return result;
|
||||
|
||||
if (name_already_exists) {
|
||||
dbg() << "Ext2FSInode::add_child(): Name '" << name << "' already exists in inode " << index();
|
||||
return KResult(-EEXIST);
|
||||
|
@ -959,7 +968,7 @@ KResult Ext2FSInode::add_child(InodeIdentifier child_id, const StringView& name,
|
|||
|
||||
auto child_inode = fs().get_inode(child_id);
|
||||
if (child_inode) {
|
||||
auto result = child_inode->increment_link_count();
|
||||
result = child_inode->increment_link_count();
|
||||
if (result.is_error())
|
||||
return result;
|
||||
}
|
||||
|
@ -991,11 +1000,13 @@ KResult Ext2FSInode::remove_child(const StringView& name)
|
|||
#endif
|
||||
|
||||
Vector<FS::DirectoryEntry> entries;
|
||||
traverse_as_directory([&](auto& entry) {
|
||||
KResult result = traverse_as_directory([&](auto& entry) {
|
||||
if (name != entry.name)
|
||||
entries.append(entry);
|
||||
return true;
|
||||
});
|
||||
if (result.is_error())
|
||||
return result;
|
||||
|
||||
bool success = write_directory(entries);
|
||||
if (!success) {
|
||||
|
|
|
@ -59,7 +59,7 @@ private:
|
|||
// ^Inode
|
||||
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual RefPtr<Inode> lookup(StringView name) override;
|
||||
virtual void flush_metadata() override;
|
||||
virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) override;
|
||||
|
|
|
@ -158,7 +158,7 @@ bool FileDescription::can_read() const
|
|||
return m_file->can_read(*this, offset());
|
||||
}
|
||||
|
||||
ByteBuffer FileDescription::read_entire_file()
|
||||
KResultOr<ByteBuffer> FileDescription::read_entire_file()
|
||||
{
|
||||
// HACK ALERT: (This entire function)
|
||||
ASSERT(m_file->is_inode());
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
|
||||
ssize_t get_dir_entries(u8* buffer, ssize_t);
|
||||
|
||||
ByteBuffer read_entire_file();
|
||||
KResultOr<ByteBuffer> read_entire_file();
|
||||
|
||||
String absolute_path() const;
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ void Inode::sync()
|
|||
}
|
||||
}
|
||||
|
||||
ByteBuffer Inode::read_entire(FileDescription* descriptor) const
|
||||
KResultOr<ByteBuffer> Inode::read_entire(FileDescription* descriptor) const
|
||||
{
|
||||
size_t initial_size = metadata().size ? metadata().size : 4096;
|
||||
StringBuilder builder(initial_size);
|
||||
|
@ -92,8 +92,11 @@ KResultOr<NonnullRefPtr<Custody>> Inode::resolve_as_link(Custody& base, RefPtr<C
|
|||
// The default implementation simply treats the stored
|
||||
// contents as a path and resolves that. That is, it
|
||||
// behaves exactly how you would expect a symlink to work.
|
||||
auto contents = read_entire();
|
||||
auto contents_or = read_entire();
|
||||
if (contents_or.is_error())
|
||||
return contents_or.error();
|
||||
|
||||
auto& contents = contents_or.value();
|
||||
if (!contents) {
|
||||
if (out_parent)
|
||||
*out_parent = nullptr;
|
||||
|
|
|
@ -66,10 +66,10 @@ public:
|
|||
InodeIdentifier identifier() const { return { fsid(), index() }; }
|
||||
virtual InodeMetadata metadata() const = 0;
|
||||
|
||||
ByteBuffer read_entire(FileDescription* = nullptr) const;
|
||||
KResultOr<ByteBuffer> read_entire(FileDescription* = nullptr) const;
|
||||
|
||||
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const = 0;
|
||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const = 0;
|
||||
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const = 0;
|
||||
virtual RefPtr<Inode> lookup(StringView name) = 0;
|
||||
virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) = 0;
|
||||
virtual KResult add_child(InodeIdentifier child_id, const StringView& name, mode_t) = 0;
|
||||
|
|
|
@ -1253,14 +1253,14 @@ InodeIdentifier ProcFS::ProcFSDirectoryEntry::identifier(unsigned fsid) const
|
|||
return to_identifier(fsid, PDI_Root, 0, (ProcFileType)proc_file_type);
|
||||
}
|
||||
|
||||
bool ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
{
|
||||
#ifdef PROCFS_DEBUG
|
||||
dbg() << "ProcFS: traverse_as_directory " << index();
|
||||
#endif
|
||||
|
||||
if (!Kernel::is_directory(identifier()))
|
||||
return false;
|
||||
return KResult(-ENOTDIR);
|
||||
|
||||
auto pid = to_pid(identifier());
|
||||
auto proc_file_type = to_proc_file_type(identifier());
|
||||
|
@ -1303,7 +1303,7 @@ bool ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)
|
|||
case FI_PID: {
|
||||
auto handle = ProcessInspectionHandle::from_pid(pid);
|
||||
if (!handle)
|
||||
return false;
|
||||
return KResult(-ENOENT);
|
||||
auto& process = handle->process();
|
||||
for (auto& entry : fs().m_entries) {
|
||||
if (entry.proc_file_type > __FI_PID_Start && entry.proc_file_type < __FI_PID_End) {
|
||||
|
@ -1318,7 +1318,7 @@ bool ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)
|
|||
case FI_PID_fd: {
|
||||
auto handle = ProcessInspectionHandle::from_pid(pid);
|
||||
if (!handle)
|
||||
return false;
|
||||
return KResult(-ENOENT);
|
||||
auto& process = handle->process();
|
||||
for (int i = 0; i < process.max_open_file_descriptors(); ++i) {
|
||||
auto description = process.file_description(i);
|
||||
|
@ -1330,10 +1330,10 @@ bool ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)
|
|||
}
|
||||
} break;
|
||||
default:
|
||||
return true;
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
return true;
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
RefPtr<Inode> ProcFSInode::lookup(StringView name)
|
||||
|
|
|
@ -101,7 +101,7 @@ private:
|
|||
// ^Inode
|
||||
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual RefPtr<Inode> lookup(StringView name) override;
|
||||
virtual void flush_metadata() override;
|
||||
virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
|
||||
|
@ -127,7 +127,7 @@ private:
|
|||
// ^Inode
|
||||
virtual ssize_t read_bytes(off_t, ssize_t, u8*, FileDescription*) const override { ASSERT_NOT_REACHED(); }
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override { ASSERT_NOT_REACHED(); }
|
||||
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override { ASSERT_NOT_REACHED(); }
|
||||
virtual RefPtr<Inode> lookup(StringView name) override;
|
||||
virtual void flush_metadata() override {};
|
||||
virtual ssize_t write_bytes(off_t, ssize_t, const u8*, FileDescription*) override { ASSERT_NOT_REACHED(); }
|
||||
|
|
|
@ -166,19 +166,19 @@ InodeMetadata TmpFSInode::metadata() const
|
|||
return m_metadata;
|
||||
}
|
||||
|
||||
bool TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
KResult TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const
|
||||
{
|
||||
LOCKER(m_lock, Lock::Mode::Shared);
|
||||
|
||||
if (!is_directory())
|
||||
return false;
|
||||
return KResult(-ENOTDIR);
|
||||
|
||||
callback({ ".", identifier(), 0 });
|
||||
callback({ "..", m_parent, 0 });
|
||||
|
||||
for (auto& it : m_children)
|
||||
callback(it.value.entry);
|
||||
return true;
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
ssize_t TmpFSInode::read_bytes(off_t offset, ssize_t size, u8* buffer, FileDescription*) const
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
// ^Inode
|
||||
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override;
|
||||
virtual RefPtr<Inode> lookup(StringView name) override;
|
||||
virtual void flush_metadata() override;
|
||||
virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
|
||||
|
|
|
@ -194,8 +194,8 @@ void load_kernel_symbol_table()
|
|||
ASSERT(!result.is_error());
|
||||
auto description = result.value();
|
||||
auto buffer = description->read_entire_file();
|
||||
ASSERT(buffer);
|
||||
load_kernel_sybols_from_data(buffer);
|
||||
ASSERT(!buffer.is_error());
|
||||
load_kernel_sybols_from_data(buffer.value());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1944,10 +1944,10 @@ int Process::sys$readlink(const Syscall::SC_readlink_params* user_params)
|
|||
return -EINVAL;
|
||||
|
||||
auto contents = description->read_entire_file();
|
||||
if (!contents)
|
||||
return -EIO; // FIXME: Get a more detailed error from VFS.
|
||||
if (!contents.is_error())
|
||||
return contents.error();
|
||||
|
||||
auto link_target = String::copy(contents);
|
||||
auto link_target = String::copy(contents.value());
|
||||
if (link_target.length() > params.buffer.size)
|
||||
return -ENAMETOOLONG;
|
||||
copy_to_user(params.buffer.data, link_target.characters(), link_target.length());
|
||||
|
@ -4444,7 +4444,11 @@ int Process::sys$module_load(const char* user_path, size_t path_length)
|
|||
if (description_or_error.is_error())
|
||||
return description_or_error.error();
|
||||
auto& description = description_or_error.value();
|
||||
auto payload = description->read_entire_file();
|
||||
auto payload_or_error = description->read_entire_file();
|
||||
if (payload_or_error.is_error())
|
||||
return payload_or_error.error();
|
||||
|
||||
auto payload = payload_or_error.value();
|
||||
auto storage = KBuffer::create_with_size(payload.size());
|
||||
memcpy(storage.data(), payload.data(), payload.size());
|
||||
payload.clear();
|
||||
|
|
Loading…
Add table
Reference in a new issue