mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 11:55:24 +00:00
vfs_import: implement write loop for copy_file
This is required to allow import of large file. Fixes #3655
This commit is contained in:
parent
46fa8197a2
commit
9da428dccf
@ -119,6 +119,7 @@ class Vfs_import::File_system : public Vfs::File_system
|
||||
bool overwrite)
|
||||
{
|
||||
using Genode::Readonly_file;
|
||||
using Genode::size_t;
|
||||
|
||||
Readonly_file src_file(src, path);
|
||||
Vfs_handle *dst_handle = nullptr;
|
||||
@ -139,34 +140,55 @@ class Vfs_import::File_system : public Vfs::File_system
|
||||
return;
|
||||
}
|
||||
|
||||
Vfs_handle::Guard guard(dst_handle);
|
||||
char buf[4096];
|
||||
Vfs_handle::Guard guard { dst_handle };
|
||||
Flush_guard flush { env, *dst_handle };
|
||||
Readonly_file::At at { };
|
||||
|
||||
{
|
||||
char buf[4096];
|
||||
Flush_guard flush(env, *dst_handle);
|
||||
while (true) {
|
||||
|
||||
Readonly_file::At at { };
|
||||
file_size bytes_from_source { src_file.read(at, buf, sizeof(buf)) };
|
||||
|
||||
while (true) {
|
||||
file_size wn = 0;
|
||||
file_size rn = src_file.read(at, buf, sizeof(buf));
|
||||
if (!rn) break;
|
||||
if (!bytes_from_source) break;
|
||||
|
||||
auto wres = dst_handle->fs().write(dst_handle, buf, rn, wn);
|
||||
switch (wres) {
|
||||
case WRITE_OK:
|
||||
case WRITE_ERR_AGAIN:
|
||||
case WRITE_ERR_WOULD_BLOCK:
|
||||
break;
|
||||
default:
|
||||
Genode::error("failed to write to ", path, ", ", wres);
|
||||
env.root_dir().unlink(path.string());
|
||||
return;
|
||||
}
|
||||
bool stalled { false };
|
||||
bool write_error { false };
|
||||
Vfs::file_size remaining_bytes { bytes_from_source };
|
||||
char const *src { buf };
|
||||
|
||||
dst_handle->advance_seek(wn);
|
||||
at.value += wn;
|
||||
while (remaining_bytes > 0 && !write_error) {
|
||||
|
||||
try {
|
||||
Vfs::file_size out_count { 0 };
|
||||
switch (dst_handle->fs().write(dst_handle, src,
|
||||
remaining_bytes,
|
||||
out_count)) {
|
||||
case WRITE_ERR_AGAIN:
|
||||
case WRITE_ERR_WOULD_BLOCK:
|
||||
stalled = true;
|
||||
break;
|
||||
case Write_result::WRITE_ERR_INVALID:
|
||||
case Write_result::WRITE_ERR_IO:
|
||||
case Write_result::WRITE_ERR_INTERRUPT:
|
||||
env.root_dir().unlink(path.string());
|
||||
write_error = true;
|
||||
break;
|
||||
case WRITE_OK:
|
||||
out_count = min(remaining_bytes, out_count);
|
||||
remaining_bytes -= out_count;
|
||||
src += out_count;
|
||||
at.value += out_count;
|
||||
dst_handle->advance_seek(out_count);
|
||||
break;
|
||||
}
|
||||
} catch (Vfs::File_io_service::Insufficient_buffer) {
|
||||
stalled = true; }
|
||||
|
||||
if (stalled)
|
||||
env.env().ep().wait_and_dispatch_one_io_signal();
|
||||
}
|
||||
if (write_error)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user