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