On Thu, Jul 25, 2019 at 10:30:24AM -0400, 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 | 76 ++++++++++++++++++++++++++++++++++++++++ > src/util/vircommand.h | 5 +++ > 3 files changed, 82 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index cf80ea3e44..e6249caa80 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1725,6 +1725,7 @@ virCommandSetOutputFD; > virCommandSetPidFile; > virCommandSetPreExecHook; > virCommandSetSELinuxLabel; > +virCommandSetSendBuffer; > virCommandSetUID; > virCommandSetUmask; > virCommandSetWorkingDirectory; > diff --git a/src/util/vircommand.c b/src/util/vircommand.c > index e10ca3eb7c..5dee730826 100644 > --- a/src/util/vircommand.c > +++ b/src/util/vircommand.c > @@ -76,6 +76,16 @@ struct _virCommandFD { > unsigned int flags; > }; > > +typedef struct _virCommandSendBuffer virCommandSendBuffer; > +typedef virCommandSendBuffer *virCommandSendBufferPtr; > + > +struct _virCommandSendBuffer { > + int fd; > + unsigned char *buffer; > + size_t buflen; > + off_t offset; > +}; > + > struct _virCommand { > int has_error; /* ENOMEM on allocation failure, -1 for anything else. */ > > @@ -135,6 +145,9 @@ struct _virCommand { > char *appArmorProfile; > #endif > int mask; > + > + virCommandSendBufferPtr sendBuffers; > + size_t numSendBuffers; > }; > > /* See virCommandSetDryRun for description for this variable */ > @@ -1728,6 +1741,67 @@ virCommandSetWorkingDirectory(virCommandPtr cmd, const char *pwd) > } > > > +static int > +virCommandGetNumSendBuffers(virCommandPtr cmd) > +{ > + return cmd->numSendBuffers; > +} > + > + > +static void > +virCommandFreeSendBuffers(virCommandPtr cmd) > +{ > + size_t i; > + > + for (i = 0; i < virCommandGetNumSendBuffers(cmd); i++) { > + VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd); > + VIR_FREE(cmd->sendBuffers[i].buffer); > + } > + VIR_FREE(cmd->sendBuffers); > +} > + > + > +/** > + * 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. > + */ > +int > +virCommandSetSendBuffer(virCommandPtr cmd, > + int fd, > + unsigned char *buffer, size_t buflen) > +{ > + size_t i = virCommandGetNumSendBuffers(cmd); > + > + 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; > + } I hit a build failure on mingw with this change, because F_SETFL doesn't exist. None of the vircommand code actually runs on windows, so we just need to stub this method out to immediately return -1 with has_error set to ENOSUPP i guess. Thre's another usage of O_NONBLOCK with same problem. If you can fix this, I'm happy to push the series. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list