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