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 struct Vfs::Zero_file_system : Single_file_system
{ {
Genode::size_t const _size;
Zero_file_system(Vfs::Env&, Genode::Xml_node config) Zero_file_system(Vfs::Env&, Genode::Xml_node config)
: :
Single_file_system(Node_type::CONTINUOUS_FILE, name(), 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"; } 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 struct Zero_vfs_handle : Single_vfs_handle
{ {
Genode::size_t const _size;
Zero_vfs_handle(Directory_service &ds, Zero_vfs_handle(Directory_service &ds,
File_io_service &fs, File_io_service &fs,
Genode::Allocator &alloc) Genode::Allocator &alloc,
: Single_vfs_handle(ds, fs, alloc, 0) { } Genode::size_t size)
:
Single_vfs_handle(ds, fs, alloc, 0),
_size(size)
{ }
Read_result read(char *dst, file_size count, Read_result read(char *dst, file_size count,
file_size &out_count) override 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); memset(dst, 0, count);
out_count = count; out_count = count;
@ -70,13 +96,24 @@ struct Vfs::Zero_file_system : Single_file_system
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
try { 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; return OPEN_OK;
} }
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } 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_ */ #endif /* _INCLUDE__VFS__ZERO_FILE_SYSTEM_H_ */