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