virlog: Introduce virLogParseOutputs

Another abstraction added on the top of parsing a single logging output. This
method takes and parses the whole set of outputs, adding each single output
that has already been parsed into a caller-provided array. If the user-supplied
string contained duplicate outputs, only the last occurrence is taken into
account (all the others are removed from the list), so we silently avoid
duplicate logs.

Signed-off-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Erik Skultety 2016-10-05 16:29:15 +02:00
parent 77a45f2ff0
commit 4b266c180b
3 changed files with 63 additions and 0 deletions

View File

@ -1892,6 +1892,7 @@ virLogParseAndDefineOutputs;
virLogParseDefaultPriority;
virLogParseFilter;
virLogParseOutput;
virLogParseOutputs;
virLogPriorityFromSyslog;
virLogProbablyLogMessage;
virLogReset;

View File

@ -2039,3 +2039,63 @@ virLogParseFilter(const char *src)
virStringFreeList(tokens);
return ret;
}
/**
* virLogParseOutputs:
* @src: string defining a (set of) output(s)
* @outputs: user-supplied list where parsed outputs from @src shall be stored
*
* Parses a (set of) output(s) into a list of logging objects. Multiple outputs
* can be defined within @src string, they just need to be separated by spaces.
* If running in setuid mode, then only the 'stderr' output will be allowed.
*
* Returns the number of outputs parsed or -1 in case of error.
*/
int
virLogParseOutputs(const char *src, virLogOutputPtr **outputs)
{
int ret = -1;
int at = -1;
size_t noutputs = 0;
size_t i, count;
char **strings = NULL;
virLogOutputPtr output = NULL;
virLogOutputPtr *list = NULL;
VIR_DEBUG("outputs=%s", src);
if (!(strings = virStringSplitCount(src, " ", 0, &count)))
goto cleanup;
for (i = 0; i < count; i++) {
/* virStringSplit may return empty strings */
if (STREQ(strings[i], ""))
continue;
if (!(output = virLogParseOutput(strings[i])))
goto cleanup;
/* let's check if a duplicate output does not already exist in which
* case we need to replace it with its last occurrence, however, rather
* than first deleting the duplicate and then adding the new one, the
* new output object is added first so in case of an error we don't
* lose the old entry
*/
at = virLogFindOutput(list, noutputs, output->dest, output->name);
if (VIR_APPEND_ELEMENT(list, noutputs, output) < 0) {
virLogOutputFree(output);
goto cleanup;
}
if (at >= 0) {
virLogOutputFree(list[at]);
VIR_DELETE_ELEMENT(list, at, noutputs);
}
}
ret = noutputs;
*outputs = list;
list = NULL;
cleanup:
virStringFreeList(strings);
return ret;
}

View File

@ -242,5 +242,7 @@ int virLogDefineOutputs(virLogOutputPtr *outputs,
int virLogDefineFilters(virLogFilterPtr *filters, size_t nfilters);
virLogOutputPtr virLogParseOutput(const char *src) ATTRIBUTE_NONNULL(1);
virLogFilterPtr virLogParseFilter(const char *src) ATTRIBUTE_NONNULL(1);
int virLogParseOutputs(const char *src,
virLogOutputPtr **outputs) ATTRIBUTE_NONNULL(1);
#endif