mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:17:42 +00:00
ProcFS: Implement symlink magic
This commit is contained in:
parent
8642a7046c
commit
68aeefa49b
2 changed files with 148 additions and 0 deletions
|
@ -1366,6 +1366,119 @@ ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, F
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KResultOr<NonnullRefPtr<Custody>> ProcFSInode::resolve_as_link(Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const
|
||||||
|
{
|
||||||
|
if (!is_process_related_file(identifier()))
|
||||||
|
return Inode::resolve_as_link(base, out_parent, options, symlink_recursion_level);
|
||||||
|
|
||||||
|
// FIXME: We should return a custody for FI_PID or FI_PID_fd here
|
||||||
|
// for correctness. It's impossible to create files in ProcFS,
|
||||||
|
// so returning null shouldn't break much.
|
||||||
|
if (out_parent)
|
||||||
|
*out_parent = nullptr;
|
||||||
|
|
||||||
|
auto pid = to_pid(identifier());
|
||||||
|
auto proc_file_type = to_proc_file_type(identifier());
|
||||||
|
auto handle = ProcessInspectionHandle::from_pid(pid);
|
||||||
|
if (!handle)
|
||||||
|
return KResult(-ENOENT);
|
||||||
|
auto& process = handle->process();
|
||||||
|
|
||||||
|
if (to_proc_parent_directory(identifier()) == PDI_PID_fd) {
|
||||||
|
if (out_parent)
|
||||||
|
*out_parent = base;
|
||||||
|
int fd = to_fd(identifier());
|
||||||
|
auto description = process.file_description(fd);
|
||||||
|
if (!description)
|
||||||
|
return KResult(-ENOENT);
|
||||||
|
auto proxy_inode = ProcFSProxyInode::create(const_cast<ProcFS&>(fs()), *description);
|
||||||
|
return Custody::create(&base, "", proxy_inode, base.mount_flags());
|
||||||
|
}
|
||||||
|
|
||||||
|
Custody* res = nullptr;
|
||||||
|
|
||||||
|
switch (proc_file_type) {
|
||||||
|
case FI_PID_cwd:
|
||||||
|
res = &process.current_directory();
|
||||||
|
break;
|
||||||
|
case FI_PID_exe:
|
||||||
|
res = process.executable();
|
||||||
|
break;
|
||||||
|
case FI_PID_root:
|
||||||
|
// Note: we open root_directory() here, not
|
||||||
|
// root_directory_relative_to_global_root().
|
||||||
|
// This seems more useful.
|
||||||
|
res = &process.root_directory();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
return KResult(-ENOENT);
|
||||||
|
|
||||||
|
return *res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcFSProxyInode::ProcFSProxyInode(ProcFS& fs, FileDescription& fd)
|
||||||
|
: Inode(fs, 0)
|
||||||
|
, m_fd(fd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcFSProxyInode::~ProcFSProxyInode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
InodeMetadata ProcFSProxyInode::metadata() const
|
||||||
|
{
|
||||||
|
InodeMetadata metadata = m_fd->metadata();
|
||||||
|
|
||||||
|
if (m_fd->is_readable())
|
||||||
|
metadata.mode |= 0444;
|
||||||
|
else
|
||||||
|
metadata.mode &= ~0444;
|
||||||
|
|
||||||
|
if (m_fd->is_writable())
|
||||||
|
metadata.mode |= 0222;
|
||||||
|
else
|
||||||
|
metadata.mode &= ~0222;
|
||||||
|
|
||||||
|
if (!metadata.is_directory())
|
||||||
|
metadata.mode &= ~0111;
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
KResult ProcFSProxyInode::add_child(InodeIdentifier child_id, const StringView& name, mode_t mode)
|
||||||
|
{
|
||||||
|
if (!m_fd->inode())
|
||||||
|
return KResult(-EINVAL);
|
||||||
|
return m_fd->inode()->add_child(child_id, name, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
KResult ProcFSProxyInode::remove_child(const StringView& name)
|
||||||
|
{
|
||||||
|
if (!m_fd->inode())
|
||||||
|
return KResult(-EINVAL);
|
||||||
|
return m_fd->inode()->remove_child(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
InodeIdentifier ProcFSProxyInode::lookup(StringView name)
|
||||||
|
{
|
||||||
|
if (!m_fd->inode())
|
||||||
|
return {};
|
||||||
|
return m_fd->inode()->lookup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ProcFSProxyInode::directory_entry_count() const
|
||||||
|
{
|
||||||
|
if (!m_fd->inode())
|
||||||
|
return 0;
|
||||||
|
return m_fd->inode()->directory_entry_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
KResult ProcFSInode::add_child(InodeIdentifier child_id, const StringView& name, mode_t)
|
KResult ProcFSInode::add_child(InodeIdentifier child_id, const StringView& name, mode_t)
|
||||||
{
|
{
|
||||||
(void)child_id;
|
(void)child_id;
|
||||||
|
|
|
@ -81,8 +81,43 @@ private:
|
||||||
virtual size_t directory_entry_count() const override;
|
virtual size_t directory_entry_count() const override;
|
||||||
virtual KResult chmod(mode_t) override;
|
virtual KResult chmod(mode_t) override;
|
||||||
virtual KResult chown(uid_t, gid_t) override;
|
virtual KResult chown(uid_t, gid_t) override;
|
||||||
|
virtual KResultOr<NonnullRefPtr<Custody>> resolve_as_link(Custody& base, RefPtr<Custody>* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0) const override;
|
||||||
|
|
||||||
ProcFS& fs() { return static_cast<ProcFS&>(Inode::fs()); }
|
ProcFS& fs() { return static_cast<ProcFS&>(Inode::fs()); }
|
||||||
const ProcFS& fs() const { return static_cast<const ProcFS&>(Inode::fs()); }
|
const ProcFS& fs() const { return static_cast<const ProcFS&>(Inode::fs()); }
|
||||||
ProcFSInode(ProcFS&, unsigned index);
|
ProcFSInode(ProcFS&, unsigned index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ProcFSProxyInode final : public Inode {
|
||||||
|
friend class ProcFSInode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~ProcFSProxyInode() override;
|
||||||
|
|
||||||
|
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 InodeIdentifier 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(); }
|
||||||
|
virtual KResult add_child(InodeIdentifier child_id, const StringView& name, mode_t) override;
|
||||||
|
virtual KResult remove_child(const StringView& name) override;
|
||||||
|
virtual size_t directory_entry_count() const override;
|
||||||
|
virtual KResult chmod(mode_t) override { return KResult(-EINVAL); }
|
||||||
|
virtual KResult chown(uid_t, gid_t) override { return KResult(-EINVAL); }
|
||||||
|
virtual KResultOr<NonnullRefPtr<Custody>> resolve_as_link(Custody&, RefPtr<Custody>*, int, int) const override { ASSERT_NOT_REACHED(); }
|
||||||
|
virtual FileDescription* preopen_fd() override { return m_fd; }
|
||||||
|
|
||||||
|
ProcFS& fs() { return static_cast<ProcFS&>(Inode::fs()); }
|
||||||
|
const ProcFS& fs() const { return static_cast<const ProcFS&>(Inode::fs()); }
|
||||||
|
|
||||||
|
ProcFSProxyInode(ProcFS&, FileDescription&);
|
||||||
|
static NonnullRefPtr<ProcFSProxyInode> create(ProcFS& fs, FileDescription& fd)
|
||||||
|
{
|
||||||
|
return adopt(*new ProcFSProxyInode(fs, fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<FileDescription> m_fd;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue