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