diff options
Diffstat (limited to 'src/udev')
l--------- | src/udev/accelerometer/Makefile | 1 | ||||
-rw-r--r-- | src/udev/accelerometer/accelerometer.c | 303 | ||||
-rw-r--r-- | src/udev/udev-event.c | 50 | ||||
-rw-r--r-- | src/udev/udev-rules.c | 65 | ||||
-rw-r--r-- | src/udev/udev.h | 3 | ||||
-rw-r--r-- | src/udev/udevd.c | 68 |
6 files changed, 67 insertions, 423 deletions
diff --git a/src/udev/accelerometer/Makefile b/src/udev/accelerometer/Makefile deleted file mode 120000 index d0b0e8e008..0000000000 --- a/src/udev/accelerometer/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile
\ No newline at end of file diff --git a/src/udev/accelerometer/accelerometer.c b/src/udev/accelerometer/accelerometer.c deleted file mode 100644 index 9e2c590c15..0000000000 --- a/src/udev/accelerometer/accelerometer.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * accelerometer - exports device orientation through property - * - * When an "change" event is received on an accelerometer, - * open its device node, and from the value, as well as the previous - * value of the property, calculate the device's new orientation, - * and export it as ID_INPUT_ACCELEROMETER_ORIENTATION. - * - * Possible values are: - * undefined - * * normal - * * bottom-up - * * left-up - * * right-up - * - * The property will be persistent across sessions, and the new - * orientations can be deducted from the previous one (it allows - * for a threshold for switching between opposite ends of the - * orientation). - * - * Copyright (C) 2011 Red Hat, Inc. - * Author: - * Bastien Nocera <hadess@hadess.net> - * - * orientation_calc() from the sensorfw package - * Copyright (C) 2009-2010 Nokia Corporation - * Authors: - * Üstün Ergenoglu <ext-ustun.ergenoglu@nokia.com> - * Timo Rongas <ext-timo.2.rongas@nokia.com> - * Lihan Guo <lihan.guo@digia.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <stdio.h> -#include <string.h> -#include <math.h> -#include <stdlib.h> -#include <getopt.h> -#include <limits.h> -#include <linux/input.h> - -#include "libudev.h" -#include "libudev-private.h" - -/* we must use this kernel-compatible implementation */ -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define OFF(x) ((x)%BITS_PER_LONG) -#define BIT(x) (1UL<<OFF(x)) -#define LONG(x) ((x)/BITS_PER_LONG) -#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) - -typedef enum { - ORIENTATION_UNDEFINED, - ORIENTATION_NORMAL, - ORIENTATION_BOTTOM_UP, - ORIENTATION_LEFT_UP, - ORIENTATION_RIGHT_UP -} OrientationUp; - -static const char *orientations[] = { - "undefined", - "normal", - "bottom-up", - "left-up", - "right-up", - NULL -}; - -#define ORIENTATION_UP_UP ORIENTATION_NORMAL - -#define DEFAULT_THRESHOLD 250 -#define RADIANS_TO_DEGREES 180.0/M_PI -#define SAME_AXIS_LIMIT 5 - -#define THRESHOLD_LANDSCAPE 25 -#define THRESHOLD_PORTRAIT 20 - -static const char * -orientation_to_string (OrientationUp o) -{ - return orientations[o]; -} - -static OrientationUp -string_to_orientation (const char *orientation) -{ - int i; - - if (orientation == NULL) - return ORIENTATION_UNDEFINED; - for (i = 0; orientations[i] != NULL; i++) { - if (streq (orientation, orientations[i])) - return i; - } - return ORIENTATION_UNDEFINED; -} - -static OrientationUp -orientation_calc (OrientationUp prev, - int x, int y, int z) -{ - int rotation; - OrientationUp ret = prev; - - /* Portrait check */ - rotation = round(atan((double) x / sqrt(y * y + z * z)) * RADIANS_TO_DEGREES); - - if (abs(rotation) > THRESHOLD_PORTRAIT) { - ret = (rotation < 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP; - - /* Some threshold to switching between portrait modes */ - if (prev == ORIENTATION_LEFT_UP || prev == ORIENTATION_RIGHT_UP) { - if (abs(rotation) < SAME_AXIS_LIMIT) { - ret = prev; - } - } - - } else { - /* Landscape check */ - rotation = round(atan((double) y / sqrt(x * x + z * z)) * RADIANS_TO_DEGREES); - - if (abs(rotation) > THRESHOLD_LANDSCAPE) { - ret = (rotation < 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL; - - /* Some threshold to switching between landscape modes */ - if (prev == ORIENTATION_BOTTOM_UP || prev == ORIENTATION_NORMAL) { - if (abs(rotation) < SAME_AXIS_LIMIT) { - ret = prev; - } - } - } - } - - return ret; -} - -static OrientationUp -get_prev_orientation(struct udev_device *dev) -{ - const char *value; - - value = udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER_ORIENTATION"); - if (value == NULL) - return ORIENTATION_UNDEFINED; - return string_to_orientation(value); -} - -#define READ_AXIS(axis, var) { memzero(&abs_info, sizeof(abs_info)); r = ioctl(fd, EVIOCGABS(axis), &abs_info); if (r < 0) return; var = abs_info.value; } - -/* accelerometers */ -static void test_orientation(struct udev *udev, - struct udev_device *dev, - const char *devpath) -{ - OrientationUp old, new; - _cleanup_close_ int fd = -1; - struct input_absinfo abs_info; - int x = 0, y = 0, z = 0; - int r; - char text[64]; - - old = get_prev_orientation(dev); - - fd = open(devpath, O_RDONLY|O_CLOEXEC); - if (fd < 0) - return; - - READ_AXIS(ABS_X, x); - READ_AXIS(ABS_Y, y); - READ_AXIS(ABS_Z, z); - - new = orientation_calc(old, x, y, z); - snprintf(text, sizeof(text), - "ID_INPUT_ACCELEROMETER_ORIENTATION=%s", orientation_to_string(new)); - puts(text); -} - -static void help(void) { - - printf("%s [options] <device path>\n\n" - "Accelerometer device identification.\n\n" - " -h --help Print this message\n" - " -d --debug Debug to stderr\n" - , program_invocation_short_name); -} - -int main (int argc, char** argv) -{ - struct udev *udev; - struct udev_device *dev; - - static const struct option options[] = { - { "debug", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - char devpath[PATH_MAX]; - char *devnode; - struct udev_enumerate *enumerate; - struct udev_list_entry *list_entry; - - log_parse_environment(); - log_open(); - - udev = udev_new(); - if (udev == NULL) - return 1; - - /* CLI argument parsing */ - while (1) { - int option; - - option = getopt_long(argc, argv, "dh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'd': - log_set_target(LOG_TARGET_CONSOLE); - log_set_max_level(LOG_DEBUG); - log_open(); - break; - case 'h': - help(); - exit(0); - default: - exit(1); - } - } - - if (argv[optind] == NULL) { - help(); - exit(1); - } - - /* get the device */ - snprintf(devpath, sizeof(devpath), "/sys/%s", argv[optind]); - dev = udev_device_new_from_syspath(udev, devpath); - if (dev == NULL) { - fprintf(stderr, "unable to access '%s'\n", devpath); - return 1; - } - - /* Get the children devices and find the devnode */ - devnode = NULL; - enumerate = udev_enumerate_new(udev); - udev_enumerate_add_match_parent(enumerate, dev); - udev_enumerate_scan_devices(enumerate); - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { - struct udev_device *device; - const char *node; - - device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), - udev_list_entry_get_name(list_entry)); - if (device == NULL) - continue; - /* Already found it */ - if (devnode != NULL) { - udev_device_unref(device); - continue; - } - - node = udev_device_get_devnode(device); - if (node == NULL) { - udev_device_unref(device); - continue; - } - /* Use the event sub-device */ - if (strstr(node, "/event") == NULL) { - udev_device_unref(device); - continue; - } - - devnode = strdup(node); - udev_device_unref(device); - } - - if (devnode == NULL) { - fprintf(stderr, "unable to get device node for '%s'\n", devpath); - return 0; - } - - log_debug("opening accelerometer device %s", devnode); - test_orientation(udev, dev, devnode); - free(devnode); - log_close(); - return 0; -} diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index 1092071e26..4761222786 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -721,19 +721,13 @@ int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, bool accept_failure, - const char *cmd, char **envp, + const char *cmd, char *result, size_t ressize) { int outpipe[2] = {-1, -1}; int errpipe[2] = {-1, -1}; pid_t pid; - char arg[UTIL_PATH_SIZE]; - char *argv[128]; - char program[UTIL_PATH_SIZE]; int err = 0; - strscpy(arg, sizeof(arg), cmd); - udev_build_argv(event->udev, arg, NULL, argv); - /* pipes from child to parent */ if (result != NULL || log_get_max_level() >= LOG_INFO) { if (pipe2(outpipe, O_NONBLOCK) != 0) { @@ -750,15 +744,14 @@ int udev_event_spawn(struct udev_event *event, } } - /* allow programs in /usr/lib/udev/ to be called without the path */ - if (argv[0][0] != '/') { - strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL); - argv[0] = program; - } - pid = fork(); switch(pid) { case 0: + { + char arg[UTIL_PATH_SIZE]; + char *argv[128]; + char program[UTIL_PATH_SIZE]; + /* child closes parent's ends of pipes */ if (outpipe[READ_END] >= 0) { close(outpipe[READ_END]); @@ -769,12 +762,22 @@ int udev_event_spawn(struct udev_event *event, errpipe[READ_END] = -1; } + strscpy(arg, sizeof(arg), cmd); + udev_build_argv(event->udev, arg, NULL, argv); + + /* allow programs in /usr/lib/udev/ to be called without the path */ + if (argv[0][0] != '/') { + strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL); + argv[0] = program; + } + log_debug("starting '%s'", cmd); - spawn_exec(event, cmd, argv, envp, + spawn_exec(event, cmd, argv, udev_device_get_properties_envp(event->dev), outpipe[WRITE_END], errpipe[WRITE_END]); - _exit(2 ); + _exit(2); + } case -1: log_error_errno(errno, "fork of '%s' failed: %m", cmd); err = -1; @@ -934,26 +937,21 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_ struct udev_list_entry *list_entry; udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) { + char command[UTIL_PATH_SIZE]; const char *cmd = udev_list_entry_get_name(list_entry); enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry); - 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)); + if (builtin_cmd < UDEV_BUILTIN_MAX) udev_builtin_run(event->dev, builtin_cmd, command, false); - } else { - char program[UTIL_PATH_SIZE]; - char **envp; - + else { if (event->exec_delay > 0) { - log_debug("delay execution of '%s'", program); + log_debug("delay execution of '%s'", command); sleep(event->exec_delay); } - udev_event_apply_format(event, cmd, program, sizeof(program)); - envp = udev_device_get_properties_envp(event->dev); - udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, program, envp, NULL, 0); + udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, command, NULL, 0); } } } diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 8ebc061eb1..d00f90afa6 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -634,14 +634,11 @@ static int import_program_into_properties(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const char *program) { - struct udev_device *dev = event->dev; - char **envp; char result[UTIL_LINE_SIZE]; char *line; int err; - envp = udev_device_get_properties_envp(dev); - err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result)); + err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)); if (err < 0) return err; @@ -654,7 +651,7 @@ static int import_program_into_properties(struct udev_event *event, pos[0] = '\0'; pos = &pos[1]; } - import_property_from_string(dev, line); + import_property_from_string(event->dev, line); line = pos; } return 0; @@ -682,41 +679,6 @@ static int import_parent_into_properties(struct udev_device *dev, const char *fi return 0; } -#define WAIT_LOOP_PER_SECOND 50 -static int wait_for_file(struct udev_device *dev, const char *file, int timeout) { - char filepath[UTIL_PATH_SIZE]; - char devicepath[UTIL_PATH_SIZE]; - struct stat stats; - int loop = timeout * WAIT_LOOP_PER_SECOND; - - /* a relative path is a device attribute */ - devicepath[0] = '\0'; - if (file[0] != '/') { - strscpyl(devicepath, sizeof(devicepath), udev_device_get_syspath(dev), NULL); - strscpyl(filepath, sizeof(filepath), devicepath, "/", file, NULL); - file = filepath; - } - - while (--loop) { - const struct timespec duration = { 0, 1000 * 1000 * 1000 / WAIT_LOOP_PER_SECOND }; - - /* lookup file */ - if (stat(file, &stats) == 0) { - log_debug("file '%s' appeared after %i loops", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1); - return 0; - } - /* make sure, the device did not disappear in the meantime */ - if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) { - log_debug("device disappeared while waiting for '%s'", file); - return -2; - } - log_debug("wait for '%s' for %i mseconds", file, 1000 / WAIT_LOOP_PER_SECOND); - nanosleep(&duration, NULL); - } - log_debug("waiting for '%s' failed", file); - return -1; -} - static int attr_subst_subdir(char *attr, size_t len) { bool found = false; @@ -1397,15 +1359,6 @@ static int add_rule(struct udev_rules *rules, char *line, continue; } - if (streq(key, "WAIT_FOR") || streq(key, "WAIT_FOR_SYSFS")) { - if (op == OP_REMOVE) { - log_error("invalid WAIT_FOR/WAIT_FOR_SYSFS operation"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_WAITFOR, 0, value, NULL); - continue; - } - if (streq(key, "LABEL")) { if (op == OP_REMOVE) { log_error("invalid LABEL operation"); @@ -1999,16 +1952,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules, if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0) goto nomatch; break; - case TK_M_WAITFOR: { - char filename[UTIL_PATH_SIZE]; - int found; - - udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename)); - found = (wait_for_file(event->dev, filename, 10) == 0); - if (!found && (cur->key.op != OP_NOMATCH)) - goto nomatch; - break; - } case TK_M_ATTR: if (match_attr(rules, event->dev, event, cur) != 0) goto nomatch; @@ -2119,19 +2062,17 @@ int udev_rules_apply_to_event(struct udev_rules *rules, } case TK_M_PROGRAM: { char program[UTIL_PATH_SIZE]; - char **envp; char result[UTIL_LINE_SIZE]; free(event->program_result); event->program_result = NULL; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program)); - envp = udev_device_get_properties_envp(event->dev); log_debug("PROGRAM '%s' %s:%u", program, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); - if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result)) < 0) { + if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)) < 0) { if (cur->key.op != OP_NOMATCH) goto nomatch; } else { diff --git a/src/udev/udev.h b/src/udev/udev.h index 3dca72e499..d17fc8c1ea 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -85,8 +85,7 @@ int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, bool accept_failure, - const char *cmd, char **envp, - char *result, size_t ressize); + const char *cmd, char *result, size_t ressize); void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list, diff --git a/src/udev/udevd.c b/src/udev/udevd.c index cf15ddf641..e27fb1fd9e 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1608,8 +1608,42 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg return 0; } -int main(int argc, char *argv[]) { +static int run(int fd_ctrl, int fd_uevent, const char *cgroup) { _cleanup_(manager_freep) Manager *manager = NULL; + int r; + + r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); + if (r < 0) { + r = log_error_errno(r, "failed to allocate manager object: %m"); + goto exit; + } + + r = udev_rules_apply_static_dev_perms(manager->rules); + if (r < 0) + log_error_errno(r, "failed to apply permissions on static device nodes: %m"); + + (void) sd_notify(false, + "READY=1\n" + "STATUS=Processing..."); + + r = sd_event_loop(manager->event); + if (r < 0) { + log_error_errno(r, "event loop failed: %m"); + goto exit; + } + + sd_event_get_exit_code(manager->event, &r); + +exit: + sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + if (manager) + udev_ctrl_cleanup(manager->ctrl); + return r; +} + +int main(int argc, char *argv[]) { _cleanup_free_ char *cgroup = NULL; int r, fd_ctrl, fd_uevent; @@ -1625,8 +1659,10 @@ int main(int argc, char *argv[]) { if (r < 0) log_warning_errno(r, "failed to parse kernel command line, ignoring: %m"); - if (arg_debug) + if (arg_debug) { + log_set_target(LOG_TARGET_CONSOLE); log_set_max_level(LOG_DEBUG); + } if (getuid() != 0) { r = log_error_errno(EPERM, "root privileges required"); @@ -1714,35 +1750,9 @@ int main(int argc, char *argv[]) { write_string_file("/proc/self/oom_score_adj", "-1000"); } - r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); - if (r < 0) { - r = log_error_errno(r, "failed to allocate manager object: %m"); - goto exit; - } - - r = udev_rules_apply_static_dev_perms(manager->rules); - if (r < 0) - log_error_errno(r, "failed to apply permissions on static device nodes: %m"); - - (void) sd_notify(false, - "READY=1\n" - "STATUS=Processing..."); - - r = sd_event_loop(manager->event); - if (r < 0) { - log_error_errno(r, "event loop failed: %m"); - goto exit; - } - - sd_event_get_exit_code(manager->event, &r); + r = run(fd_ctrl, fd_uevent, cgroup); exit: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - - if (manager) - udev_ctrl_cleanup(manager->ctrl); mac_selinux_finish(); log_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |