/* See virCommandSetDryRun for description for this variable */
static virBufferPtr dryRunBuffer;
+static virCommandDryRunCallback dryRunCallback;
+static void *dryRunOpaque;
+static int dryRunStatus;
/*
* virCommandFDIsSet:
size_t inoff = 0;
int ret = 0;
+ if (dryRunBuffer || dryRunCallback) {
+ VIR_DEBUG("Dry run requested, skipping I/O processing");
+ return 0;
+ }
+
/* With an input buffer, feed data to child
* via pipe */
if (cmd->inbuf)
}
str = virCommandToString(cmd);
- if (dryRunBuffer) {
+ if (dryRunBuffer || dryRunCallback) {
+ dryRunStatus = 0;
if (!str) {
/* error already reported by virCommandToString */
goto cleanup;
}
- VIR_DEBUG("Dry run requested, appending stringified "
- "command to dryRunBuffer=%p", dryRunBuffer);
- virBufferAdd(dryRunBuffer, str, -1);
- virBufferAddChar(dryRunBuffer, '\n');
+ if (dryRunBuffer) {
+ VIR_DEBUG("Dry run requested, appending stringified "
+ "command to dryRunBuffer=%p", dryRunBuffer);
+ virBufferAdd(dryRunBuffer, str, -1);
+ virBufferAddChar(dryRunBuffer, '\n');
+ }
+ if (dryRunCallback) {
+ dryRunCallback((const char *const*)cmd->args,
+ (const char *const*)cmd->env,
+ cmd->inbuf, cmd->outbuf, cmd->errbuf,
+ &dryRunStatus, dryRunOpaque);
+ }
ret = 0;
goto cleanup;
}
return -1;
}
- if (dryRunBuffer) {
- VIR_DEBUG("Dry run requested, claiming success");
+ if (dryRunBuffer || dryRunCallback) {
+ VIR_DEBUG("Dry run requested, returning status %d",
+ dryRunStatus);
if (exitstatus)
- *exitstatus = 0;
+ *exitstatus = dryRunStatus;
return 0;
}
/**
* virCommandSetDryRun:
* @buf: buffer to store stringified commands
+ * @callback: callback to process input/output/args
*
* Sometimes it's desired to not actually run given command, but
* see its string representation without having to change the
* virCommandRun* API. The virCommandSetDryRun allows you to
* modify this behavior: once called, every call to
* virCommandRun* results in command string representation being
- * appended to @buf instead of being executed. the strings are
- * escaped for a shell and separated by a newline. For example:
+ * appended to @buf instead of being executed. If @callback is
+ * provided, then it is invoked with the argv, env and stdin
+ * data string for the command. It is expected to fill the stdout
+ * and stderr data strings and exit status variables.
+ *
+ * The strings stored in @buf are escaped for a shell and
+ * separated by a newline. For example:
*
* virBuffer buffer = VIR_BUFFER_INITIALIZER;
* virCommandSetDryRun(&buffer);
*
* /bin/echo 'Hello world'\n
*
- * To cancel this effect pass NULL.
+ * To cancel this effect pass NULL for @buf and @callback.
*/
void
-virCommandSetDryRun(virBufferPtr buf)
+virCommandSetDryRun(virBufferPtr buf,
+ virCommandDryRunCallback cb,
+ void *opaque)
{
dryRunBuffer = buf;
+ dryRunCallback = cb;
+ dryRunOpaque = opaque;
}
bool useBlacklist = info->useBlacklist;
virBuffer buf = VIR_BUFFER_INITIALIZER;
- virCommandSetDryRun(&buf);
+ virCommandSetDryRun(&buf, NULL, NULL);
errbuf = virKModLoad(module, useBlacklist);
if (errbuf) {
ret = 0;
cleanup:
- virCommandSetDryRun(NULL);
+ virCommandSetDryRun(NULL, NULL, NULL);
VIR_FREE(errbuf);
return ret;
}
const char *module = info->module;
virBuffer buf = VIR_BUFFER_INITIALIZER;
- virCommandSetDryRun(&buf);
+ virCommandSetDryRun(&buf, NULL, NULL);
errbuf = virKModUnload(module);
if (errbuf) {
ret = 0;
cleanup:
- virCommandSetDryRun(NULL);
+ virCommandSetDryRun(NULL, NULL, NULL);
VIR_FREE(errbuf);
return ret;
}