diff options
author | Dan Streetman <ddstreet@ieee.org> | 2017-01-25 20:06:54 -0500 |
---|---|---|
committer | Dan Streetman <ddstreet@ieee.org> | 2017-01-27 07:58:00 -0500 |
commit | 0d53705b65b496f979a816a15181c5b1cda7a90f (patch) | |
tree | ba489dcc208a5d50b96cecaa6bc96332a9823c7d /src/udev | |
parent | 644317741a1e19331d779bdccb3dae0c7f812607 (diff) |
udev-event: refactor udev_event_apply_format
Move the large case statement into its own function
Diffstat (limited to 'src/udev')
-rw-r--r-- | src/udev/udev-event.c | 411 |
1 files changed, 212 insertions, 199 deletions
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index deffefd60b..3cb2673291 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -73,29 +73,221 @@ void udev_event_unref(struct udev_event *event) { free(event); } +enum subst_type { + SUBST_UNKNOWN, + SUBST_DEVNODE, + SUBST_ATTR, + SUBST_ENV, + SUBST_KERNEL, + SUBST_KERNEL_NUMBER, + SUBST_DRIVER, + SUBST_DEVPATH, + SUBST_ID, + SUBST_MAJOR, + SUBST_MINOR, + SUBST_RESULT, + SUBST_PARENT, + SUBST_NAME, + SUBST_LINKS, + SUBST_ROOT, + SUBST_SYS, +}; + +static size_t subst_format_var(struct udev_event *event, struct udev_device *dev, + enum subst_type type, char *attr, + char **dest, size_t l) { + char *s = *dest; + + switch (type) { + case SUBST_DEVPATH: + l = strpcpy(&s, l, udev_device_get_devpath(dev)); + break; + case SUBST_KERNEL: + l = strpcpy(&s, l, udev_device_get_sysname(dev)); + break; + case SUBST_KERNEL_NUMBER: + if (udev_device_get_sysnum(dev) == NULL) + break; + l = strpcpy(&s, l, udev_device_get_sysnum(dev)); + break; + case SUBST_ID: + if (event->dev_parent == NULL) + break; + l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent)); + break; + case SUBST_DRIVER: { + const char *driver; + + if (event->dev_parent == NULL) + break; + + driver = udev_device_get_driver(event->dev_parent); + if (driver == NULL) + break; + l = strpcpy(&s, l, driver); + break; + } + case SUBST_MAJOR: { + char num[UTIL_PATH_SIZE]; + + sprintf(num, "%u", major(udev_device_get_devnum(dev))); + l = strpcpy(&s, l, num); + break; + } + case SUBST_MINOR: { + char num[UTIL_PATH_SIZE]; + + sprintf(num, "%u", minor(udev_device_get_devnum(dev))); + l = strpcpy(&s, l, num); + break; + } + case SUBST_RESULT: { + char *rest; + int i; + + if (event->program_result == NULL) + break; + /* get part of the result string */ + i = 0; + if (attr != NULL) + i = strtoul(attr, &rest, 10); + if (i > 0) { + char result[UTIL_PATH_SIZE]; + char tmp[UTIL_PATH_SIZE]; + char *cpos; + + strscpy(result, sizeof(result), event->program_result); + 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"); + 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); + } + break; + } + case SUBST_ATTR: { + const char *value = NULL; + char vbuf[UTIL_NAME_SIZE]; + size_t len; + int count; + + if (attr == NULL) { + log_error("missing file parameter for attr"); + break; + } + + /* try to read the value specified by "[dmi/id]product_name" */ + if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0) + value = vbuf; + + /* try to read the attribute the device */ + if (value == NULL) + value = udev_device_get_sysattr_value(event->dev, attr); + + /* try to read the attribute of the parent device, other matches have selected */ + if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev) + value = udev_device_get_sysattr_value(event->dev_parent, attr); + + if (value == NULL) + break; + + /* strip trailing whitespace, and replace unwanted characters */ + if (value != vbuf) + strscpy(vbuf, sizeof(vbuf), value); + len = strlen(vbuf); + while (len > 0 && isspace(vbuf[--len])) + vbuf[len] = '\0'; + count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT); + if (count > 0) + log_debug("%i character(s) replaced" , count); + l = strpcpy(&s, l, vbuf); + break; + } + case SUBST_PARENT: { + struct udev_device *dev_parent; + const char *devnode; + + dev_parent = udev_device_get_parent(event->dev); + if (dev_parent == NULL) + break; + devnode = udev_device_get_devnode(dev_parent); + if (devnode != NULL) + l = strpcpy(&s, l, devnode + strlen("/dev/")); + break; + } + case SUBST_DEVNODE: + if (udev_device_get_devnode(dev) != NULL) + l = strpcpy(&s, l, udev_device_get_devnode(dev)); + break; + case SUBST_NAME: + if (event->name != NULL) + l = strpcpy(&s, l, event->name); + else if (udev_device_get_devnode(dev) != NULL) + l = strpcpy(&s, l, udev_device_get_devnode(dev) + strlen("/dev/")); + else + l = strpcpy(&s, l, udev_device_get_sysname(dev)); + break; + case SUBST_LINKS: { + struct udev_list_entry *list_entry; + + list_entry = udev_device_get_devlinks_list_entry(dev); + if (list_entry == NULL) + break; + l = strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen("/dev/")); + udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) + l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen("/dev/"), NULL); + break; + } + case SUBST_ROOT: + l = strpcpy(&s, l, "/dev"); + break; + case SUBST_SYS: + l = strpcpy(&s, l, "/sys"); + break; + case SUBST_ENV: + if (attr == NULL) { + break; + } else { + const char *value; + + value = udev_device_get_property_value(event->dev, attr); + if (value == NULL) + break; + l = strpcpy(&s, l, value); + break; + } + default: + log_error("unknown substitution type=%i", type); + break; + } + + *dest = s; + + return l; +} + 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, - SUBST_DEVNODE, - SUBST_ATTR, - SUBST_ENV, - SUBST_KERNEL, - SUBST_KERNEL_NUMBER, - SUBST_DRIVER, - SUBST_DEVPATH, - SUBST_ID, - SUBST_MAJOR, - SUBST_MINOR, - SUBST_RESULT, - SUBST_PARENT, - SUBST_NAME, - SUBST_LINKS, - SUBST_ROOT, - SUBST_SYS, - }; static const struct subst_map { const char *name; const char fmt; @@ -217,186 +409,7 @@ subst: l = UTIL_PATH_SIZE; } - switch (type) { - case SUBST_DEVPATH: - l = strpcpy(&s, l, udev_device_get_devpath(dev)); - break; - case SUBST_KERNEL: - l = strpcpy(&s, l, udev_device_get_sysname(dev)); - break; - case SUBST_KERNEL_NUMBER: - if (udev_device_get_sysnum(dev) == NULL) - break; - l = strpcpy(&s, l, udev_device_get_sysnum(dev)); - break; - case SUBST_ID: - if (event->dev_parent == NULL) - break; - l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent)); - break; - case SUBST_DRIVER: { - const char *driver; - - if (event->dev_parent == NULL) - break; - - driver = udev_device_get_driver(event->dev_parent); - if (driver == NULL) - break; - l = strpcpy(&s, l, driver); - break; - } - case SUBST_MAJOR: { - char num[UTIL_PATH_SIZE]; - - sprintf(num, "%u", major(udev_device_get_devnum(dev))); - l = strpcpy(&s, l, num); - break; - } - case SUBST_MINOR: { - char num[UTIL_PATH_SIZE]; - - sprintf(num, "%u", minor(udev_device_get_devnum(dev))); - l = strpcpy(&s, l, num); - break; - } - case SUBST_RESULT: { - char *rest; - int i; - - if (event->program_result == NULL) - break; - /* get part of the result string */ - i = 0; - if (attr != NULL) - i = strtoul(attr, &rest, 10); - if (i > 0) { - char result[UTIL_PATH_SIZE]; - char tmp[UTIL_PATH_SIZE]; - char *cpos; - - strscpy(result, sizeof(result), event->program_result); - 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"); - 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); - } - break; - } - case SUBST_ATTR: { - const char *value = NULL; - char vbuf[UTIL_NAME_SIZE]; - size_t len; - int count; - - if (attr == NULL) { - log_error("missing file parameter for attr"); - break; - } - - /* try to read the value specified by "[dmi/id]product_name" */ - if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0) - value = vbuf; - - /* try to read the attribute the device */ - if (value == NULL) - value = udev_device_get_sysattr_value(event->dev, attr); - - /* try to read the attribute of the parent device, other matches have selected */ - if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev) - value = udev_device_get_sysattr_value(event->dev_parent, attr); - - if (value == NULL) - break; - - /* strip trailing whitespace, and replace unwanted characters */ - if (value != vbuf) - strscpy(vbuf, sizeof(vbuf), value); - len = strlen(vbuf); - while (len > 0 && isspace(vbuf[--len])) - vbuf[len] = '\0'; - count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT); - if (count > 0) - log_debug("%i character(s) replaced" , count); - l = strpcpy(&s, l, vbuf); - break; - } - case SUBST_PARENT: { - struct udev_device *dev_parent; - const char *devnode; - - dev_parent = udev_device_get_parent(event->dev); - if (dev_parent == NULL) - break; - devnode = udev_device_get_devnode(dev_parent); - if (devnode != NULL) - l = strpcpy(&s, l, devnode + strlen("/dev/")); - break; - } - case SUBST_DEVNODE: - if (udev_device_get_devnode(dev) != NULL) - l = strpcpy(&s, l, udev_device_get_devnode(dev)); - break; - case SUBST_NAME: - if (event->name != NULL) - l = strpcpy(&s, l, event->name); - else if (udev_device_get_devnode(dev) != NULL) - l = strpcpy(&s, l, udev_device_get_devnode(dev) + strlen("/dev/")); - else - l = strpcpy(&s, l, udev_device_get_sysname(dev)); - break; - case SUBST_LINKS: { - struct udev_list_entry *list_entry; - - list_entry = udev_device_get_devlinks_list_entry(dev); - if (list_entry == NULL) - break; - l = strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen("/dev/")); - udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) - l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen("/dev/"), NULL); - break; - } - case SUBST_ROOT: - l = strpcpy(&s, l, "/dev"); - break; - case SUBST_SYS: - l = strpcpy(&s, l, "/sys"); - break; - case SUBST_ENV: - if (attr == NULL) { - break; - } else { - const char *value; - - value = udev_device_get_property_value(event->dev, attr); - if (value == NULL) - break; - l = strpcpy(&s, l, value); - break; - } - default: - log_error("unknown substitution type=%i", type); - break; - } + l = subst_format_var(event, dev, type, attr, &s, l); /* replace whitespace in sbuf and copy to dest */ if (replws) { |