1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <ctype.h>
4 #include <net/if.h>
5 #include <sys/types.h>
6
7 #include "sd-device.h"
8
9 #include "alloc-util.h"
10 #include "device-internal.h"
11 #include "device-private.h"
12 #include "device-util.h"
13 #include "fd-util.h"
14 #include "fileio.h"
15 #include "fs-util.h"
16 #include "hashmap.h"
17 #include "macro.h"
18 #include "mkdir.h"
19 #include "nulstr-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
22 #include "set.h"
23 #include "stdio-util.h"
24 #include "string-table.h"
25 #include "string-util.h"
26 #include "strv.h"
27 #include "strxcpyx.h"
28 #include "tmpfile-util.h"
29 #include "user-util.h"
30
device_add_property(sd_device * device,const char * key,const char * value)31 int device_add_property(sd_device *device, const char *key, const char *value) {
32 int r;
33
34 assert(device);
35 assert(key);
36
37 r = device_add_property_aux(device, key, value, false);
38 if (r < 0)
39 return r;
40
41 if (key[0] != '.') {
42 r = device_add_property_aux(device, key, value, true);
43 if (r < 0)
44 return r;
45 }
46
47 return 0;
48 }
49
device_add_propertyf(sd_device * device,const char * key,const char * format,...)50 int device_add_propertyf(sd_device *device, const char *key, const char *format, ...) {
51 _cleanup_free_ char *value = NULL;
52 va_list ap;
53 int r;
54
55 assert(device);
56 assert(key);
57
58 if (!format)
59 return device_add_property(device, key, NULL);
60
61 va_start(ap, format);
62 r = vasprintf(&value, format, ap);
63 va_end(ap);
64
65 if (r < 0)
66 return -ENOMEM;
67
68 return device_add_property(device, key, value);
69 }
70
device_set_devlink_priority(sd_device * device,int priority)71 void device_set_devlink_priority(sd_device *device, int priority) {
72 assert(device);
73
74 device->devlink_priority = priority;
75 }
76
device_set_is_initialized(sd_device * device)77 void device_set_is_initialized(sd_device *device) {
78 assert(device);
79
80 device->is_initialized = true;
81 }
82
device_ensure_usec_initialized(sd_device * device,sd_device * device_old)83 int device_ensure_usec_initialized(sd_device *device, sd_device *device_old) {
84 usec_t when;
85
86 assert(device);
87
88 if (device_old && device_old->usec_initialized > 0)
89 when = device_old->usec_initialized;
90 else
91 when = now(CLOCK_MONOTONIC);
92
93 return device_set_usec_initialized(device, when);
94 }
95
device_get_properties_generation(sd_device * device)96 uint64_t device_get_properties_generation(sd_device *device) {
97 assert(device);
98
99 return device->properties_generation;
100 }
101
device_get_tags_generation(sd_device * device)102 uint64_t device_get_tags_generation(sd_device *device) {
103 assert(device);
104
105 return device->tags_generation;
106 }
107
device_get_devlinks_generation(sd_device * device)108 uint64_t device_get_devlinks_generation(sd_device *device) {
109 assert(device);
110
111 return device->devlinks_generation;
112 }
113
device_get_devnode_mode(sd_device * device,mode_t * ret)114 int device_get_devnode_mode(sd_device *device, mode_t *ret) {
115 int r;
116
117 assert(device);
118
119 r = device_read_db(device);
120 if (r < 0)
121 return r;
122
123 if (device->devmode == MODE_INVALID)
124 return -ENOENT;
125
126 if (ret)
127 *ret = device->devmode;
128
129 return 0;
130 }
131
device_get_devnode_uid(sd_device * device,uid_t * ret)132 int device_get_devnode_uid(sd_device *device, uid_t *ret) {
133 int r;
134
135 assert(device);
136
137 r = device_read_db(device);
138 if (r < 0)
139 return r;
140
141 if (device->devuid == UID_INVALID)
142 return -ENOENT;
143
144 if (ret)
145 *ret = device->devuid;
146
147 return 0;
148 }
149
device_set_devuid(sd_device * device,const char * uid)150 static int device_set_devuid(sd_device *device, const char *uid) {
151 uid_t u;
152 int r;
153
154 assert(device);
155 assert(uid);
156
157 r = parse_uid(uid, &u);
158 if (r < 0)
159 return r;
160
161 r = device_add_property_internal(device, "DEVUID", uid);
162 if (r < 0)
163 return r;
164
165 device->devuid = u;
166
167 return 0;
168 }
169
device_get_devnode_gid(sd_device * device,gid_t * ret)170 int device_get_devnode_gid(sd_device *device, gid_t *ret) {
171 int r;
172
173 assert(device);
174
175 r = device_read_db(device);
176 if (r < 0)
177 return r;
178
179 if (device->devgid == GID_INVALID)
180 return -ENOENT;
181
182 if (ret)
183 *ret = device->devgid;
184
185 return 0;
186 }
187
device_set_devgid(sd_device * device,const char * gid)188 static int device_set_devgid(sd_device *device, const char *gid) {
189 gid_t g;
190 int r;
191
192 assert(device);
193 assert(gid);
194
195 r = parse_gid(gid, &g);
196 if (r < 0)
197 return r;
198
199 r = device_add_property_internal(device, "DEVGID", gid);
200 if (r < 0)
201 return r;
202
203 device->devgid = g;
204
205 return 0;
206 }
207
device_set_action(sd_device * device,sd_device_action_t a)208 int device_set_action(sd_device *device, sd_device_action_t a) {
209 int r;
210
211 assert(device);
212 assert(a >= 0 && a < _SD_DEVICE_ACTION_MAX);
213
214 r = device_add_property_internal(device, "ACTION", device_action_to_string(a));
215 if (r < 0)
216 return r;
217
218 device->action = a;
219
220 return 0;
221 }
222
device_set_action_from_string(sd_device * device,const char * action)223 static int device_set_action_from_string(sd_device *device, const char *action) {
224 sd_device_action_t a;
225
226 assert(device);
227 assert(action);
228
229 a = device_action_from_string(action);
230 if (a < 0)
231 return a;
232
233 return device_set_action(device, a);
234 }
235
device_set_seqnum(sd_device * device,const char * str)236 static int device_set_seqnum(sd_device *device, const char *str) {
237 uint64_t seqnum;
238 int r;
239
240 assert(device);
241 assert(str);
242
243 r = safe_atou64(str, &seqnum);
244 if (r < 0)
245 return r;
246 if (seqnum == 0)
247 return -EINVAL;
248
249 r = device_add_property_internal(device, "SEQNUM", str);
250 if (r < 0)
251 return r;
252
253 device->seqnum = seqnum;
254
255 return 0;
256 }
257
device_amend(sd_device * device,const char * key,const char * value)258 static int device_amend(sd_device *device, const char *key, const char *value) {
259 int r;
260
261 assert(device);
262 assert(key);
263 assert(value);
264
265 if (streq(key, "DEVPATH")) {
266 char *path;
267
268 path = strjoina("/sys", value);
269
270 /* the caller must verify or trust this data (e.g., if it comes from the kernel) */
271 r = device_set_syspath(device, path, false);
272 if (r < 0)
273 return log_device_debug_errno(device, r, "sd-device: Failed to set syspath to '%s': %m", path);
274 } else if (streq(key, "SUBSYSTEM")) {
275 r = device_set_subsystem(device, value);
276 if (r < 0)
277 return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem to '%s': %m", value);
278 } else if (streq(key, "DEVTYPE")) {
279 r = device_set_devtype(device, value);
280 if (r < 0)
281 return log_device_debug_errno(device, r, "sd-device: Failed to set devtype to '%s': %m", value);
282 } else if (streq(key, "DEVNAME")) {
283 r = device_set_devname(device, value);
284 if (r < 0)
285 return log_device_debug_errno(device, r, "sd-device: Failed to set devname to '%s': %m", value);
286 } else if (streq(key, "USEC_INITIALIZED")) {
287 usec_t t;
288
289 r = safe_atou64(value, &t);
290 if (r < 0)
291 return log_device_debug_errno(device, r, "sd-device: Failed to parse timestamp '%s': %m", value);
292
293 r = device_set_usec_initialized(device, t);
294 if (r < 0)
295 return log_device_debug_errno(device, r, "sd-device: Failed to set usec-initialized to '%s': %m", value);
296 } else if (streq(key, "DRIVER")) {
297 r = device_set_driver(device, value);
298 if (r < 0)
299 return log_device_debug_errno(device, r, "sd-device: Failed to set driver to '%s': %m", value);
300 } else if (streq(key, "IFINDEX")) {
301 r = device_set_ifindex(device, value);
302 if (r < 0)
303 return log_device_debug_errno(device, r, "sd-device: Failed to set ifindex to '%s': %m", value);
304 } else if (streq(key, "DEVMODE")) {
305 r = device_set_devmode(device, value);
306 if (r < 0)
307 return log_device_debug_errno(device, r, "sd-device: Failed to set devmode to '%s': %m", value);
308 } else if (streq(key, "DEVUID")) {
309 r = device_set_devuid(device, value);
310 if (r < 0)
311 return log_device_debug_errno(device, r, "sd-device: Failed to set devuid to '%s': %m", value);
312 } else if (streq(key, "DEVGID")) {
313 r = device_set_devgid(device, value);
314 if (r < 0)
315 return log_device_debug_errno(device, r, "sd-device: Failed to set devgid to '%s': %m", value);
316 } else if (streq(key, "ACTION")) {
317 r = device_set_action_from_string(device, value);
318 if (r < 0)
319 return log_device_debug_errno(device, r, "sd-device: Failed to set action to '%s': %m", value);
320 } else if (streq(key, "SEQNUM")) {
321 r = device_set_seqnum(device, value);
322 if (r < 0)
323 return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value);
324 } else if (streq(key, "DISKSEQ")) {
325 r = device_set_diskseq(device, value);
326 if (r < 0)
327 return log_device_debug_errno(device, r, "sd-device: Failed to set DISKSEQ to '%s': %m", value);
328 } else if (streq(key, "DEVLINKS")) {
329 for (const char *p = value;;) {
330 _cleanup_free_ char *word = NULL;
331
332 /* udev rules may set escaped strings, and sd-device does not modify the input
333 * strings. So, it is also necessary to keep the strings received through
334 * sd-device-monitor. */
335 r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
336 if (r < 0)
337 return r;
338 if (r == 0)
339 break;
340
341 r = device_add_devlink(device, word);
342 if (r < 0)
343 return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", word);
344 }
345 } else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) {
346 for (const char *p = value;;) {
347 _cleanup_free_ char *word = NULL;
348
349 r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
350 if (r < 0)
351 return r;
352 if (r == 0)
353 break;
354
355 r = device_add_tag(device, word, streq(key, "CURRENT_TAGS"));
356 if (r < 0)
357 return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", word);
358 }
359 } else {
360 r = device_add_property_internal(device, key, value);
361 if (r < 0)
362 return log_device_debug_errno(device, r, "sd-device: Failed to add property '%s=%s': %m", key, value);
363 }
364
365 return 0;
366 }
367
device_append(sd_device * device,char * key,const char ** _major,const char ** _minor)368 static int device_append(
369 sd_device *device,
370 char *key,
371 const char **_major,
372 const char **_minor) {
373
374 const char *major = NULL, *minor = NULL;
375 char *value;
376 int r;
377
378 assert(device);
379 assert(key);
380 assert(_major);
381 assert(_minor);
382
383 value = strchr(key, '=');
384 if (!value)
385 return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
386 "sd-device: Not a key-value pair: '%s'", key);
387
388 *value = '\0';
389
390 value++;
391
392 if (streq(key, "MAJOR"))
393 major = value;
394 else if (streq(key, "MINOR"))
395 minor = value;
396 else {
397 r = device_amend(device, key, value);
398 if (r < 0)
399 return r;
400 }
401
402 if (major)
403 *_major = major;
404
405 if (minor)
406 *_minor = minor;
407
408 return 0;
409 }
410
device_seal(sd_device * device)411 void device_seal(sd_device *device) {
412 assert(device);
413
414 device->sealed = true;
415 }
416
device_verify(sd_device * device)417 static int device_verify(sd_device *device) {
418 int r;
419
420 assert(device);
421
422 if (!device->devpath || !device->subsystem || device->action < 0 || device->seqnum == 0)
423 return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
424 "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum.");
425
426 if (streq(device->subsystem, "drivers")) {
427 r = device_set_drivers_subsystem(device);
428 if (r < 0)
429 return r;
430 }
431
432 device->sealed = true;
433
434 return 0;
435 }
436
device_new_from_strv(sd_device ** ret,char ** strv)437 int device_new_from_strv(sd_device **ret, char **strv) {
438 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
439 const char *major = NULL, *minor = NULL;
440 int r;
441
442 assert(ret);
443 assert(strv);
444
445 r = device_new_aux(&device);
446 if (r < 0)
447 return r;
448
449 STRV_FOREACH(key, strv) {
450 r = device_append(device, *key, &major, &minor);
451 if (r < 0)
452 return r;
453 }
454
455 if (major) {
456 r = device_set_devnum(device, major, minor);
457 if (r < 0)
458 return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
459 }
460
461 r = device_verify(device);
462 if (r < 0)
463 return r;
464
465 *ret = TAKE_PTR(device);
466
467 return 0;
468 }
469
device_new_from_nulstr(sd_device ** ret,uint8_t * nulstr,size_t len)470 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
471 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
472 const char *major = NULL, *minor = NULL;
473 int r;
474
475 assert(ret);
476 assert(nulstr);
477 assert(len);
478
479 r = device_new_aux(&device);
480 if (r < 0)
481 return r;
482
483 for (size_t i = 0; i < len; ) {
484 char *key;
485 const char *end;
486
487 key = (char*) &nulstr[i];
488 end = memchr(key, '\0', len - i);
489 if (!end)
490 return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
491 "sd-device: Failed to parse nulstr");
492
493 i += end - key + 1;
494
495 /* netlink messages for some devices contain an unwanted newline at the end of value.
496 * Let's drop the newline and remaining characters after the newline. */
497 truncate_nl(key);
498
499 r = device_append(device, key, &major, &minor);
500 if (r < 0)
501 return r;
502 }
503
504 if (major) {
505 r = device_set_devnum(device, major, minor);
506 if (r < 0)
507 return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
508 }
509
510 r = device_verify(device);
511 if (r < 0)
512 return r;
513
514 *ret = TAKE_PTR(device);
515
516 return 0;
517 }
518
device_update_properties_bufs(sd_device * device)519 static int device_update_properties_bufs(sd_device *device) {
520 const char *val, *prop;
521 _cleanup_free_ char **buf_strv = NULL;
522 _cleanup_free_ uint8_t *buf_nulstr = NULL;
523 size_t nulstr_len = 0, num = 0, i = 0;
524
525 assert(device);
526
527 if (!device->properties_buf_outdated)
528 return 0;
529
530 FOREACH_DEVICE_PROPERTY(device, prop, val) {
531 size_t len = 0;
532
533 len = strlen(prop) + 1 + strlen(val);
534
535 buf_nulstr = GREEDY_REALLOC0(buf_nulstr, nulstr_len + len + 2);
536 if (!buf_nulstr)
537 return -ENOMEM;
538
539 strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL);
540 nulstr_len += len + 1;
541 ++num;
542 }
543
544 /* build buf_strv from buf_nulstr */
545 buf_strv = new0(char *, num + 1);
546 if (!buf_strv)
547 return -ENOMEM;
548
549 NULSTR_FOREACH(val, (char*) buf_nulstr) {
550 buf_strv[i] = (char *) val;
551 assert(i < num);
552 i++;
553 }
554
555 free_and_replace(device->properties_nulstr, buf_nulstr);
556 device->properties_nulstr_len = nulstr_len;
557 free_and_replace(device->properties_strv, buf_strv);
558
559 device->properties_buf_outdated = false;
560
561 return 0;
562 }
563
device_get_properties_nulstr(sd_device * device,const uint8_t ** nulstr,size_t * len)564 int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) {
565 int r;
566
567 assert(device);
568 assert(nulstr);
569 assert(len);
570
571 r = device_update_properties_bufs(device);
572 if (r < 0)
573 return r;
574
575 *nulstr = device->properties_nulstr;
576 *len = device->properties_nulstr_len;
577
578 return 0;
579 }
580
device_get_properties_strv(sd_device * device,char *** strv)581 int device_get_properties_strv(sd_device *device, char ***strv) {
582 int r;
583
584 assert(device);
585 assert(strv);
586
587 r = device_update_properties_bufs(device);
588 if (r < 0)
589 return r;
590
591 *strv = device->properties_strv;
592
593 return 0;
594 }
595
device_get_devlink_priority(sd_device * device,int * ret)596 int device_get_devlink_priority(sd_device *device, int *ret) {
597 int r;
598
599 assert(device);
600
601 r = device_read_db(device);
602 if (r < 0)
603 return r;
604
605 if (ret)
606 *ret = device->devlink_priority;
607
608 return 0;
609 }
610
device_get_watch_handle(sd_device * device)611 int device_get_watch_handle(sd_device *device) {
612 char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
613 _cleanup_free_ char *buf = NULL;
614 const char *id, *path_id;
615 int wd, r;
616
617 assert(device);
618
619 if (device->watch_handle >= 0)
620 return device->watch_handle;
621
622 r = device_get_device_id(device, &id);
623 if (r < 0)
624 return r;
625
626 path_id = strjoina("/run/udev/watch/", id);
627 r = readlink_malloc(path_id, &buf);
628 if (r < 0)
629 return r;
630
631 r = safe_atoi(buf, &wd);
632 if (r < 0)
633 return r;
634
635 if (wd < 0)
636 return -EBADF;
637
638 buf = mfree(buf);
639 xsprintf(path_wd, "/run/udev/watch/%d", wd);
640 r = readlink_malloc(path_wd, &buf);
641 if (r < 0)
642 return r;
643
644 if (!streq(buf, id))
645 return -EBADF;
646
647 return device->watch_handle = wd;
648 }
649
device_remove_watch_handle(sd_device * device)650 static void device_remove_watch_handle(sd_device *device) {
651 const char *id;
652 int wd;
653
654 assert(device);
655
656 /* First, remove the symlink from handle to device id. */
657 wd = device_get_watch_handle(device);
658 if (wd >= 0) {
659 char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
660
661 xsprintf(path_wd, "/run/udev/watch/%d", wd);
662 if (unlink(path_wd) < 0 && errno != ENOENT)
663 log_device_debug_errno(device, errno,
664 "sd-device: failed to remove %s, ignoring: %m",
665 path_wd);
666 }
667
668 /* Next, remove the symlink from device id to handle. */
669 if (device_get_device_id(device, &id) >= 0) {
670 const char *path_id;
671
672 path_id = strjoina("/run/udev/watch/", id);
673 if (unlink(path_id) < 0 && errno != ENOENT)
674 log_device_debug_errno(device, errno,
675 "sd-device: failed to remove %s, ignoring: %m",
676 path_id);
677 }
678
679 device->watch_handle = -1;
680 }
681
device_set_watch_handle(sd_device * device,int wd)682 int device_set_watch_handle(sd_device *device, int wd) {
683 char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
684 const char *id, *path_id;
685 int r;
686
687 assert(device);
688
689 if (wd >= 0 && wd == device_get_watch_handle(device))
690 return 0;
691
692 device_remove_watch_handle(device);
693
694 if (wd < 0)
695 /* negative wd means that the caller requests to clear saved watch handle. */
696 return 0;
697
698 r = device_get_device_id(device, &id);
699 if (r < 0)
700 return r;
701
702 path_id = strjoina("/run/udev/watch/", id);
703 xsprintf(path_wd, "/run/udev/watch/%d", wd);
704
705 r = mkdir_parents(path_wd, 0755);
706 if (r < 0)
707 return r;
708
709 if (symlink(id, path_wd) < 0)
710 return -errno;
711
712 if (symlink(path_wd + STRLEN("/run/udev/watch/"), path_id) < 0) {
713 r = -errno;
714 if (unlink(path_wd) < 0 && errno != ENOENT)
715 log_device_debug_errno(device, errno,
716 "sd-device: failed to remove %s, ignoring: %m",
717 path_wd);
718 return r;
719 }
720
721 device->watch_handle = wd;
722
723 return 0;
724 }
725
device_new_from_watch_handle_at(sd_device ** ret,int dirfd,int wd)726 int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd) {
727 char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
728 _cleanup_free_ char *id = NULL;
729 int r;
730
731 assert(ret);
732
733 if (wd < 0)
734 return -EBADF;
735
736 if (dirfd >= 0) {
737 xsprintf(path_wd, "%d", wd);
738 r = readlinkat_malloc(dirfd, path_wd, &id);
739 } else {
740 xsprintf(path_wd, "/run/udev/watch/%d", wd);
741 r = readlink_malloc(path_wd, &id);
742 }
743 if (r < 0)
744 return r;
745
746 return sd_device_new_from_device_id(ret, id);
747 }
748
device_rename(sd_device * device,const char * name)749 int device_rename(sd_device *device, const char *name) {
750 _cleanup_free_ char *new_syspath = NULL;
751 const char *interface;
752 int r;
753
754 assert(device);
755 assert(name);
756
757 if (!filename_is_valid(name))
758 return -EINVAL;
759
760 r = path_extract_directory(device->syspath, &new_syspath);
761 if (r < 0)
762 return r;
763
764 if (!path_extend(&new_syspath, name))
765 return -ENOMEM;
766
767 if (!path_is_safe(new_syspath))
768 return -EINVAL;
769
770 /* At the time this is called, the renamed device may not exist yet. Hence, we cannot validate
771 * the new syspath. */
772 r = device_set_syspath(device, new_syspath, false);
773 if (r < 0)
774 return r;
775
776 /* Here, only clear the sysname and sysnum. They will be set when requested. */
777 device->sysnum = NULL;
778 device->sysname = mfree(device->sysname);
779
780 r = sd_device_get_property_value(device, "INTERFACE", &interface);
781 if (r == -ENOENT)
782 return 0;
783 if (r < 0)
784 return r;
785
786 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
787 r = device_add_property_internal(device, "INTERFACE_OLD", interface);
788 if (r < 0)
789 return r;
790
791 return device_add_property_internal(device, "INTERFACE", name);
792 }
793
device_shallow_clone(sd_device * device,sd_device ** ret)794 int device_shallow_clone(sd_device *device, sd_device **ret) {
795 _cleanup_(sd_device_unrefp) sd_device *dest = NULL;
796 const char *val = NULL;
797 int r;
798
799 assert(device);
800 assert(ret);
801
802 r = device_new_aux(&dest);
803 if (r < 0)
804 return r;
805
806 r = device_set_syspath(dest, device->syspath, false);
807 if (r < 0)
808 return r;
809
810 (void) sd_device_get_subsystem(device, &val);
811 r = device_set_subsystem(dest, val);
812 if (r < 0)
813 return r;
814 if (streq_ptr(val, "drivers")) {
815 r = free_and_strdup(&dest->driver_subsystem, device->driver_subsystem);
816 if (r < 0)
817 return r;
818 }
819
820 /* The device may be already removed. Let's copy minimal set of information to make
821 * device_get_device_id() work without uevent file. */
822
823 if (sd_device_get_property_value(device, "IFINDEX", &val) >= 0) {
824 r = device_set_ifindex(dest, val);
825 if (r < 0)
826 return r;
827 }
828
829 if (sd_device_get_property_value(device, "MAJOR", &val) >= 0) {
830 const char *minor = NULL;
831
832 (void) sd_device_get_property_value(device, "MINOR", &minor);
833 r = device_set_devnum(dest, val, minor);
834 if (r < 0)
835 return r;
836 }
837
838 r = device_read_uevent_file(dest);
839 if (r < 0)
840 return r;
841
842 *ret = TAKE_PTR(dest);
843 return 0;
844 }
845
device_clone_with_db(sd_device * device,sd_device ** ret)846 int device_clone_with_db(sd_device *device, sd_device **ret) {
847 _cleanup_(sd_device_unrefp) sd_device *dest = NULL;
848 int r;
849
850 assert(device);
851 assert(ret);
852
853 r = device_shallow_clone(device, &dest);
854 if (r < 0)
855 return r;
856
857 r = device_read_db(dest);
858 if (r < 0)
859 return r;
860
861 dest->sealed = true;
862
863 *ret = TAKE_PTR(dest);
864 return 0;
865 }
866
device_copy_properties(sd_device * device_dst,sd_device * device_src)867 int device_copy_properties(sd_device *device_dst, sd_device *device_src) {
868 const char *property, *value;
869 int r;
870
871 assert(device_dst);
872 assert(device_src);
873
874 r = device_properties_prepare(device_src);
875 if (r < 0)
876 return r;
877
878 ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties_db) {
879 r = device_add_property_aux(device_dst, property, value, true);
880 if (r < 0)
881 return r;
882 }
883
884 ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties) {
885 r = device_add_property_aux(device_dst, property, value, false);
886 if (r < 0)
887 return r;
888 }
889
890 return 0;
891 }
892
device_cleanup_tags(sd_device * device)893 void device_cleanup_tags(sd_device *device) {
894 assert(device);
895
896 device->all_tags = set_free_free(device->all_tags);
897 device->current_tags = set_free_free(device->current_tags);
898 device->property_tags_outdated = true;
899 device->tags_generation++;
900 }
901
device_cleanup_devlinks(sd_device * device)902 void device_cleanup_devlinks(sd_device *device) {
903 assert(device);
904
905 set_free_free(device->devlinks);
906 device->devlinks = NULL;
907 device->property_devlinks_outdated = true;
908 device->devlinks_generation++;
909 }
910
device_remove_tag(sd_device * device,const char * tag)911 void device_remove_tag(sd_device *device, const char *tag) {
912 assert(device);
913 assert(tag);
914
915 free(set_remove(device->current_tags, tag));
916 device->property_tags_outdated = true;
917 device->tags_generation++;
918 }
919
device_tag(sd_device * device,const char * tag,bool add)920 static int device_tag(sd_device *device, const char *tag, bool add) {
921 const char *id;
922 char *path;
923 int r;
924
925 assert(device);
926 assert(tag);
927
928 r = device_get_device_id(device, &id);
929 if (r < 0)
930 return r;
931
932 path = strjoina("/run/udev/tags/", tag, "/", id);
933
934 if (add)
935 return touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
936
937 if (unlink(path) < 0 && errno != ENOENT)
938 return -errno;
939
940 return 0;
941 }
942
device_tag_index(sd_device * device,sd_device * device_old,bool add)943 int device_tag_index(sd_device *device, sd_device *device_old, bool add) {
944 const char *tag;
945 int r = 0, k;
946
947 if (add && device_old)
948 /* delete possible left-over tags */
949 FOREACH_DEVICE_TAG(device_old, tag)
950 if (!sd_device_has_tag(device, tag)) {
951 k = device_tag(device_old, tag, false);
952 if (r >= 0 && k < 0)
953 r = k;
954 }
955
956 FOREACH_DEVICE_TAG(device, tag) {
957 k = device_tag(device, tag, add);
958 if (r >= 0 && k < 0)
959 r = k;
960 }
961
962 return r;
963 }
964
device_has_info(sd_device * device)965 static bool device_has_info(sd_device *device) {
966 assert(device);
967
968 if (!set_isempty(device->devlinks))
969 return true;
970
971 if (device->devlink_priority != 0)
972 return true;
973
974 if (!ordered_hashmap_isempty(device->properties_db))
975 return true;
976
977 if (!set_isempty(device->all_tags))
978 return true;
979
980 if (!set_isempty(device->current_tags))
981 return true;
982
983 return false;
984 }
985
device_set_db_persist(sd_device * device)986 void device_set_db_persist(sd_device *device) {
987 assert(device);
988
989 device->db_persist = true;
990 }
991
device_update_db(sd_device * device)992 int device_update_db(sd_device *device) {
993 const char *id;
994 char *path;
995 _cleanup_fclose_ FILE *f = NULL;
996 _cleanup_free_ char *path_tmp = NULL;
997 bool has_info;
998 int r;
999
1000 assert(device);
1001
1002 has_info = device_has_info(device);
1003
1004 r = device_get_device_id(device, &id);
1005 if (r < 0)
1006 return r;
1007
1008 path = strjoina("/run/udev/data/", id);
1009
1010 /* do not store anything for otherwise empty devices */
1011 if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) {
1012 if (unlink(path) < 0 && errno != ENOENT)
1013 return -errno;
1014
1015 return 0;
1016 }
1017
1018 /* write a database file */
1019 r = mkdir_parents(path, 0755);
1020 if (r < 0)
1021 return r;
1022
1023 r = fopen_temporary(path, &f, &path_tmp);
1024 if (r < 0)
1025 return r;
1026
1027 /*
1028 * set 'sticky' bit to indicate that we should not clean the
1029 * database when we transition from initramfs to the real root
1030 */
1031 if (fchmod(fileno(f), device->db_persist ? 01644 : 0644) < 0) {
1032 r = -errno;
1033 goto fail;
1034 }
1035
1036 if (has_info) {
1037 const char *property, *value, *tag;
1038
1039 if (major(device->devnum) > 0) {
1040 const char *devlink;
1041
1042 FOREACH_DEVICE_DEVLINK(device, devlink)
1043 fprintf(f, "S:%s\n", devlink + STRLEN("/dev/"));
1044
1045 if (device->devlink_priority != 0)
1046 fprintf(f, "L:%i\n", device->devlink_priority);
1047 }
1048
1049 if (device->usec_initialized > 0)
1050 fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized);
1051
1052 ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db)
1053 fprintf(f, "E:%s=%s\n", property, value);
1054
1055 FOREACH_DEVICE_TAG(device, tag)
1056 fprintf(f, "G:%s\n", tag); /* Any tag */
1057
1058 SET_FOREACH(tag, device->current_tags)
1059 fprintf(f, "Q:%s\n", tag); /* Current tag */
1060
1061 /* Always write the latest database version here, instead of the value stored in
1062 * device->database_version, as which may be 0. */
1063 fputs("V:" STRINGIFY(LATEST_UDEV_DATABASE_VERSION) "\n", f);
1064 }
1065
1066 r = fflush_and_check(f);
1067 if (r < 0)
1068 goto fail;
1069
1070 if (rename(path_tmp, path) < 0) {
1071 r = -errno;
1072 goto fail;
1073 }
1074
1075 log_device_debug(device, "sd-device: Created %s file '%s' for '%s'", has_info ? "db" : "empty",
1076 path, device->devpath);
1077
1078 return 0;
1079
1080 fail:
1081 (void) unlink(path);
1082 (void) unlink(path_tmp);
1083
1084 return log_device_debug_errno(device, r, "sd-device: Failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath);
1085 }
1086
device_delete_db(sd_device * device)1087 int device_delete_db(sd_device *device) {
1088 const char *id;
1089 char *path;
1090 int r;
1091
1092 assert(device);
1093
1094 r = device_get_device_id(device, &id);
1095 if (r < 0)
1096 return r;
1097
1098 path = strjoina("/run/udev/data/", id);
1099
1100 if (unlink(path) < 0 && errno != ENOENT)
1101 return -errno;
1102
1103 return 0;
1104 }
1105
1106 static const char* const device_action_table[_SD_DEVICE_ACTION_MAX] = {
1107 [SD_DEVICE_ADD] = "add",
1108 [SD_DEVICE_REMOVE] = "remove",
1109 [SD_DEVICE_CHANGE] = "change",
1110 [SD_DEVICE_MOVE] = "move",
1111 [SD_DEVICE_ONLINE] = "online",
1112 [SD_DEVICE_OFFLINE] = "offline",
1113 [SD_DEVICE_BIND] = "bind",
1114 [SD_DEVICE_UNBIND] = "unbind",
1115 };
1116
1117 DEFINE_STRING_TABLE_LOOKUP(device_action, sd_device_action_t);
1118
dump_device_action_table(void)1119 void dump_device_action_table(void) {
1120 DUMP_STRING_TABLE(device_action, sd_device_action_t, _SD_DEVICE_ACTION_MAX);
1121 }
1122