mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 11:31:16 +00:00
utils: Implement function to pass a buffer to send via a fd to virCommand
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@linux.ibm.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
1f46dd4cba
commit
149eda402f
@ -1725,6 +1725,7 @@ virCommandSetOutputFD;
|
|||||||
virCommandSetPidFile;
|
virCommandSetPidFile;
|
||||||
virCommandSetPreExecHook;
|
virCommandSetPreExecHook;
|
||||||
virCommandSetSELinuxLabel;
|
virCommandSetSELinuxLabel;
|
||||||
|
virCommandSetSendBuffer;
|
||||||
virCommandSetUID;
|
virCommandSetUID;
|
||||||
virCommandSetUmask;
|
virCommandSetUmask;
|
||||||
virCommandSetWorkingDirectory;
|
virCommandSetWorkingDirectory;
|
||||||
|
@ -76,6 +76,16 @@ struct _virCommandFD {
|
|||||||
unsigned int flags;
|
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 {
|
struct _virCommand {
|
||||||
int has_error; /* ENOMEM on allocation failure, -1 for anything else. */
|
int has_error; /* ENOMEM on allocation failure, -1 for anything else. */
|
||||||
|
|
||||||
@ -135,6 +145,9 @@ struct _virCommand {
|
|||||||
char *appArmorProfile;
|
char *appArmorProfile;
|
||||||
#endif
|
#endif
|
||||||
int mask;
|
int mask;
|
||||||
|
|
||||||
|
virCommandSendBufferPtr sendBuffers;
|
||||||
|
size_t numSendBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* See virCommandSetDryRun for description for this variable */
|
/* See virCommandSetDryRun for description for this variable */
|
||||||
@ -1728,6 +1741,85 @@ 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.
|
||||||
|
*/
|
||||||
|
#if defined(F_SETFL)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ATTRIBUTE_UNUSED,
|
||||||
|
unsigned char *buffer ATTRIBUTE_UNUSED,
|
||||||
|
size_t buflen ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
if (!cmd || cmd->has_error)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cmd->has_error = ENOTSUP;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virCommandSetInputBuffer:
|
* virCommandSetInputBuffer:
|
||||||
* @cmd: the command to modify
|
* @cmd: the command to modify
|
||||||
@ -2867,6 +2959,8 @@ virCommandFree(virCommandPtr cmd)
|
|||||||
VIR_FREE(cmd->appArmorProfile);
|
VIR_FREE(cmd->appArmorProfile);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virCommandFreeSendBuffers(cmd);
|
||||||
|
|
||||||
VIR_FREE(cmd);
|
VIR_FREE(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +146,11 @@ void virCommandAddArgList(virCommandPtr cmd,
|
|||||||
void virCommandSetWorkingDirectory(virCommandPtr cmd,
|
void virCommandSetWorkingDirectory(virCommandPtr cmd,
|
||||||
const char *pwd) ATTRIBUTE_NONNULL(2);
|
const char *pwd) ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
|
int virCommandSetSendBuffer(virCommandPtr cmd,
|
||||||
|
int fd,
|
||||||
|
unsigned char *buffer, size_t buflen)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
|
||||||
|
|
||||||
void virCommandSetInputBuffer(virCommandPtr cmd,
|
void virCommandSetInputBuffer(virCommandPtr cmd,
|
||||||
const char *inbuf) ATTRIBUTE_NONNULL(2);
|
const char *inbuf) ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user