blob: b049ad88fa0f7c9ff4d207bc8b62bcbe56bb80f9 [file] [log] [blame]
[BACKPORT] udev-event: add replace_whitespace param
Fixed 2 conflicts in src/udev/udev-rules.c.
From e20a917105b9c41e7e552ca5f11f9077897db505 Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@ieee.org>
Date: Tue, 3 Jan 2017 14:37:59 -0500
Subject: [PATCH] udev-event: add replace_whitespace param to
udev_event_apply_format
If replace_whitespace is true, each substitution value has all its
whitespace removed/replaced by util_replace_whitespace (except the
SUBST_RESULT substitution - $result{} or %c{} - which handles spaces
itself as field separators). All existing callers are updated to
pass false, so no functional change is made by this patch.
This is needed so the SYMLINK assignment can replace any spaces
introduced through variable substitution, becuase the SYMLINK value is
a space-separated list of symlinks to create. Any variables that
contain spaces will thus unexpectedly change the symlink value from
a single symlink to multiple incorrectly-named symlinks.
This is used in the next patch, which enables the whitespace
replacement for SYMLINK variable substitution.
---
src/udev/udev-event.c | 39 +++++++++++++++++++++++++++++++++++----
src/udev/udev-rules.c | 38 +++++++++++++++++++-------------------
src/udev/udev.h | 4 +++-
src/udev/udevadm-test.c | 2 +-
4 files changed, 58 insertions(+), 25 deletions(-)
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 4761222..acd5fe4 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -71,7 +71,9 @@ void udev_event_unref(struct udev_event *event) {
free(event);
}
-size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) {
+size_t udev_event_apply_format(struct udev_event *event,
+ const char *src, char *dest, size_t size,
+ bool replace_whitespace) {
struct udev_device *dev = event->dev;
enum subst_type {
SUBST_UNKNOWN,
@@ -128,8 +130,10 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
for (;;) {
enum subst_type type = SUBST_UNKNOWN;
- char attrbuf[UTIL_PATH_SIZE];
- char *attr = NULL;
+ char attrbuf[UTIL_PATH_SIZE], sbuf[UTIL_PATH_SIZE];
+ char *attr = NULL, *_s;
+ size_t _l;
+ bool replws = replace_whitespace;
while (from[0] != '\0') {
if (from[0] == '$') {
@@ -198,6 +202,19 @@ subst:
attr = NULL;
}
+ /* result subst handles space as field separator */
+ if (type == SUBST_RESULT)
+ replws = false;
+
+ if (replws) {
+ /* store dest string ptr and remaining len */
+ _s = s;
+ _l = l;
+ /* temporarily use sbuf */
+ s = &sbuf;
+ l = UTIL_PATH_SIZE;
+ }
+
switch (type) {
case SUBST_DEVPATH:
l = strpcpy(&s, l, udev_device_get_devpath(dev));
@@ -378,6 +395,20 @@ subst:
log_error("unknown substitution type=%i", type);
break;
}
+
+ /* replace whitespace in sbuf and copy to dest */
+ if (replws) {
+ size_t tmplen = UTIL_PATH_SIZE - l;
+
+ /* restore s and l to dest string values */
+ s = _s;
+ l = _l;
+
+ /* copy ws-replaced value to s */
+ tmplen = util_replace_whitespace(sbuf, s, MIN(tmplen, l));
+ l -= tmplen;
+ s += tmplen;
+ }
}
out:
@@ -941,7 +972,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
const char *cmd = udev_list_entry_get_name(list_entry);
enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry);
- udev_event_apply_format(event, cmd, command, sizeof(command));
+ udev_event_apply_format(event, cmd, command, sizeof(command), false);
if (builtin_cmd < UDEV_BUILTIN_MAX)
udev_builtin_run(event->dev, builtin_cmd, command, false);
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 43255fb..4ba8ab4 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1800,7 +1800,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct
name = rules_str(rules, cur->key.attr_off);
switch (cur->key.attrsubst) {
case SB_FORMAT:
- udev_event_apply_format(event, name, nbuf, sizeof(nbuf));
+ udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false);
name = nbuf;
/* fall through */
case SB_NONE:
@@ -1961,7 +1961,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
_cleanup_free_ char *value = NULL;
size_t len;
- udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
+ udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename), false);
sysctl_normalize(filename);
if (sysctl_read(filename, &value) < 0)
goto nomatch;
@@ -2039,7 +2039,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
struct stat statbuf;
int match;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename), false);
if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) {
if (filename[0] != '/') {
char tmp[UTIL_PATH_SIZE];
@@ -2066,7 +2066,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
free(event->program_result);
event->program_result = NULL;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program), false);
log_debug("PROGRAM '%s' %s:%u",
program,
rules_str(rules, rule->rule.filename_off),
@@ -2093,7 +2093,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
case TK_M_IMPORT_FILE: {
char import[UTIL_PATH_SIZE];
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
if (import_file_into_properties(event->dev, import) != 0)
if (cur->key.op != OP_NOMATCH)
goto nomatch;
@@ -2102,7 +2102,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
case TK_M_IMPORT_PROG: {
char import[UTIL_PATH_SIZE];
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
log_debug("IMPORT '%s' %s:%u",
import,
rules_str(rules, rule->rule.filename_off),
@@ -2133,7 +2133,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
event->builtin_run |= (1 << cur->key.builtin_cmd);
}
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command), false);
log_debug("IMPORT builtin '%s' %s:%u",
udev_builtin_name(cur->key.builtin_cmd),
rules_str(rules, rule->rule.filename_off),
@@ -2203,7 +2203,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
case TK_M_IMPORT_PARENT: {
char import[UTIL_PATH_SIZE];
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
if (import_parent_into_properties(event->dev, import) != 0)
if (cur->key.op != OP_NOMATCH)
goto nomatch;
@@ -2241,7 +2241,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
break;
if (cur->key.op == OP_ASSIGN_FINAL)
event->owner_final = true;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner), false);
event->owner_set = true;
r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL);
if (r < 0) {
@@ -2267,7 +2267,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
break;
if (cur->key.op == OP_ASSIGN_FINAL)
event->group_final = true;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group), false);
event->group_set = true;
r = get_group_creds(&gr, &event->gid);
if (r < 0) {
@@ -2291,7 +2291,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
if (event->mode_final)
break;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str), false);
mode = strtol(mode_str, &endptr, 8);
if (endptr[0] != '\0') {
log_error("ignoring invalid mode '%s'", mode_str);
@@ -2376,10 +2376,10 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
char temp[UTIL_NAME_SIZE];
/* append value separated by space */
- udev_event_apply_format(event, value, temp, sizeof(temp));
+ udev_event_apply_format(event, value, temp, sizeof(temp), false);
strscpyl(value_new, sizeof(value_new), value_old, " ", temp, NULL);
} else
- udev_event_apply_format(event, value, value_new, sizeof(value_new));
+ udev_event_apply_format(event, value, value_new, sizeof(value_new), false);
udev_device_add_property(event->dev, name, value_new);
break;
@@ -2388,7 +2388,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
char tag[UTIL_PATH_SIZE];
const char *p;
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag), false);
if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL)
udev_device_cleanup_tags_list(event->dev);
for (p = tag; *p != '\0'; p++) {
@@ -2416,7 +2416,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
break;
if (cur->key.op == OP_ASSIGN_FINAL)
event->name_final = true;
- udev_event_apply_format(event, name, name_str, sizeof(name_str));
+ udev_event_apply_format(event, name, name_str, sizeof(name_str), false);
if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) {
count = util_replace_chars(name_str, "/");
if (count > 0)
@@ -2452,7 +2452,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
udev_device_cleanup_devlinks_list(event->dev);
/* allow multiple symlinks separated by spaces */
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp), false);
if (esc == ESCAPE_UNSET)
count = util_replace_chars(temp, "/ ");
else if (esc == ESCAPE_REPLACE)
@@ -2492,7 +2492,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL);
attr_subst_subdir(attr, sizeof(attr));
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value), false);
log_debug("ATTR '%s' writing '%s' %s:%u", attr, value,
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
@@ -2511,9 +2511,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
char value[UTIL_NAME_SIZE];
int r;
- udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
+ udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename), false);
sysctl_normalize(filename);
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
+ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value), false);
log_debug("SYSCTL '%s' writing '%s' %s:%u", filename, value,
rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
r = sysctl_write(filename, value);
diff --git a/src/udev/udev.h b/src/udev/udev.h
index d17fc8c..6d6cf94 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -78,7 +78,9 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
/* udev-event.c */
struct udev_event *udev_event_new(struct udev_device *dev);
void udev_event_unref(struct udev_event *event);
-size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size);
+size_t udev_event_apply_format(struct udev_event *event,
+ const char *src, char *dest, size_t size,
+ bool replace_whitespace);
int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string,
char *result, size_t maxsize, int read_value);
int udev_event_spawn(struct udev_event *event,
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index d04e618..75821ce 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -143,7 +143,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) {
char program[UTIL_PATH_SIZE];
- udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program));
+ udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program), false);
printf("run: '%s'\n", program);
}
out: