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