]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/udev-util.c
Merge pull request #21838 from lnussel/logind-refactor
[thirdparty/systemd.git] / src / shared / udev-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <ctype.h>
4 #include <errno.h>
5 #include <sys/inotify.h>
6 #include <unistd.h>
7
8 #include "alloc-util.h"
9 #include "device-nodes.h"
10 #include "device-private.h"
11 #include "device-util.h"
12 #include "env-file.h"
13 #include "errno-util.h"
14 #include "escape.h"
15 #include "fd-util.h"
16 #include "id128-util.h"
17 #include "log.h"
18 #include "macro.h"
19 #include "parse-util.h"
20 #include "path-util.h"
21 #include "signal-util.h"
22 #include "socket-util.h"
23 #include "string-table.h"
24 #include "string-util.h"
25 #include "strxcpyx.h"
26 #include "udev-util.h"
27 #include "utf8.h"
28
29 static const char* const resolve_name_timing_table[_RESOLVE_NAME_TIMING_MAX] = {
30 [RESOLVE_NAME_NEVER] = "never",
31 [RESOLVE_NAME_LATE] = "late",
32 [RESOLVE_NAME_EARLY] = "early",
33 };
34
35 DEFINE_STRING_TABLE_LOOKUP(resolve_name_timing, ResolveNameTiming);
36
37 int udev_parse_config_full(
38 unsigned *ret_children_max,
39 usec_t *ret_exec_delay_usec,
40 usec_t *ret_event_timeout_usec,
41 ResolveNameTiming *ret_resolve_name_timing,
42 int *ret_timeout_signal) {
43
44 _cleanup_free_ char *log_val = NULL, *children_max = NULL, *exec_delay = NULL, *event_timeout = NULL, *resolve_names = NULL, *timeout_signal = NULL;
45 int r;
46
47 r = parse_env_file(NULL, "/etc/udev/udev.conf",
48 "udev_log", &log_val,
49 "children_max", &children_max,
50 "exec_delay", &exec_delay,
51 "event_timeout", &event_timeout,
52 "resolve_names", &resolve_names,
53 "timeout_signal", &timeout_signal);
54 if (r == -ENOENT)
55 return 0;
56 if (r < 0)
57 return r;
58
59 if (log_val) {
60 const char *log;
61 size_t n;
62
63 /* unquote */
64 n = strlen(log_val);
65 if (n >= 2 &&
66 ((log_val[0] == '"' && log_val[n-1] == '"') ||
67 (log_val[0] == '\'' && log_val[n-1] == '\''))) {
68 log_val[n - 1] = '\0';
69 log = log_val + 1;
70 } else
71 log = log_val;
72
73 /* we set the udev log level here explicitly, this is supposed
74 * to regulate the code in libudev/ and udev/. */
75 r = log_set_max_level_from_string(log);
76 if (r < 0)
77 log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
78 "failed to set udev log level '%s', ignoring: %m", log);
79 }
80
81 if (ret_children_max && children_max) {
82 r = safe_atou(children_max, ret_children_max);
83 if (r < 0)
84 log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
85 "failed to parse children_max=%s, ignoring: %m", children_max);
86 }
87
88 if (ret_exec_delay_usec && exec_delay) {
89 r = parse_sec(exec_delay, ret_exec_delay_usec);
90 if (r < 0)
91 log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
92 "failed to parse exec_delay=%s, ignoring: %m", exec_delay);
93 }
94
95 if (ret_event_timeout_usec && event_timeout) {
96 r = parse_sec(event_timeout, ret_event_timeout_usec);
97 if (r < 0)
98 log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
99 "failed to parse event_timeout=%s, ignoring: %m", event_timeout);
100 }
101
102 if (ret_resolve_name_timing && resolve_names) {
103 ResolveNameTiming t;
104
105 t = resolve_name_timing_from_string(resolve_names);
106 if (t < 0)
107 log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
108 "failed to parse resolve_names=%s, ignoring.", resolve_names);
109 else
110 *ret_resolve_name_timing = t;
111 }
112
113 if (ret_timeout_signal && timeout_signal) {
114 r = signal_from_string(timeout_signal);
115 if (r < 0)
116 log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
117 "failed to parse timeout_signal=%s, ignoring: %m", timeout_signal);
118 else
119 *ret_timeout_signal = r;
120 }
121
122 return 0;
123 }
124
125 /* Note that if -ENOENT is returned, it will be logged at debug level rather than error,
126 * because it's an expected, common occurrence that the caller will handle with a fallback */
127 static int device_new_from_dev_path(const char *devlink, sd_device **ret_device) {
128 struct stat st;
129 int r;
130
131 assert(devlink);
132
133 if (stat(devlink, &st) < 0)
134 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
135 "Failed to stat() %s: %m", devlink);
136
137 if (!S_ISBLK(st.st_mode))
138 return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK),
139 "%s does not point to a block device: %m", devlink);
140
141 r = sd_device_new_from_stat_rdev(ret_device, &st);
142 if (r < 0)
143 return log_error_errno(r, "Failed to initialize device from %s: %m", devlink);
144
145 return 0;
146 }
147
148 struct DeviceMonitorData {
149 const char *sysname;
150 const char *devlink;
151 sd_device *device;
152 };
153
154 static void device_monitor_data_free(struct DeviceMonitorData *d) {
155 assert(d);
156
157 sd_device_unref(d->device);
158 }
159
160 static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) {
161 struct DeviceMonitorData *data = userdata;
162 const char *sysname;
163
164 assert(device);
165 assert(data);
166 assert(data->sysname || data->devlink);
167 assert(!data->device);
168
169 /* Ignore REMOVE events here. We are waiting for initialization after all, not de-initialization. We
170 * might see a REMOVE event from an earlier use of the device (devices by the same name are recycled
171 * by the kernel after all), which we should not get confused by. After all we cannot distinguish use
172 * cycles of the devices, as the udev queue is entirely asynchronous.
173 *
174 * If we see a REMOVE event here for the use cycle we actually care about then we won't notice of
175 * course, but that should be OK, given the timeout logic used on the wait loop: this will be noticed
176 * by means of -ETIMEDOUT. Thus we won't notice immediately, but eventually, and that should be
177 * sufficient for an error path that should regularly not happen.
178 *
179 * (And yes, we only need to special case REMOVE. It's the only "negative" event type, where a device
180 * ceases to exist. All other event types are "positive": the device exists and is registered in the
181 * udev database, thus whenever we see the event, we can consider it initialized.) */
182 if (device_for_action(device, SD_DEVICE_REMOVE))
183 return 0;
184
185 if (data->sysname && sd_device_get_sysname(device, &sysname) >= 0 && streq(sysname, data->sysname))
186 goto found;
187
188 if (data->devlink) {
189 const char *devlink;
190
191 FOREACH_DEVICE_DEVLINK(device, devlink)
192 if (path_equal(devlink, data->devlink))
193 goto found;
194
195 if (sd_device_get_devname(device, &devlink) >= 0 && path_equal(devlink, data->devlink))
196 goto found;
197 }
198
199 return 0;
200
201 found:
202 data->device = sd_device_ref(device);
203 return sd_event_exit(sd_device_monitor_get_event(monitor), 0);
204 }
205
206 static int device_wait_for_initialization_internal(
207 sd_device *_device,
208 const char *devlink,
209 const char *subsystem,
210 usec_t deadline,
211 sd_device **ret) {
212
213 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
214 _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
215 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
216 /* Ensure that if !_device && devlink, device gets unrefd on errors since it will be new */
217 _cleanup_(sd_device_unrefp) sd_device *device = sd_device_ref(_device);
218 _cleanup_(device_monitor_data_free) struct DeviceMonitorData data = {
219 .devlink = devlink,
220 };
221 int r;
222
223 assert(device || (subsystem && devlink));
224
225 /* Devlink might already exist, if it does get the device to use the sysname filtering */
226 if (!device && devlink) {
227 r = device_new_from_dev_path(devlink, &device);
228 if (r < 0 && r != -ENOENT)
229 return r;
230 }
231
232 if (device) {
233 if (sd_device_get_is_initialized(device) > 0) {
234 if (ret)
235 *ret = sd_device_ref(device);
236 return 0;
237 }
238 /* We need either the sysname or the devlink for filtering */
239 assert_se(sd_device_get_sysname(device, &data.sysname) >= 0 || devlink);
240 }
241
242 /* Wait until the device is initialized, so that we can get access to the ID_PATH property */
243
244 r = sd_event_new(&event);
245 if (r < 0)
246 return log_error_errno(r, "Failed to get default event: %m");
247
248 r = sd_device_monitor_new(&monitor);
249 if (r < 0)
250 return log_error_errno(r, "Failed to acquire monitor: %m");
251
252 if (device && !subsystem) {
253 r = sd_device_get_subsystem(device, &subsystem);
254 if (r < 0 && r != -ENOENT)
255 return log_device_error_errno(device, r, "Failed to get subsystem: %m");
256 }
257
258 if (subsystem) {
259 r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, NULL);
260 if (r < 0)
261 return log_error_errno(r, "Failed to add %s subsystem match to monitor: %m", subsystem);
262 }
263
264 r = sd_device_monitor_attach_event(monitor, event);
265 if (r < 0)
266 return log_error_errno(r, "Failed to attach event to device monitor: %m");
267
268 r = sd_device_monitor_start(monitor, device_monitor_handler, &data);
269 if (r < 0)
270 return log_error_errno(r, "Failed to start device monitor: %m");
271
272 if (deadline != USEC_INFINITY) {
273 r = sd_event_add_time(
274 event, &timeout_source,
275 CLOCK_MONOTONIC, deadline, 0,
276 NULL, INT_TO_PTR(-ETIMEDOUT));
277 if (r < 0)
278 return log_error_errno(r, "Failed to add timeout event source: %m");
279 }
280
281 /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized
282 * yet. */
283 if (!device && devlink) {
284 r = device_new_from_dev_path(devlink, &device);
285 if (r < 0 && r != -ENOENT)
286 return r;
287 }
288 if (device && sd_device_get_is_initialized(device) > 0) {
289 if (ret)
290 *ret = sd_device_ref(device);
291 return 0;
292 }
293
294 r = sd_event_loop(event);
295 if (r < 0)
296 return log_error_errno(r, "Failed to wait for device to be initialized: %m");
297
298 if (ret)
299 *ret = TAKE_PTR(data.device);
300 return 0;
301 }
302
303 int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t deadline, sd_device **ret) {
304 return device_wait_for_initialization_internal(device, NULL, subsystem, deadline, ret);
305 }
306
307 int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t deadline, sd_device **ret) {
308 return device_wait_for_initialization_internal(NULL, devlink, subsystem, deadline, ret);
309 }
310
311 int device_is_renaming(sd_device *dev) {
312 int r;
313
314 assert(dev);
315
316 r = sd_device_get_property_value(dev, "ID_RENAMING", NULL);
317 if (r == -ENOENT)
318 return false;
319 if (r < 0)
320 return r;
321
322 return true;
323 }
324
325 bool device_for_action(sd_device *dev, sd_device_action_t a) {
326 sd_device_action_t b;
327
328 assert(dev);
329
330 if (a < 0)
331 return false;
332
333 if (sd_device_get_action(dev, &b) < 0)
334 return false;
335
336 return a == b;
337 }
338
339 void log_device_uevent(sd_device *device, const char *str) {
340 sd_device_action_t action = _SD_DEVICE_ACTION_INVALID;
341 sd_id128_t event_id = SD_ID128_NULL;
342 uint64_t seqnum = 0;
343
344 if (!DEBUG_LOGGING)
345 return;
346
347 (void) sd_device_get_seqnum(device, &seqnum);
348 (void) sd_device_get_action(device, &action);
349 (void) sd_device_get_trigger_uuid(device, &event_id);
350 log_device_debug(device, "%s%s(SEQNUM=%"PRIu64", ACTION=%s%s%s)",
351 strempty(str), isempty(str) ? "" : " ",
352 seqnum, strna(device_action_to_string(action)),
353 sd_id128_is_null(event_id) ? "" : ", UUID=",
354 sd_id128_is_null(event_id) ? "" : id128_to_uuid_string(event_id, (char[ID128_UUID_STRING_MAX]){}));
355 }
356
357 int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
358 char *i, *j;
359 bool is_escaped;
360
361 /* value must be double quotated */
362 is_escaped = str[0] == 'e';
363 str += is_escaped;
364 if (str[0] != '"')
365 return -EINVAL;
366 str++;
367
368 if (!is_escaped) {
369 /* unescape double quotation '\"'->'"' */
370 for (i = j = str; *i != '"'; i++, j++) {
371 if (*i == '\0')
372 return -EINVAL;
373 if (i[0] == '\\' && i[1] == '"')
374 i++;
375 *j = *i;
376 }
377 j[0] = '\0';
378 } else {
379 _cleanup_free_ char *unescaped = NULL;
380 ssize_t l;
381
382 /* find the end position of value */
383 for (i = str; *i != '"'; i++) {
384 if (i[0] == '\\')
385 i++;
386 if (*i == '\0')
387 return -EINVAL;
388 }
389 i[0] = '\0';
390
391 l = cunescape_length(str, i - str, 0, &unescaped);
392 if (l < 0)
393 return l;
394
395 assert(l <= i - str);
396 memcpy(str, unescaped, l + 1);
397 }
398
399 *ret_value = str;
400 *ret_endpos = i + 1;
401 return 0;
402 }
403
404 size_t udev_replace_whitespace(const char *str, char *to, size_t len) {
405 bool is_space = false;
406 size_t i, j;
407
408 assert(str);
409 assert(to);
410
411 /* Copy from 'str' to 'to', while removing all leading and trailing whitespace, and replacing
412 * each run of consecutive whitespace with a single underscore. The chars from 'str' are copied
413 * up to the \0 at the end of the string, or at most 'len' chars. This appends \0 to 'to', at
414 * the end of the copied characters.
415 *
416 * If 'len' chars are copied into 'to', the final \0 is placed at len+1 (i.e. 'to[len] = \0'),
417 * so the 'to' buffer must have at least len+1 chars available.
418 *
419 * Note this may be called with 'str' == 'to', i.e. to replace whitespace in-place in a buffer.
420 * This function can handle that situation.
421 *
422 * Note that only 'len' characters are read from 'str'. */
423
424 i = strspn(str, WHITESPACE);
425
426 for (j = 0; j < len && i < len && str[i] != '\0'; i++) {
427 if (isspace(str[i])) {
428 is_space = true;
429 continue;
430 }
431
432 if (is_space) {
433 if (j + 1 >= len)
434 break;
435
436 to[j++] = '_';
437 is_space = false;
438 }
439 to[j++] = str[i];
440 }
441
442 to[j] = '\0';
443 return j;
444 }
445
446 size_t udev_replace_ifname(char *str) {
447 size_t replaced = 0;
448
449 assert(str);
450
451 /* See ifname_valid_full(). */
452
453 for (char *p = str; *p != '\0'; p++)
454 if (!ifname_valid_char(*p)) {
455 *p = '_';
456 replaced++;
457 }
458
459 return replaced;
460 }
461
462 size_t udev_replace_chars(char *str, const char *allow) {
463 size_t i = 0, replaced = 0;
464
465 assert(str);
466
467 /* allow chars in allow list, plain ascii, hex-escaping and valid utf8. */
468
469 while (str[i] != '\0') {
470 int len;
471
472 if (allow_listed_char_for_devnode(str[i], allow)) {
473 i++;
474 continue;
475 }
476
477 /* accept hex encoding */
478 if (str[i] == '\\' && str[i+1] == 'x') {
479 i += 2;
480 continue;
481 }
482
483 /* accept valid utf8 */
484 len = utf8_encoded_valid_unichar(str + i, SIZE_MAX);
485 if (len > 1) {
486 i += len;
487 continue;
488 }
489
490 /* if space is allowed, replace whitespace with ordinary space */
491 if (isspace(str[i]) && allow && strchr(allow, ' ')) {
492 str[i] = ' ';
493 i++;
494 replaced++;
495 continue;
496 }
497
498 /* everything else is replaced with '_' */
499 str[i] = '_';
500 i++;
501 replaced++;
502 }
503 return replaced;
504 }
505
506 int udev_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value) {
507 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
508 _cleanup_free_ char *temp = NULL;
509 char *subsys, *sysname, *attr;
510 const char *val;
511 int r;
512
513 assert(string);
514 assert(result);
515
516 /* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */
517
518 if (string[0] != '[')
519 return -EINVAL;
520
521 temp = strdup(string);
522 if (!temp)
523 return -ENOMEM;
524
525 subsys = &temp[1];
526
527 sysname = strchr(subsys, '/');
528 if (!sysname)
529 return -EINVAL;
530 sysname[0] = '\0';
531 sysname = &sysname[1];
532
533 attr = strchr(sysname, ']');
534 if (!attr)
535 return -EINVAL;
536 attr[0] = '\0';
537 attr = &attr[1];
538 if (attr[0] == '/')
539 attr = &attr[1];
540 if (attr[0] == '\0')
541 attr = NULL;
542
543 if (read_value && !attr)
544 return -EINVAL;
545
546 r = sd_device_new_from_subsystem_sysname(&dev, subsys, sysname);
547 if (r < 0)
548 return r;
549
550 if (read_value) {
551 r = sd_device_get_sysattr_value(dev, attr, &val);
552 if (r < 0 && !ERRNO_IS_PRIVILEGE(r) && r != -ENOENT)
553 return r;
554 if (r >= 0)
555 strscpy(result, maxsize, val);
556 else
557 result[0] = '\0';
558 log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result);
559 } else {
560 r = sd_device_get_syspath(dev, &val);
561 if (r < 0)
562 return r;
563
564 strscpyl(result, maxsize, val, attr ? "/" : NULL, attr ?: NULL, NULL);
565 log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, strempty(attr), result);
566 }
567 return 0;
568 }
569
570 int udev_queue_is_empty(void) {
571 return access("/run/udev/queue", F_OK) < 0 ?
572 (errno == ENOENT ? true : -errno) : false;
573 }
574
575 int udev_queue_init(void) {
576 _cleanup_close_ int fd = -1;
577
578 fd = inotify_init1(IN_CLOEXEC);
579 if (fd < 0)
580 return -errno;
581
582 if (inotify_add_watch(fd, "/run/udev" , IN_DELETE) < 0)
583 return -errno;
584
585 return TAKE_FD(fd);
586 }
587
588 static int device_is_power_sink(sd_device *device) {
589 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
590 bool found_source = false, found_sink = false;
591 sd_device *parent, *d;
592 int r;
593
594 assert(device);
595
596 /* USB-C power supply device has two power roles: source or sink. See,
597 * https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-typec */
598
599 r = sd_device_enumerator_new(&e);
600 if (r < 0)
601 return r;
602
603 r = sd_device_enumerator_allow_uninitialized(e);
604 if (r < 0)
605 return r;
606
607 r = sd_device_enumerator_add_match_subsystem(e, "typec", true);
608 if (r < 0)
609 return r;
610
611 r = sd_device_get_parent(device, &parent);
612 if (r < 0)
613 return r;
614
615 r = sd_device_enumerator_add_match_parent(e, parent);
616 if (r < 0)
617 return r;
618
619 FOREACH_DEVICE(e, d) {
620 const char *val;
621
622 r = sd_device_get_sysattr_value(d, "power_role", &val);
623 if (r < 0) {
624 if (r != -ENOENT)
625 log_device_debug_errno(d, r, "Failed to read 'power_role' sysfs attribute, ignoring: %m");
626 continue;
627 }
628
629 if (strstr(val, "[source]")) {
630 found_source = true;
631 log_device_debug(d, "The USB type-C port is in power source mode.");
632 } else if (strstr(val, "[sink]")) {
633 found_sink = true;
634 log_device_debug(d, "The USB type-C port is in power sink mode.");
635 }
636 }
637
638 if (found_sink)
639 log_device_debug(device, "The USB type-C device has at least one port in power sink mode.");
640 else if (!found_source)
641 log_device_debug(device, "The USB type-C device has no port in power source mode, assuming the device is in power sink mode.");
642 else
643 log_device_debug(device, "All USB type-C ports are in power source mode.");
644
645 return found_sink || !found_source;
646 }
647
648 int on_ac_power(void) {
649 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
650 bool found_offline = false, found_online = false;
651 sd_device *d;
652 int r;
653
654 r = sd_device_enumerator_new(&e);
655 if (r < 0)
656 return r;
657
658 r = sd_device_enumerator_allow_uninitialized(e);
659 if (r < 0)
660 return r;
661
662 r = sd_device_enumerator_add_match_subsystem(e, "power_supply", true);
663 if (r < 0)
664 return r;
665
666 FOREACH_DEVICE(e, d) {
667 const char *val;
668 unsigned v;
669
670 r = sd_device_get_sysattr_value(d, "type", &val);
671 if (r < 0) {
672 log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring: %m");
673 continue;
674 }
675
676 /* We assume every power source is AC, except for batteries. See
677 * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
678 * for defined power source types. Also see:
679 * https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power */
680 if (streq(val, "Battery")) {
681 log_device_debug(d, "The power supply is battery, ignoring.");
682 continue;
683 }
684
685 /* Ignore USB-C power supply in source mode. See issue #21988. */
686 if (streq(val, "USB")) {
687 r = device_is_power_sink(d);
688 if (r <= 0) {
689 if (r < 0)
690 log_device_debug_errno(d, r, "Failed to determine the current power role, ignoring: %m");
691 else
692 log_device_debug(d, "USB power supply is in source mode, ignoring.");
693 continue;
694 }
695 }
696
697 r = sd_device_get_sysattr_value(d, "online", &val);
698 if (r < 0) {
699 log_device_debug_errno(d, r, "Failed to read 'online' sysfs attribute, ignoring: %m");
700 continue;
701 }
702
703 r = safe_atou(val, &v);
704 if (r < 0) {
705 log_device_debug_errno(d, r, "Failed to parse 'online' attribute, ignoring: %m");
706 continue;
707 }
708
709 if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
710 found_online = true;
711 else
712 found_offline = true;
713
714 log_device_debug(d, "The power supply is currently %s.", v > 0 ? "online" : "offline");
715 }
716
717 if (found_online)
718 log_debug("Found at least one online non-battery power supply, system is running on AC power.");
719 else if (!found_offline)
720 log_debug("Found no offline non-battery power supply, assuming system is running on AC power.");
721 else
722 log_debug("All non-battery power supplies are offline, assuming system is running with battery.");
723
724 return found_online || !found_offline;
725 }