Kernel/SysFS: Provide a way to "truncate" and "set" mtime on inodes

Normally, trying to truncate a SysFSInode should result in EPERM error.
However, as suggested by Ali (@alimpfard), we can allow the PowerState
node to be "truncated" so one can open that file with O_TRUNC option.
Likewise, we also need to provide a way to set modified time on SysFS
inodes. For most inodes, we should return ENOTIMPL error, but for the
power state switch, we ignore the modified time setting and just return
KSuccess.

These fixes allow to do "echo -n 1 > /sys/firmware/power_state" in Shell
after gaining root permissions, to switch the power state.
This commit is contained in:
Liav A 2021-09-17 11:52:51 +03:00 committed by Andreas Kling
parent 7269ce15fc
commit f8489da8ee
5 changed files with 21 additions and 2 deletions

View file

@ -182,9 +182,14 @@ KResult SysFSInode::chown(UserID, GroupID)
return EPERM;
}
KResult SysFSInode::truncate(u64)
KResult SysFSInode::set_mtime(time_t time)
{
return EPERM;
return m_associated_component->set_mtime(time);
}
KResult SysFSInode::truncate(u64 size)
{
return m_associated_component->truncate(size);
}
KResultOr<NonnullRefPtr<SysFSDirectoryInode>> SysFSDirectoryInode::try_create(SysFS const& sysfs, SysFSComponent const& component)

View file

@ -146,6 +146,7 @@ protected:
virtual KResult chmod(mode_t) override;
virtual KResult chown(UserID, GroupID) override;
virtual KResult truncate(u64) override;
virtual KResult set_mtime(time_t);
virtual KResult attach(OpenFileDescription& description) override final;
virtual void did_seek(OpenFileDescription&, off_t) override final;

View file

@ -30,6 +30,8 @@ public:
virtual KResult traverse_as_directory(unsigned, Function<bool(FileSystem::DirectoryEntryView const&)>) const { VERIFY_NOT_REACHED(); }
virtual RefPtr<SysFSComponent> lookup(StringView) { VERIFY_NOT_REACHED(); };
virtual mode_t permissions() const;
virtual KResult truncate(u64) { return EPERM; }
virtual KResult set_mtime(time_t) { return ENOTIMPL; }
virtual KResultOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) { return EROFS; }
virtual KResult refresh_data(OpenFileDescription&) const { return KSuccess; }

View file

@ -30,6 +30,15 @@ UNMAP_AFTER_INIT PowerStateSwitchNode::PowerStateSwitchNode(FirmwareSysFSDirecto
{
}
KResult PowerStateSwitchNode::truncate(u64 size)
{
// Note: This node doesn't store any useful data anyway, so we can safely
// truncate this to zero (essentially ignoring the request without failing).
if (size != 0)
return EPERM;
return KSuccess;
}
KResultOr<size_t> PowerStateSwitchNode::write_bytes(off_t offset, size_t count, UserOrKernelBuffer const& data, OpenFileDescription*)
{
if (Checked<off_t>::addition_would_overflow(offset, count))

View file

@ -25,6 +25,8 @@ public:
static NonnullRefPtr<PowerStateSwitchNode> must_create(FirmwareSysFSDirectory&);
virtual mode_t permissions() const override;
virtual KResultOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) override;
virtual KResult truncate(u64) override;
virtual KResult set_mtime(time_t) { return KSuccess; }
private:
PowerStateSwitchNode(FirmwareSysFSDirectory&);