noux: handle short writes in the libc plugin

Fixes #2661
This commit is contained in:
Christian Prochaska 2018-01-30 17:26:37 +01:00 committed by Norman Feske
parent 2ee15cc2e0
commit 50966583f6
6 changed files with 23 additions and 50 deletions

View File

@ -1263,8 +1263,8 @@ namespace {
}
}
count -= curr_count;
src += curr_count;
count -= sysio()->write_out.count;
src += sysio()->write_out.count;
}
return orig_count;
}

View File

@ -72,14 +72,14 @@ class Noux::Io_channel : public Reference_counter
virtual Io_channel_backend *backend() { return nullptr; }
virtual bool write(Sysio &sysio, size_t &offset) { return false; }
virtual bool read(Sysio &sysio) { return false; }
virtual bool fstat(Sysio &sysio) { return false; }
virtual bool ftruncate(Sysio &sysio) { return false; }
virtual bool fcntl(Sysio &sysio) { return false; }
virtual bool dirent(Sysio &sysio) { return false; }
virtual bool ioctl(Sysio &sysio) { return false; }
virtual bool lseek(Sysio &sysio) { return false; }
virtual bool write(Sysio &sysio) { return false; }
virtual bool read(Sysio &sysio) { return false; }
virtual bool fstat(Sysio &sysio) { return false; }
virtual bool ftruncate(Sysio &sysio) { return false; }
virtual bool fcntl(Sysio &sysio) { return false; }
virtual bool dirent(Sysio &sysio) { return false; }
virtual bool ioctl(Sysio &sysio) { return false; }
virtual bool lseek(Sysio &sysio) { return false; }
/**
* Return true if an unblocking condition of the channel is satisfied

View File

@ -242,21 +242,10 @@ class Noux::Pipe_sink_io_channel : public Io_channel
return wr && _pipe->any_space_avail_for_writing();
}
bool write(Sysio &sysio, size_t &offset) override
bool write(Sysio &sysio) override
{
/*
* If the write operation is larger than the space available in
* the pipe buffer, the write function is successively called
* for different portions of original write request. The
* current read pointer of the request is tracked via the
* 'count' in/out argument. If completed, 'count' equals
* 'write_in.count'.
*/
/* dimension the pipe write operation to the not yet written data */
size_t curr_count = _pipe->write(sysio.write_in.chunk + offset,
sysio.write_in.count - offset);
offset += curr_count;
sysio.write_out.count = _pipe->write(sysio.write_in.chunk,
sysio.write_in.count);
return true;
}

View File

@ -50,31 +50,17 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
case SYSCALL_WRITE:
{
size_t const count_in = _sysio.write_in.count;
Shared_pointer<Io_channel> io = _lookup_channel(_sysio.write_in.fd);
for (size_t offset = 0; offset != count_in; ) {
if (!io->nonblocking())
_block_for_io_channel(io, false, true, false);
Shared_pointer<Io_channel> io = _lookup_channel(_sysio.write_in.fd);
if (io->check_unblock(false, true, false)) {
/* 'io->write' is expected to update '_sysio.write_out.count' */
result = io->write(_sysio);
} else
_sysio.error.write = Vfs::File_io_service::WRITE_ERR_INTERRUPT;
if (!io->nonblocking())
_block_for_io_channel(io, false, true, false);
if (io->check_unblock(false, true, false)) {
/*
* 'io->write' is expected to update
* '_sysio.write_out.count' and 'offset'
*/
result = io->write(_sysio, offset);
if (result == false)
break;
} else {
if (result == false) {
/* nothing was written yet */
_sysio.error.write = Vfs::File_io_service::WRITE_ERR_INTERRUPT;
}
break;
}
}
break;
}

View File

@ -66,7 +66,7 @@ struct Noux::Terminal_io_channel : Io_channel
}
}
bool write(Sysio &sysio, size_t &offset) override
bool write(Sysio &sysio) override
{
size_t const count = min(sysio.write_in.count,
sizeof(sysio.write_in.chunk));
@ -74,7 +74,6 @@ struct Noux::Terminal_io_channel : Io_channel
_terminal.write(sysio.write_in.chunk, count);
sysio.write_out.count = count;
offset = count;
return true;
}

View File

@ -93,7 +93,7 @@ struct Noux::Vfs_io_channel : Io_channel
_fh->ds().close(_fh);
}
bool write(Sysio &sysio, size_t &offset) override
bool write(Sysio &sysio) override
{
Vfs::file_size count = sysio.write_in.count;
Vfs::file_size out_count = 0;
@ -117,7 +117,6 @@ struct Noux::Vfs_io_channel : Io_channel
_fh->advance_seek(out_count);
sysio.write_out.count = out_count;
offset = out_count;
return true;
}