aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <anthony.g.basile@gmail.com>2017-09-03 13:32:07 -0400
committerGitHub <noreply@github.com>2017-09-03 13:32:07 -0400
commit7fc1d0b190a8adf926df9c425d80f3a8b1f60c88 (patch)
tree1dd787f49c344a294ff882c0e9adb72b8b4dd5f7
parentrules: update (diff)
parent"always replace spaces in symlinks, unless string_escape=none" -- This fix is... (diff)
downloadeudev-7fc1d0b190a8adf926df9c425d80f3a8b1f60c88.tar.gz
eudev-7fc1d0b190a8adf926df9c425d80f3a8b1f60c88.tar.bz2
eudev-7fc1d0b190a8adf926df9c425d80f3a8b1f60c88.zip
Merge pull request #149 from msmith626/symlink_spaces_fix
always replace spaces in symlinks, unless string_escape=none
-rw-r--r--src/libudev/libudev-util.c2
-rw-r--r--src/udev/udev-event.c41
-rw-r--r--src/udev/udev-rules.c40
-rw-r--r--src/udev/udev.h4
-rw-r--r--src/udev/udevadm-test.c2
5 files changed, 61 insertions, 28 deletions
diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c
index e5d340eea..ce42ff425 100644
--- a/src/libudev/libudev-util.c
+++ b/src/libudev/libudev-util.c
@@ -241,7 +241,7 @@ int util_replace_whitespace(const char *str, char *to, size_t len)
to[j++] = str[i++];
}
to[j] = '\0';
- return 0;
+ return j;
}
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 897f98b32..d13ab8fdb 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -62,7 +62,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,
@@ -117,8 +119,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] == '$') {
@@ -187,6 +191,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));
@@ -367,6 +384,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:
@@ -1026,7 +1057,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
if (builtin_cmd < UDEV_BUILTIN_MAX) {
char command[UTIL_PATH_SIZE];
- udev_event_apply_format(event, cmd, command, sizeof(command));
+ udev_event_apply_format(event, cmd, command, sizeof(command), false);
udev_builtin_run(event->dev, builtin_cmd, command, false);
} else {
char program[UTIL_PATH_SIZE];
@@ -1037,7 +1068,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
sleep(event->exec_delay);
}
- udev_event_apply_format(event, cmd, program, sizeof(program));
+ udev_event_apply_format(event, cmd, program, sizeof(program), false);
envp = udev_device_get_properties_envp(event->dev);
udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, NULL, 0);
}
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index c4f422187..b29ac8ed8 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1849,7 +1849,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:
@@ -2006,7 +2006,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
char filename[UTIL_PATH_SIZE];
int found;
- 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);
found = (wait_for_file(event->dev, filename, 10) == 0);
if (!found && (cur->key.op != OP_NOMATCH))
goto nomatch;
@@ -2021,7 +2021,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;
@@ -2099,7 +2099,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];
@@ -2127,7 +2127,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);
envp = udev_device_get_properties_envp(event->dev);
log_debug("PROGRAM '%s' %s:%u",
program,
@@ -2155,7 +2155,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;
@@ -2164,7 +2164,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),
@@ -2195,7 +2195,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),
@@ -2265,7 +2265,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;
@@ -2303,7 +2303,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) {
@@ -2329,7 +2329,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) {
@@ -2353,7 +2353,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);
@@ -2438,10 +2438,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;
@@ -2450,7 +2450,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++) {
@@ -2478,7 +2478,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)
@@ -2515,7 +2515,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), esc != ESCAPE_NONE);
if (esc == ESCAPE_UNSET)
count = util_replace_chars(temp, "/ ");
else if (esc == ESCAPE_REPLACE)
@@ -2555,7 +2555,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);
@@ -2574,9 +2574,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 da5e6163d..9193ddbbf 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -81,7 +81,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 9a9bfa97c..47fd92474 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -153,7 +153,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: