On 7/25/19 2:22 PM, Stefan Berger wrote: > Implement virCommandSetSendBuffer() that allows the caller to pass a > file descriptor and buffer to virCommand. virCommand will write the > buffer into the file descriptor. That file descriptor could be the > write end of a pipe or one of the file descriptors of a socketpair. > The other file descriptor should be passed to the launched process to > read the data from. > > Only implement the function to allocate memory for send buffers > and to free them later on. > > Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> > Reviewed-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> > --- > src/libvirt_private.syms | 1 + > src/util/vircommand.c | 93 ++++++++++++++++++++++++++++++++++++++++ > src/util/vircommand.h | 5 +++ > 3 files changed, 99 insertions(+) > [...] > +/** > + * virCommandSetSendBuffer > + * @cmd: the command to modify > + * > + * Pass a buffer to virCommand that will be written into the > + * given file descriptor. The buffer will be freed automatically > + * and the file descriptor closed. > + */ > +#if defined(F_SETFL) > +int > +virCommandSetSendBuffer(virCommandPtr cmd, > + int fd, > + unsigned char *buffer, size_t buflen) > +{ > + size_t i = virCommandGetNumSendBuffers(cmd); This call would deref @cmd before the following check for !cmd [1] Was found by Coverity, but see below > + > + if (!cmd || cmd->has_error) > + return -1; > + > + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { > + virReportSystemError(errno, "%s", > + _("fcntl failed to set O_NONBLOCK")); > + cmd->has_error = errno; > + return -1; > + } > + > + if (VIR_REALLOC_N(cmd->sendBuffers, i + 1) < 0) { > + cmd->has_error = ENOMEM; > + return -1; > + } > + > + cmd->sendBuffers[i].fd = fd; > + cmd->sendBuffers[i].buffer = buffer; > + cmd->sendBuffers[i].buflen = buflen; > + cmd->sendBuffers[i].offset = 0; > + > + cmd->numSendBuffers++; > + > + return 0; > +} > + > +#else /* !defined(F_SETFL) */ > + > +int > +virCommandSetSendBuffer(virCommandPtr cmd, > + int fd, > + unsigned char *buffer, size_t buflen) > +{ > + if (!cmd || cmd->has_error) > + return -1; > + > + cmd->has_error = ENOTSUP; > + > + return -1; > +} > + > +#endif > + > /** > * virCommandSetInputBuffer: > * @cmd: the command to modify > @@ -2867,6 +2958,8 @@ virCommandFree(virCommandPtr cmd) > VIR_FREE(cmd->appArmorProfile); > #endif > > + virCommandFreeSendBuffers(cmd); > + > VIR_FREE(cmd); > } > > diff --git a/src/util/vircommand.h b/src/util/vircommand.h > index 2a9ee5cdc7..c2abc7b2c3 100644 > --- a/src/util/vircommand.h > +++ b/src/util/vircommand.h > @@ -146,6 +146,11 @@ void virCommandAddArgList(virCommandPtr cmd, > void virCommandSetWorkingDirectory(virCommandPtr cmd, > const char *pwd) ATTRIBUTE_NONNULL(2); > > +int virCommandSetSendBuffer(virCommandPtr cmd, > + int fd, > + unsigned char *buffer, size_t buflen) > + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3); The ATTRIBUTE_NONNULL(1) causes a Coverity build error when the function checks !cmd - so either this is removed or the function doesn't check for !cmd... If going with the latter, then both halves of the "#if defined(F_SETFL)" would need to be changed. John > + > void virCommandSetInputBuffer(virCommandPtr cmd, > const char *inbuf) ATTRIBUTE_NONNULL(2); > > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list