1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * Copyright © 2009 Canonical Ltd.
4 * Copyright © 2009 Scott James Remnant <scott@netsplit.com>
17 #include "sd-messages.h"
22 #include "string-util.h"
24 #include "time-util.h"
25 #include "udev-ctrl.h"
26 #include "udev-util.h"
32 static usec_t arg_timeout
= 120 * USEC_PER_SEC
;
33 static const char *arg_exists
= NULL
;
35 static int help(void) {
36 printf("%s settle [OPTIONS]\n\n"
37 "Wait for pending udev events.\n\n"
38 " -h --help Show this help\n"
39 " -V --version Show package version\n"
40 " -t --timeout=SEC Maximum time to wait for events\n"
41 " -E --exit-if-exists=FILE Stop waiting if file exists\n",
42 program_invocation_short_name
);
47 static int parse_argv(int argc
, char *argv
[]) {
48 static const struct option options
[] = {
49 { "timeout", required_argument
, NULL
, 't' },
50 { "exit-if-exists", required_argument
, NULL
, 'E' },
51 { "version", no_argument
, NULL
, 'V' },
52 { "help", no_argument
, NULL
, 'h' },
53 { "seq-start", required_argument
, NULL
, 's' }, /* removed */
54 { "seq-end", required_argument
, NULL
, 'e' }, /* removed */
55 { "quiet", no_argument
, NULL
, 'q' }, /* removed */
61 while ((c
= getopt_long(argc
, argv
, "t:E:Vhs:e:q", options
, NULL
)) >= 0) {
64 r
= parse_sec(optarg
, &arg_timeout
);
66 return log_error_errno(r
, "Failed to parse timeout value '%s': %m", optarg
);
72 return print_version();
78 return log_info_errno(SYNTHETIC_ERRNO(EINVAL
),
79 "Option -%c no longer supported.",
91 static int emit_deprecation_warning(void) {
92 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
93 _cleanup_strv_free_
char **a
= NULL
;
94 _cleanup_free_
char *unit
= NULL
;
97 r
= sd_pid_get_unit(0, &unit
);
99 log_debug_errno(r
, "Failed to determine unit we run in, ignoring: %m");
103 if (!streq(unit
, "systemd-udev-settle.service"))
106 r
= bus_connect_system_systemd(&bus
);
108 log_debug_errno(r
, "Failed to open connection to systemd, skipping dependency queries: %m");
110 _cleanup_strv_free_
char **b
= NULL
;
111 _cleanup_free_
char *unit_path
= NULL
;
113 unit_path
= unit_dbus_path_from_name("systemd-udev-settle.service");
117 (void) sd_bus_get_property_strv(
119 "org.freedesktop.systemd1",
121 "org.freedesktop.systemd1.Unit",
126 (void) sd_bus_get_property_strv(
128 "org.freedesktop.systemd1",
130 "org.freedesktop.systemd1.Unit",
135 r
= strv_extend_strv(&a
, b
, true);
141 /* Print a simple message if we cannot determine the dependencies */
142 log_notice("systemd-udev-settle.service is deprecated.");
144 /* Print a longer, structured message if we can acquire the dependencies (this should be the
145 * common case). This is hooked up with a catalog entry and everything. */
146 _cleanup_free_
char *t
= NULL
;
148 t
= strv_join(a
, ", ");
152 log_struct(LOG_NOTICE
,
153 "MESSAGE=systemd-udev-settle.service is deprecated. Please fix %s not to pull it in.", t
,
154 "OFFENDING_UNITS=%s", t
,
155 "MESSAGE_ID=" SD_MESSAGE_SYSTEMD_UDEV_SETTLE_DEPRECATED_STR
);
161 int settle_main(int argc
, char *argv
[], void *userdata
) {
162 _cleanup_close_
int fd
= -1;
166 r
= parse_argv(argc
, argv
);
170 if (running_in_chroot() > 0) {
171 log_info("Running in chroot, ignoring request.");
175 deadline
= now(CLOCK_MONOTONIC
) + arg_timeout
;
177 /* guarantee that the udev daemon isn't pre-processing */
179 _cleanup_(udev_ctrl_unrefp
) UdevCtrl
*uctrl
= NULL
;
181 if (udev_ctrl_new(&uctrl
) >= 0) {
182 r
= udev_ctrl_send_ping(uctrl
);
184 log_debug_errno(r
, "Failed to connect to udev daemon: %m");
188 r
= udev_ctrl_wait(uctrl
, MAX(5 * USEC_PER_SEC
, arg_timeout
));
190 return log_error_errno(r
, "Failed to wait for daemon to reply: %m");
194 fd
= udev_queue_init();
196 log_debug_errno(fd
, "Queue is empty, nothing to watch: %m");
200 (void) emit_deprecation_warning();
203 if (arg_exists
&& access(arg_exists
, F_OK
) >= 0)
206 /* exit if queue is empty */
207 r
= udev_queue_is_empty();
209 return log_error_errno(r
, "Failed to check queue is empty: %m");
213 if (now(CLOCK_MONOTONIC
) >= deadline
)
216 /* wake up when queue becomes empty */
217 r
= fd_wait_for_event(fd
, POLLIN
, MSEC_PER_SEC
);
223 return log_error_errno(r
, "Failed to flush queue: %m");