|
@@ -91,20 +91,48 @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
|
|
const struct iovec *iov,
|
|
const struct iovec *iov,
|
|
size_t niov,
|
|
size_t niov,
|
|
Error **errp)
|
|
Error **errp)
|
|
|
|
+{
|
|
|
|
+ return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, errp);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int qio_channel_readv_all(QIOChannel *ioc,
|
|
|
|
+ const struct iovec *iov,
|
|
|
|
+ size_t niov,
|
|
|
|
+ Error **errp)
|
|
|
|
+{
|
|
|
|
+ return qio_channel_readv_full_all(ioc, iov, niov, NULL, NULL, errp);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int qio_channel_readv_full_all_eof(QIOChannel *ioc,
|
|
|
|
+ const struct iovec *iov,
|
|
|
|
+ size_t niov,
|
|
|
|
+ int **fds, size_t *nfds,
|
|
|
|
+ Error **errp)
|
|
{
|
|
{
|
|
int ret = -1;
|
|
int ret = -1;
|
|
struct iovec *local_iov = g_new(struct iovec, niov);
|
|
struct iovec *local_iov = g_new(struct iovec, niov);
|
|
struct iovec *local_iov_head = local_iov;
|
|
struct iovec *local_iov_head = local_iov;
|
|
unsigned int nlocal_iov = niov;
|
|
unsigned int nlocal_iov = niov;
|
|
|
|
+ int **local_fds = fds;
|
|
|
|
+ size_t *local_nfds = nfds;
|
|
bool partial = false;
|
|
bool partial = false;
|
|
|
|
|
|
|
|
+ if (nfds) {
|
|
|
|
+ *nfds = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (fds) {
|
|
|
|
+ *fds = NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
nlocal_iov = iov_copy(local_iov, nlocal_iov,
|
|
nlocal_iov = iov_copy(local_iov, nlocal_iov,
|
|
iov, niov,
|
|
iov, niov,
|
|
0, iov_size(iov, niov));
|
|
0, iov_size(iov, niov));
|
|
|
|
|
|
- while (nlocal_iov > 0) {
|
|
|
|
|
|
+ while ((nlocal_iov > 0) || local_fds) {
|
|
ssize_t len;
|
|
ssize_t len;
|
|
- len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
|
|
|
|
|
|
+ len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds,
|
|
|
|
+ local_nfds, errp);
|
|
if (len == QIO_CHANNEL_ERR_BLOCK) {
|
|
if (len == QIO_CHANNEL_ERR_BLOCK) {
|
|
if (qemu_in_coroutine()) {
|
|
if (qemu_in_coroutine()) {
|
|
qio_channel_yield(ioc, G_IO_IN);
|
|
qio_channel_yield(ioc, G_IO_IN);
|
|
@@ -112,20 +140,50 @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
|
|
qio_channel_wait(ioc, G_IO_IN);
|
|
qio_channel_wait(ioc, G_IO_IN);
|
|
}
|
|
}
|
|
continue;
|
|
continue;
|
|
- } else if (len < 0) {
|
|
|
|
- goto cleanup;
|
|
|
|
- } else if (len == 0) {
|
|
|
|
- if (partial) {
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Unexpected end-of-file before all bytes were read");
|
|
|
|
- } else {
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (len == 0) {
|
|
|
|
+ if (local_nfds && *local_nfds) {
|
|
|
|
+ /*
|
|
|
|
+ * Got some FDs, but no data yet. This isn't an EOF
|
|
|
|
+ * scenario (yet), so carry on to try to read data
|
|
|
|
+ * on next loop iteration
|
|
|
|
+ */
|
|
|
|
+ goto next_iter;
|
|
|
|
+ } else if (!partial) {
|
|
|
|
+ /* No fds and no data - EOF before any data read */
|
|
ret = 0;
|
|
ret = 0;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ } else {
|
|
|
|
+ len = -1;
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "Unexpected end-of-file before all data were read");
|
|
|
|
+ /* Fallthrough into len < 0 handling */
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (len < 0) {
|
|
|
|
+ /* Close any FDs we previously received */
|
|
|
|
+ if (nfds && fds) {
|
|
|
|
+ size_t i;
|
|
|
|
+ for (i = 0; i < (*nfds); i++) {
|
|
|
|
+ close((*fds)[i]);
|
|
|
|
+ }
|
|
|
|
+ g_free(*fds);
|
|
|
|
+ *fds = NULL;
|
|
|
|
+ *nfds = 0;
|
|
}
|
|
}
|
|
goto cleanup;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (nlocal_iov) {
|
|
|
|
+ iov_discard_front(&local_iov, &nlocal_iov, len);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+next_iter:
|
|
partial = true;
|
|
partial = true;
|
|
- iov_discard_front(&local_iov, &nlocal_iov, len);
|
|
|
|
|
|
+ local_fds = NULL;
|
|
|
|
+ local_nfds = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
ret = 1;
|
|
ret = 1;
|
|
@@ -135,20 +193,23 @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-int qio_channel_readv_all(QIOChannel *ioc,
|
|
|
|
- const struct iovec *iov,
|
|
|
|
- size_t niov,
|
|
|
|
- Error **errp)
|
|
|
|
|
|
+int qio_channel_readv_full_all(QIOChannel *ioc,
|
|
|
|
+ const struct iovec *iov,
|
|
|
|
+ size_t niov,
|
|
|
|
+ int **fds, size_t *nfds,
|
|
|
|
+ Error **errp)
|
|
{
|
|
{
|
|
- int ret = qio_channel_readv_all_eof(ioc, iov, niov, errp);
|
|
|
|
|
|
+ int ret = qio_channel_readv_full_all_eof(ioc, iov, niov, fds, nfds, errp);
|
|
|
|
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|
|
- ret = -1;
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Unexpected end-of-file before all bytes were read");
|
|
|
|
- } else if (ret == 1) {
|
|
|
|
- ret = 0;
|
|
|
|
|
|
+ error_prepend(errp,
|
|
|
|
+ "Unexpected end-of-file before all data were read.");
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
|
|
+ if (ret == 1) {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|