]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-device/device-private.c
pkgconfig: define variables relative to ${prefix}/${rootprefix}/${sysconfdir}
[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_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", 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_device_debug_errno(device, 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_device_debug(device, "sd-device: Invalid db entry with key '%c', ignoring", 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_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %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
275 r = device_read_db(device);
276 if (r < 0)
277 return r;
278
279 if (device->devmode == (mode_t) -1)
280 return -ENOENT;
281
282 if (mode)
283 *mode = device->devmode;
284
285 return 0;
286 }
287
288 int device_get_devnode_uid(sd_device *device, uid_t *uid) {
289 int r;
290
291 assert(device);
292
293 r = device_read_db(device);
294 if (r < 0)
295 return r;
296
297 if (device->devuid == (uid_t) -1)
298 return -ENOENT;
299
300 if (uid)
301 *uid = device->devuid;
302
303 return 0;
304 }
305
306 static int device_set_devuid(sd_device *device, const char *uid) {
307 unsigned u;
308 int r;
309
310 assert(device);
311 assert(uid);
312
313 r = safe_atou(uid, &u);
314 if (r < 0)
315 return r;
316
317 r = device_add_property_internal(device, "DEVUID", uid);
318 if (r < 0)
319 return r;
320
321 device->devuid = u;
322
323 return 0;
324 }
325
326 int device_get_devnode_gid(sd_device *device, gid_t *gid) {
327 int r;
328
329 assert(device);
330
331 r = device_read_db(device);
332 if (r < 0)
333 return r;
334
335 if (device->devgid == (gid_t) -1)
336 return -ENOENT;
337
338 if (gid)
339 *gid = device->devgid;
340
341 return 0;
342 }
343
344 static int device_set_devgid(sd_device *device, const char *gid) {
345 unsigned g;
346 int r;
347
348 assert(device);
349 assert(gid);
350
351 r = safe_atou(gid, &g);
352 if (r < 0)
353 return r;
354
355 r = device_add_property_internal(device, "DEVGID", gid);
356 if (r < 0)
357 return r;
358
359 device->devgid = g;
360
361 return 0;
362 }
363
364 static int device_amend(sd_device *device, const char *key, const char *value) {
365 int r;
366
367 assert(device);
368 assert(key);
369 assert(value);
370
371 if (streq(key, "DEVPATH")) {
372 char *path;
373
374 path = strjoina("/sys", value);
375
376 /* the caller must verify or trust this data (e.g., if it comes from the kernel) */
377 r = device_set_syspath(device, path, false);
378 if (r < 0)
379 return log_device_debug_errno(device, r, "sd-device: Failed to set syspath to '%s': %m", path);
380 } else if (streq(key, "SUBSYSTEM")) {
381 r = device_set_subsystem(device, value);
382 if (r < 0)
383 return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem to '%s': %m", value);
384 } else if (streq(key, "DEVTYPE")) {
385 r = device_set_devtype(device, value);
386 if (r < 0)
387 return log_device_debug_errno(device, r, "sd-device: Failed to set devtype to '%s': %m", value);
388 } else if (streq(key, "DEVNAME")) {
389 r = device_set_devname(device, value);
390 if (r < 0)
391 return log_device_debug_errno(device, r, "sd-device: Failed to set devname to '%s': %m", value);
392 } else if (streq(key, "USEC_INITIALIZED")) {
393 r = device_set_usec_initialized(device, value);
394 if (r < 0)
395 return log_device_debug_errno(device, r, "sd-device: Failed to set usec-initialized to '%s': %m", value);
396 } else if (streq(key, "DRIVER")) {
397 r = device_set_driver(device, value);
398 if (r < 0)
399 return log_device_debug_errno(device, r, "sd-device: Failed to set driver to '%s': %m", value);
400 } else if (streq(key, "IFINDEX")) {
401 r = device_set_ifindex(device, value);
402 if (r < 0)
403 return log_device_debug_errno(device, r, "sd-device: Failed to set ifindex to '%s': %m", value);
404 } else if (streq(key, "DEVMODE")) {
405 r = device_set_devmode(device, value);
406 if (r < 0)
407 return log_device_debug_errno(device, r, "sd-device: Failed to set devmode to '%s': %m", value);
408 } else if (streq(key, "DEVUID")) {
409 r = device_set_devuid(device, value);
410 if (r < 0)
411 return log_device_debug_errno(device, r, "sd-device: Failed to set devuid to '%s': %m", value);
412 } else if (streq(key, "DEVGID")) {
413 r = device_set_devgid(device, value);
414 if (r < 0)
415 return log_device_debug_errno(device, r, "sd-device: Failed to set devgid to '%s': %m", value);
416 } else if (streq(key, "DEVLINKS")) {
417 const char *word, *state;
418 size_t l;
419
420 FOREACH_WORD(word, l, value, state) {
421 char devlink[l + 1];
422
423 strncpy(devlink, word, l);
424 devlink[l] = '\0';
425
426 r = device_add_devlink(device, devlink);
427 if (r < 0)
428 return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink);
429 }
430 } else if (streq(key, "TAGS")) {
431 const char *word, *state;
432 size_t l;
433
434 FOREACH_WORD_SEPARATOR(word, l, value, ":", state) {
435 char tag[l + 1];
436
437 (void) strncpy(tag, word, l);
438 tag[l] = '\0';
439
440 r = device_add_tag(device, tag);
441 if (r < 0)
442 return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", tag);
443 }
444 } else {
445 r = device_add_property_internal(device, key, value);
446 if (r < 0)
447 return log_device_debug_errno(device, r, "sd-device: Failed to add property '%s=%s': %m", key, value);
448 }
449
450 return 0;
451 }
452
453 static const char* const device_action_table[_DEVICE_ACTION_MAX] = {
454 [DEVICE_ACTION_ADD] = "add",
455 [DEVICE_ACTION_REMOVE] = "remove",
456 [DEVICE_ACTION_CHANGE] = "change",
457 [DEVICE_ACTION_MOVE] = "move",
458 [DEVICE_ACTION_ONLINE] = "online",
459 [DEVICE_ACTION_OFFLINE] = "offline",
460 [DEVICE_ACTION_BIND] = "bind",
461 [DEVICE_ACTION_UNBIND] = "unbind",
462 };
463
464 DEFINE_STRING_TABLE_LOOKUP(device_action, DeviceAction);
465
466 static int device_append(sd_device *device, char *key, const char **_major, const char **_minor, uint64_t *_seqnum,
467 DeviceAction *_action) {
468 DeviceAction action = _DEVICE_ACTION_INVALID;
469 uint64_t seqnum = 0;
470 const char *major = NULL, *minor = NULL;
471 char *value;
472 int r;
473
474 assert(device);
475 assert(key);
476 assert(_major);
477 assert(_minor);
478 assert(_seqnum);
479 assert(_action);
480
481 value = strchr(key, '=');
482 if (!value) {
483 log_device_debug(device, "sd-device: Not a key-value pair: '%s'", key);
484 return -EINVAL;
485 }
486
487 *value = '\0';
488
489 value++;
490
491 if (streq(key, "MAJOR"))
492 major = value;
493 else if (streq(key, "MINOR"))
494 minor = value;
495 else {
496 if (streq(key, "ACTION")) {
497 action = device_action_from_string(value);
498 if (action == _DEVICE_ACTION_INVALID)
499 return -EINVAL;
500 } else if (streq(key, "SEQNUM")) {
501 r = safe_atou64(value, &seqnum);
502 if (r < 0)
503 return r;
504 else if (seqnum == 0)
505 /* kernel only sends seqnum > 0 */
506 return -EINVAL;
507 }
508
509 r = device_amend(device, key, value);
510 if (r < 0)
511 return r;
512 }
513
514 if (major != 0)
515 *_major = major;
516
517 if (minor != 0)
518 *_minor = minor;
519
520 if (action != _DEVICE_ACTION_INVALID)
521 *_action = action;
522
523 if (seqnum > 0)
524 *_seqnum = seqnum;
525
526 return 0;
527 }
528
529 void device_seal(sd_device *device) {
530 assert(device);
531
532 device->sealed = true;
533 }
534
535 static int device_verify(sd_device *device, DeviceAction action, uint64_t seqnum) {
536 assert(device);
537
538 if (!device->devpath || !device->subsystem || action == _DEVICE_ACTION_INVALID || seqnum == 0) {
539 log_device_debug(device, "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum.");
540 return -EINVAL;
541 }
542
543 device->sealed = true;
544
545 return 0;
546 }
547
548 int device_new_from_strv(sd_device **ret, char **strv) {
549 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
550 char **key;
551 const char *major = NULL, *minor = NULL;
552 DeviceAction action = _DEVICE_ACTION_INVALID;
553 uint64_t seqnum = 0;
554 int r;
555
556 assert(ret);
557 assert(strv);
558
559 r = device_new_aux(&device);
560 if (r < 0)
561 return r;
562
563 STRV_FOREACH(key, strv) {
564 r = device_append(device, *key, &major, &minor, &seqnum, &action);
565 if (r < 0)
566 return r;
567 }
568
569 if (major) {
570 r = device_set_devnum(device, major, minor);
571 if (r < 0)
572 return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
573 }
574
575 r = device_verify(device, action, seqnum);
576 if (r < 0)
577 return r;
578
579 *ret = TAKE_PTR(device);
580
581 return 0;
582 }
583
584 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
585 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
586 const char *major = NULL, *minor = NULL;
587 DeviceAction action = _DEVICE_ACTION_INVALID;
588 uint64_t seqnum = 0;
589 unsigned i = 0;
590 int r;
591
592 assert(ret);
593 assert(nulstr);
594 assert(len);
595
596 r = device_new_aux(&device);
597 if (r < 0)
598 return r;
599
600 while (i < len) {
601 char *key;
602 const char *end;
603
604 key = (char*)&nulstr[i];
605 end = memchr(key, '\0', len - i);
606 if (!end) {
607 log_device_debug(device, "sd-device: Failed to parse nulstr");
608 return -EINVAL;
609 }
610 i += end - key + 1;
611
612 r = device_append(device, key, &major, &minor, &seqnum, &action);
613 if (r < 0)
614 return r;
615 }
616
617 if (major) {
618 r = device_set_devnum(device, major, minor);
619 if (r < 0)
620 return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
621 }
622
623 r = device_verify(device, action, seqnum);
624 if (r < 0)
625 return r;
626
627 *ret = TAKE_PTR(device);
628
629 return 0;
630 }
631
632 static int device_update_properties_bufs(sd_device *device) {
633 const char *val, *prop;
634 _cleanup_free_ char **buf_strv = NULL;
635 _cleanup_free_ uint8_t *buf_nulstr = NULL;
636 size_t allocated_nulstr = 0;
637 size_t nulstr_len = 0, num = 0, i = 0;
638
639 assert(device);
640
641 if (!device->properties_buf_outdated)
642 return 0;
643
644 FOREACH_DEVICE_PROPERTY(device, prop, val) {
645 size_t len = 0;
646
647 len = strlen(prop) + 1 + strlen(val);
648
649 buf_nulstr = GREEDY_REALLOC0(buf_nulstr, allocated_nulstr, nulstr_len + len + 2);
650 if (!buf_nulstr)
651 return -ENOMEM;
652
653 strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL);
654 nulstr_len += len + 1;
655 ++num;
656 }
657
658 /* build buf_strv from buf_nulstr */
659 buf_strv = new0(char *, num + 1);
660 if (!buf_strv)
661 return -ENOMEM;
662
663 NULSTR_FOREACH(val, (char*) buf_nulstr) {
664 buf_strv[i] = (char *) val;
665 assert(i < num);
666 i++;
667 }
668
669 free_and_replace(device->properties_nulstr, buf_nulstr);
670 device->properties_nulstr_len = nulstr_len;
671 free_and_replace(device->properties_strv, buf_strv);
672
673 device->properties_buf_outdated = false;
674
675 return 0;
676 }
677
678 int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) {
679 int r;
680
681 assert(device);
682 assert(nulstr);
683 assert(len);
684
685 r = device_update_properties_bufs(device);
686 if (r < 0)
687 return r;
688
689 *nulstr = device->properties_nulstr;
690 *len = device->properties_nulstr_len;
691
692 return 0;
693 }
694
695 int device_get_properties_strv(sd_device *device, char ***strv) {
696 int r;
697
698 assert(device);
699 assert(strv);
700
701 r = device_update_properties_bufs(device);
702 if (r < 0)
703 return r;
704
705 *strv = device->properties_strv;
706
707 return 0;
708 }
709
710 int device_get_devlink_priority(sd_device *device, int *priority) {
711 int r;
712
713 assert(device);
714 assert(priority);
715
716 r = device_read_db(device);
717 if (r < 0)
718 return r;
719
720 *priority = device->devlink_priority;
721
722 return 0;
723 }
724
725 int device_get_watch_handle(sd_device *device, int *handle) {
726 int r;
727
728 assert(device);
729
730 r = device_read_db(device);
731 if (r < 0)
732 return r;
733
734 if (device->watch_handle < 0)
735 return -ENOENT;
736
737 if (handle)
738 *handle = device->watch_handle;
739
740 return 0;
741 }
742
743 void device_set_watch_handle(sd_device *device, int handle) {
744 assert(device);
745
746 device->watch_handle = handle;
747 }
748
749 int device_rename(sd_device *device, const char *name) {
750 _cleanup_free_ char *dirname = NULL;
751 char *new_syspath;
752 const char *interface;
753 int r;
754
755 assert(device);
756 assert(name);
757
758 dirname = dirname_malloc(device->syspath);
759 if (!dirname)
760 return -ENOMEM;
761
762 new_syspath = strjoina(dirname, "/", name);
763
764 /* the user must trust that the new name is correct */
765 r = device_set_syspath(device, new_syspath, false);
766 if (r < 0)
767 return r;
768
769 r = sd_device_get_property_value(device, "INTERFACE", &interface);
770 if (r >= 0) {
771 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
772 r = device_add_property_internal(device, "INTERFACE_OLD", interface);
773 if (r < 0)
774 return r;
775
776 r = device_add_property_internal(device, "INTERFACE", name);
777 if (r < 0)
778 return r;
779 } else if (r != -ENOENT)
780 return r;
781
782 return 0;
783 }
784
785 int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
786 _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
787 int r;
788
789 assert(old_device);
790 assert(new_device);
791
792 r = device_new_aux(&ret);
793 if (r < 0)
794 return r;
795
796 r = device_set_syspath(ret, old_device->syspath, false);
797 if (r < 0)
798 return r;
799
800 r = device_set_subsystem(ret, old_device->subsystem);
801 if (r < 0)
802 return r;
803
804 ret->devnum = old_device->devnum;
805
806 *new_device = TAKE_PTR(ret);
807
808 return 0;
809 }
810
811 int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
812 _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
813 int r;
814
815 assert(old_device);
816 assert(new_device);
817
818 r = device_shallow_clone(old_device, &ret);
819 if (r < 0)
820 return r;
821
822 r = device_read_db(ret);
823 if (r < 0)
824 return r;
825
826 ret->sealed = true;
827
828 *new_device = TAKE_PTR(ret);
829
830 return 0;
831 }
832
833 int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
834 _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
835 int r;
836
837 assert(new_device);
838 assert(syspath);
839 assert(action);
840
841 r = sd_device_new_from_syspath(&ret, syspath);
842 if (r < 0)
843 return r;
844
845 r = device_read_uevent_file(ret);
846 if (r < 0)
847 return r;
848
849 r = device_add_property_internal(ret, "ACTION", action);
850 if (r < 0)
851 return r;
852
853 *new_device = TAKE_PTR(ret);
854
855 return 0;
856 }
857
858 int device_new_from_stat_rdev(sd_device **ret, const struct stat *st) {
859 char type;
860
861 assert(ret);
862 assert(st);
863
864 if (S_ISBLK(st->st_mode))
865 type = 'b';
866 else if (S_ISCHR(st->st_mode))
867 type = 'c';
868 else
869 return -ENOTTY;
870
871 return sd_device_new_from_devnum(ret, type, st->st_rdev);
872 }
873
874 int device_copy_properties(sd_device *device_dst, sd_device *device_src) {
875 const char *property, *value;
876 int r;
877
878 assert(device_dst);
879 assert(device_src);
880
881 FOREACH_DEVICE_PROPERTY(device_src, property, value) {
882 r = device_add_property(device_dst, property, value);
883 if (r < 0)
884 return r;
885 }
886
887 return 0;
888 }
889
890 void device_cleanup_tags(sd_device *device) {
891 assert(device);
892
893 set_free_free(device->tags);
894 device->tags = NULL;
895 device->property_tags_outdated = true;
896 device->tags_generation++;
897 }
898
899 void device_cleanup_devlinks(sd_device *device) {
900 assert(device);
901
902 set_free_free(device->devlinks);
903 device->devlinks = NULL;
904 device->property_devlinks_outdated = true;
905 device->devlinks_generation++;
906 }
907
908 void device_remove_tag(sd_device *device, const char *tag) {
909 assert(device);
910 assert(tag);
911
912 free(set_remove(device->tags, tag));
913 device->property_tags_outdated = true;
914 device->tags_generation++;
915 }
916
917 static int device_tag(sd_device *device, const char *tag, bool add) {
918 const char *id;
919 char *path;
920 int r;
921
922 assert(device);
923 assert(tag);
924
925 r = device_get_id_filename(device, &id);
926 if (r < 0)
927 return r;
928
929 path = strjoina("/run/udev/tags/", tag, "/", id);
930
931 if (add) {
932 r = touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
933 if (r < 0)
934 return r;
935 } else {
936 r = unlink(path);
937 if (r < 0 && errno != ENOENT)
938 return -errno;
939 }
940
941 return 0;
942 }
943
944 int device_tag_index(sd_device *device, sd_device *device_old, bool add) {
945 const char *tag;
946 int r = 0, k;
947
948 if (add && device_old) {
949 /* delete possible left-over tags */
950 FOREACH_DEVICE_TAG(device_old, tag) {
951 if (!sd_device_has_tag(device, tag)) {
952 k = device_tag(device_old, tag, false);
953 if (r >= 0 && k < 0)
954 r = k;
955 }
956 }
957 }
958
959 FOREACH_DEVICE_TAG(device, tag) {
960 k = device_tag(device, tag, add);
961 if (r >= 0 && k < 0)
962 r = k;
963 }
964
965 return r;
966 }
967
968 static bool device_has_info(sd_device *device) {
969 assert(device);
970
971 if (!set_isempty(device->devlinks))
972 return true;
973
974 if (device->devlink_priority != 0)
975 return true;
976
977 if (!ordered_hashmap_isempty(device->properties_db))
978 return true;
979
980 if (!set_isempty(device->tags))
981 return true;
982
983 if (device->watch_handle >= 0)
984 return true;
985
986 return false;
987 }
988
989 void device_set_db_persist(sd_device *device) {
990 assert(device);
991
992 device->db_persist = true;
993 }
994
995 int device_update_db(sd_device *device) {
996 const char *id;
997 char *path;
998 _cleanup_fclose_ FILE *f = NULL;
999 _cleanup_free_ char *path_tmp = NULL;
1000 bool has_info;
1001 int r;
1002
1003 assert(device);
1004
1005 has_info = device_has_info(device);
1006
1007 r = device_get_id_filename(device, &id);
1008 if (r < 0)
1009 return r;
1010
1011 path = strjoina("/run/udev/data/", id);
1012
1013 /* do not store anything for otherwise empty devices */
1014 if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) {
1015 r = unlink(path);
1016 if (r < 0 && errno != ENOENT)
1017 return -errno;
1018
1019 return 0;
1020 }
1021
1022 /* write a database file */
1023 r = mkdir_parents(path, 0755);
1024 if (r < 0)
1025 return r;
1026
1027 r = fopen_temporary(path, &f, &path_tmp);
1028 if (r < 0)
1029 return r;
1030
1031 /*
1032 * set 'sticky' bit to indicate that we should not clean the
1033 * database when we transition from initramfs to the real root
1034 */
1035 if (device->db_persist) {
1036 r = fchmod(fileno(f), 01644);
1037 if (r < 0) {
1038 r = -errno;
1039 goto fail;
1040 }
1041 } else {
1042 r = fchmod(fileno(f), 0644);
1043 if (r < 0) {
1044 r = -errno;
1045 goto fail;
1046 }
1047 }
1048
1049 if (has_info) {
1050 const char *property, *value, *tag;
1051 Iterator i;
1052
1053 if (major(device->devnum) > 0) {
1054 const char *devlink;
1055
1056 FOREACH_DEVICE_DEVLINK(device, devlink)
1057 fprintf(f, "S:%s\n", devlink + STRLEN("/dev/"));
1058
1059 if (device->devlink_priority != 0)
1060 fprintf(f, "L:%i\n", device->devlink_priority);
1061
1062 if (device->watch_handle >= 0)
1063 fprintf(f, "W:%i\n", device->watch_handle);
1064 }
1065
1066 if (device->usec_initialized > 0)
1067 fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized);
1068
1069 ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i)
1070 fprintf(f, "E:%s=%s\n", property, value);
1071
1072 FOREACH_DEVICE_TAG(device, tag)
1073 fprintf(f, "G:%s\n", tag);
1074 }
1075
1076 r = fflush_and_check(f);
1077 if (r < 0)
1078 goto fail;
1079
1080 r = rename(path_tmp, path);
1081 if (r < 0) {
1082 r = -errno;
1083 goto fail;
1084 }
1085
1086 log_device_debug(device, "sd-device: Created %s file '%s' for '%s'", has_info ? "db" : "empty",
1087 path, device->devpath);
1088
1089 return 0;
1090
1091 fail:
1092 (void) unlink(path);
1093 (void) unlink(path_tmp);
1094
1095 return log_device_debug_errno(device, r, "sd-device: Failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath);
1096 }
1097
1098 int device_delete_db(sd_device *device) {
1099 const char *id;
1100 char *path;
1101 int r;
1102
1103 assert(device);
1104
1105 r = device_get_id_filename(device, &id);
1106 if (r < 0)
1107 return r;
1108
1109 path = strjoina("/run/udev/data/", id);
1110
1111 r = unlink(path);
1112 if (r < 0 && errno != ENOENT)
1113 return -errno;
1114
1115 return 0;
1116 }
1117
1118 int device_read_db_force(sd_device *device) {
1119 assert(device);
1120
1121 return device_read_db_aux(device, true);
1122 }