vfs: extend <zero> 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.
This commit is contained in:
Josef Söntgen 2020-06-18 15:48:52 +02:00 committed by Norman Feske
parent 103ae9df4a
commit e56dd15a4b

View File

@ -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_ */