From e56dd15a4bf35a60593ae77392ab17d4eef687d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Thu, 18 Jun 2020 15:48:52 +0200 Subject: [PATCH] vfs: extend fs to limit amount of zeros Setting the 'size' attribute will restrict a reader to consume 0s up to the specified amount per VFS handle. The attribute is parsed as 'Number_of_bytes', which will limit the amount to the maximum of the addressable memory on the platform. This addition comes in handy when needing to provide a synthetic empty file with a fixed size. Issue #3781. --- repos/os/src/lib/vfs/zero_file_system.h | 45 ++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/repos/os/src/lib/vfs/zero_file_system.h b/repos/os/src/lib/vfs/zero_file_system.h index 0332512c5..372e3cc71 100644 --- a/repos/os/src/lib/vfs/zero_file_system.h +++ b/repos/os/src/lib/vfs/zero_file_system.h @@ -22,10 +22,14 @@ namespace Vfs { class Zero_file_system; } struct Vfs::Zero_file_system : Single_file_system { + Genode::size_t const _size; + Zero_file_system(Vfs::Env&, Genode::Xml_node config) : Single_file_system(Node_type::CONTINUOUS_FILE, name(), - Node_rwx::rw(), config) + Node_rwx::rw(), config), + _size(config.attribute_value("size", + Genode::Number_of_bytes(0))) { } static char const *name() { return "zero"; } @@ -33,14 +37,36 @@ struct Vfs::Zero_file_system : Single_file_system struct Zero_vfs_handle : Single_vfs_handle { + Genode::size_t const _size; + Zero_vfs_handle(Directory_service &ds, File_io_service &fs, - Genode::Allocator &alloc) - : Single_vfs_handle(ds, fs, alloc, 0) { } + Genode::Allocator &alloc, + Genode::size_t size) + : + Single_vfs_handle(ds, fs, alloc, 0), + _size(size) + { } Read_result read(char *dst, file_size count, file_size &out_count) override { + if (_size) { + + /* current read offset */ + file_size const read_offset = seek(); + + /* maximum read offset */ + file_size const end_offset = min(count + read_offset, _size); + + if (read_offset >= end_offset) { + out_count = 0; + return READ_OK; + } + + count = end_offset - read_offset; + } + memset(dst, 0, count); out_count = count; @@ -70,13 +96,24 @@ struct Vfs::Zero_file_system : Single_file_system return OPEN_ERR_UNACCESSIBLE; try { - *out_handle = new (alloc) Zero_vfs_handle(*this, *this, alloc); + *out_handle = new (alloc) Zero_vfs_handle(*this, *this, alloc, + _size); return OPEN_OK; } catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } } + Stat_result stat(char const *path, Stat &out) override + { + Stat_result const result = Single_file_system::stat(path, out); + + if (_size) { + out.size = _size; + } + + return result; + } }; #endif /* _INCLUDE__VFS__ZERO_FILE_SYSTEM_H_ */