1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-29 21:55:36 +03:00

udev: make parser for attribute of $result harder

This commit is contained in:
Yu Watanabe 2019-04-30 20:30:49 +02:00
parent 13cd553f91
commit ce4f94b8e9

View File

@ -20,6 +20,7 @@
#include "format-util.h" #include "format-util.h"
#include "libudev-util.h" #include "libudev-util.h"
#include "netlink-util.h" #include "netlink-util.h"
#include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
@ -204,6 +205,26 @@ static int get_subst_type(const char **str, FormatSubstitutionType *ret_type, ch
return 1; return 1;
} }
static int safe_atou_optional_plus(const char *s, unsigned *ret) {
const char *p;
int r;
assert(s);
assert(ret);
/* Returns 1 if plus, 0 if no plus, negative on error */
p = endswith(s, "+");
if (p)
s = strndupa(s, p - s);
r = safe_atou(s, ret);
if (r < 0)
return r;
return !!p;
}
static ssize_t udev_event_subst_format( static ssize_t udev_event_subst_format(
UdevEvent *event, UdevEvent *event,
FormatSubstitutionType type, FormatSubstitutionType type,
@ -267,43 +288,50 @@ static ssize_t udev_event_subst_format(
break; break;
} }
case FORMAT_SUBST_RESULT: { case FORMAT_SUBST_RESULT: {
char *rest; unsigned index = 0; /* 0 means whole string */
int i; bool has_plus;
if (!event->program_result) if (!event->program_result)
goto null_terminate; goto null_terminate;
/* get part of the result string */ if (!isempty(attr)) {
i = 0; r = safe_atou_optional_plus(attr, &index);
if (!isempty(attr)) if (r < 0)
i = strtoul(attr, &rest, 10); return r;
if (i > 0) {
char result[UTIL_PATH_SIZE], tmp[UTIL_PATH_SIZE], *cpos;
strscpy(result, sizeof(result), event->program_result); has_plus = r;
cpos = result;
while (--i) {
while (cpos[0] != '\0' && !isspace(cpos[0]))
cpos++;
while (isspace(cpos[0]))
cpos++;
if (cpos[0] == '\0')
break;
} }
if (i > 0) {
log_error("requested part of result string not found"); if (index == 0)
break;
}
strscpy(tmp, sizeof(tmp), cpos);
/* %{2+}c copies the whole string from the second part on */
if (rest[0] != '+') {
cpos = strchr(tmp, ' ');
if (cpos)
cpos[0] = '\0';
}
l = strpcpy(&s, l, tmp);
} else
l = strpcpy(&s, l, event->program_result); l = strpcpy(&s, l, event->program_result);
else {
const char *start, *p;
unsigned i;
p = skip_leading_chars(event->program_result, NULL);
for (i = 1; i < index; i++) {
while (p[0] != '\0' && !strchr(WHITESPACE, p[0]))
p++;
p = skip_leading_chars(p, NULL);
if (*p == '\0')
break;
}
if (i != index) {
log_device_debug(dev, "requested part of result string not found");
goto null_terminate;
}
start = p;
/* %c{2+} copies the whole string from the second part on */
if (has_plus)
l = strpcpy(&s, l, start);
else {
while (p[0] != '\0' && !strchr(WHITESPACE, p[0]))
p++;
l = strnpcpy(&s, l, start, p - start);
}
}
break; break;
} }
case FORMAT_SUBST_ATTR: { case FORMAT_SUBST_ATTR: {