From c71509028fc2741b25dd537f9e1b7e8896df745e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 22 Aug 2018 21:59:29 +0900 Subject: udevadm-settle: modernize code --- src/udev/udevadm-settle.c | 139 +++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 76 deletions(-) (limited to 'src/udev/udevadm-settle.c') diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 9d46cb5221..a172b25ada 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -13,23 +13,26 @@ #include #include -#include "parse-util.h" -#include "udev.h" +#include "time-util.h" #include "udevadm.h" -#include "udevadm-util.h" -#include "util.h" +#include "udev.h" + +static usec_t arg_timeout = 120 * USEC_PER_SEC; +static const char *arg_exists = NULL; -static void help(void) { +static int help(void) { printf("%s settle [OPTIONS]\n\n" "Wait for pending udev events.\n\n" " -h --help Show this help\n" " -V --version Show package version\n" - " -t --timeout=SECONDS Maximum time to wait for events\n" + " -t --timeout=SEC Maximum time to wait for events\n" " -E --exit-if-exists=FILE Stop waiting if file exists\n" , program_invocation_short_name); + + return 0; } -int settle_main(int argc, char *argv[], void *userdata) { +static int parse_argv(int argc, char *argv[]) { static const struct option options[] = { { "timeout", required_argument, NULL, 't' }, { "exit-if-exists", required_argument, NULL, 'E' }, @@ -40,111 +43,95 @@ int settle_main(int argc, char *argv[], void *userdata) { { "quiet", no_argument, NULL, 'q' }, /* removed */ {} }; - usec_t deadline; - const char *exists = NULL; - unsigned int timeout = 120; - struct pollfd pfd[1] = { {.fd = -1}, }; - int c; - struct udev_queue *queue; - int rc = EXIT_FAILURE; + + int c, r; while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) { switch (c) { - - case 't': { - int r; - - r = safe_atou(optarg, &timeout); - if (r < 0) { - log_error_errno(r, "Invalid timeout value '%s': %m", optarg); - return EXIT_FAILURE; - } + case 't': + r = parse_sec(optarg, &arg_timeout); + if (r < 0) + return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg); break; - } - case 'E': - exists = optarg; + arg_exists = optarg; break; - case 'V': - print_version(); - return EXIT_SUCCESS; - + return version(); case 'h': - help(); - return EXIT_SUCCESS; - + return help(); case 's': case 'e': case 'q': log_info("Option -%c no longer supported.", c); - return EXIT_FAILURE; - + return -EINVAL; case '?': - return EXIT_FAILURE; - + return -EINVAL; default: - assert_not_reached("Unknown argument"); + assert_not_reached("Unknown option."); } } - if (optind < argc) { - fprintf(stderr, "Extraneous argument: '%s'\n", argv[optind]); - return EXIT_FAILURE; - } + return 1; +} + +int settle_main(int argc, char *argv[], void *userdata) { + _cleanup_(udev_queue_unrefp) struct udev_queue *queue = NULL; + struct pollfd pfd; + usec_t deadline; + int r; - deadline = now(CLOCK_MONOTONIC) + timeout * USEC_PER_SEC; + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + deadline = now(CLOCK_MONOTONIC) + arg_timeout; /* guarantee that the udev daemon isn't pre-processing */ if (getuid() == 0) { - struct udev_ctrl *uctrl; + _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL; uctrl = udev_ctrl_new(); - if (uctrl != NULL) { - if (udev_ctrl_send_ping(uctrl, MAX(5U, timeout)) < 0) { - log_debug("no connection to daemon"); - udev_ctrl_unref(uctrl); - return EXIT_SUCCESS; + if (uctrl) { + r = udev_ctrl_send_ping(uctrl, MAX(5U, arg_timeout / USEC_PER_SEC)); + if (r < 0) { + log_debug_errno(r, "Failed to connect to udev daemon."); + return 0; } - udev_ctrl_unref(uctrl); } } queue = udev_queue_new(NULL); - if (!queue) { - log_error("unable to get udev queue"); - return EXIT_FAILURE; - } + if (!queue) + return log_error_errno(errno, "Failed to get udev queue: %m"); - pfd[0].events = POLLIN; - pfd[0].fd = udev_queue_get_fd(queue); - if (pfd[0].fd < 0) { - log_debug("queue is empty, nothing to watch"); - rc = EXIT_SUCCESS; - goto out; + r = udev_queue_get_fd(queue); + if (r < 0) { + log_debug_errno(r, "Queue is empty, nothing to watch."); + return 0; } + pfd = (struct pollfd) { + .events = POLLIN, + .fd = r, + }; + for (;;) { - if (exists && access(exists, F_OK) >= 0) { - rc = EXIT_SUCCESS; - break; - } + if (arg_exists && access(arg_exists, F_OK) >= 0) + return 0; /* exit if queue is empty */ - if (udev_queue_get_queue_is_empty(queue)) { - rc = EXIT_SUCCESS; - break; - } + if (udev_queue_get_queue_is_empty(queue)) + return 0; if (now(CLOCK_MONOTONIC) >= deadline) - break; + return -ETIMEDOUT; - /* wake up when queue is empty */ - if (poll(pfd, 1, MSEC_PER_SEC) > 0 && pfd[0].revents & POLLIN) - udev_queue_flush(queue); + /* wake up when queue becomes empty */ + if (poll(&pfd, 1, MSEC_PER_SEC) > 0 && pfd.revents & POLLIN) { + r = udev_queue_flush(queue); + if (r < 0) + return log_error_errno(r, "Failed to flush queue: %m"); + } } - -out: - udev_queue_unref(queue); - return rc; } -- cgit v1.2.1