chiark / gitweb /
sd-device: fix deserialization from netlink
[elogind.git] / src / libelogind / 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_ammend(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;
427
428                         devlink = strndupa(word, l);
429
430                         r = device_add_devlink(device, devlink);
431                         if (r < 0)
432                                 return log_debug_errno(r, "sd-device: could not add devlink '%s': %m", devlink);
433                 }
434         } else if (streq(key, "TAGS")) {
435                 const char *word, *state;
436                 size_t l;
437
438                 FOREACH_WORD_SEPARATOR(word, l, value, ":", state) {
439                         char *tag;
440
441                         tag = strndupa(word, l);
442
443                         r = device_add_tag(device, tag);
444                         if (r < 0)
445                                 return log_debug_errno(r, "sd-device: could not add tag '%s': %m", tag);
446                 }
447         } else {
448                 r = device_add_property_internal(device, key, value);
449                 if (r < 0)
450                         return log_debug_errno(r, "sd-device: could not add property '%s=%s': %m", key, value);
451         }
452
453         return 0;
454 }
455
456 static const char* const device_action_table[_DEVICE_ACTION_MAX] = {
457         [DEVICE_ACTION_ADD] = "add",
458         [DEVICE_ACTION_REMOVE] = "remove",
459         [DEVICE_ACTION_CHANGE] = "change",
460         [DEVICE_ACTION_MOVE] = "move",
461         [DEVICE_ACTION_ONLINE] = "online",
462         [DEVICE_ACTION_OFFLINE] = "offline",
463 };
464
465 DEFINE_STRING_TABLE_LOOKUP(device_action, DeviceAction);
466
467 static int device_append(sd_device *device, char *key, const char **_major, const char **_minor, uint64_t *_seqnum,
468                          DeviceAction *_action) {
469         DeviceAction action = _DEVICE_ACTION_INVALID;
470         uint64_t seqnum = 0;
471         const char *major = NULL, *minor = NULL;
472         char *value;
473         int r;
474
475         assert(device);
476         assert(key);
477         assert(_major);
478         assert(_minor);
479         assert(_seqnum);
480         assert(_action);
481
482         value = strchr(key, '=');
483         if (!value) {
484                 log_debug("sd-device: not a key-value pair: '%s'", key);
485                 return -EINVAL;
486         }
487
488         *value = '\0';
489
490         value++;
491
492         if (streq(key, "MAJOR"))
493                 major = value;
494         else if (streq(key, "MINOR"))
495                 minor = value;
496         else {
497                 if (streq(key, "ACTION")) {
498                         action = device_action_from_string(value);
499                         if (action == _DEVICE_ACTION_INVALID)
500                                 return -EINVAL;
501                 } else if (streq(key, "SEQNUM")) {
502                         r = safe_atou64(value, &seqnum);
503                         if (r < 0)
504                                 return r;
505                         else if (seqnum == 0)
506                                  /* kernel only sends seqnum > 0 */
507                                 return -EINVAL;
508                 }
509
510                 r = device_ammend(device, key, value);
511                 if (r < 0)
512                         return r;
513         }
514
515         if (major != 0)
516                 *_major = major;
517
518         if (minor != 0)
519                 *_minor = minor;
520
521         if (action != _DEVICE_ACTION_INVALID)
522                 *_action = action;
523
524         if (seqnum > 0)
525                 *_seqnum = seqnum;
526
527         return 0;
528 }
529
530 void device_seal(sd_device *device) {
531         assert(device);
532
533         device->sealed = true;
534 }
535
536 static int device_verify(sd_device *device, DeviceAction action, uint64_t seqnum) {
537         assert(device);
538
539         if (!device->devpath || !device->subsystem || action == _DEVICE_ACTION_INVALID || seqnum == 0) {
540                 log_debug("sd-device: device created from strv lacks devpath, subsystem, action or seqnum");
541                 return -EINVAL;
542         }
543
544         device->sealed = true;
545
546         return 0;
547 }
548
549 int device_new_from_strv(sd_device **ret, char **strv) {
550         _cleanup_device_unref_ sd_device *device = NULL;
551         char **key;
552         const char *major = NULL, *minor = NULL;
553         DeviceAction action = _DEVICE_ACTION_INVALID;
554         uint64_t seqnum;
555         int r;
556
557         assert(ret);
558         assert(strv);
559
560         r = device_new_aux(&device);
561         if (r < 0)
562                 return r;
563
564         STRV_FOREACH(key, strv) {
565                 r = device_append(device, *key, &major, &minor, &seqnum, &action);
566                 if (r < 0)
567                         return r;
568         }
569
570         if (major) {
571                 r = device_set_devnum(device, major, minor);
572                 if (r < 0)
573                         return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor);
574         }
575
576         r = device_verify(device, action, seqnum);
577         if (r < 0)
578                 return r;
579
580         *ret = device;
581         device = NULL;
582
583         return 0;
584 }
585
586 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
587         _cleanup_device_unref_ sd_device *device = NULL;
588         const char *major = NULL, *minor = NULL;
589         DeviceAction action = _DEVICE_ACTION_INVALID;
590         uint64_t seqnum;
591         unsigned i = 0;
592         int r;
593
594         assert(ret);
595         assert(nulstr);
596         assert(len);
597
598         r = device_new_aux(&device);
599         if (r < 0)
600                 return r;
601
602         while (i < len) {
603                 char *key;
604                 const char *end;
605
606                 key = (char*)&nulstr[i];
607                 end = memchr(key, '\0', len - i);
608                 if (!end) {
609                         log_debug("sd-device: failed to parse nulstr");
610                         return -EINVAL;
611                 }
612                 i += end - key + 1;
613
614                 r = device_append(device, key, &major, &minor, &seqnum, &action);
615                 if (r < 0)
616                         return r;
617         }
618
619         if (major) {
620                 r = device_set_devnum(device, major, minor);
621                 if (r < 0)
622                         return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor);
623         }
624
625         r = device_verify(device, action, seqnum);
626         if (r < 0)
627                 return r;
628
629         *ret = device;
630         device = NULL;
631
632         return 0;
633 }
634
635 static int device_update_properties_bufs(sd_device *device) {
636         const char *val, *prop;
637         char **buf_strv = NULL;
638         uint8_t *buf_nulstr = NULL;
639         size_t allocated_nulstr = 0, allocated_strv = 0;
640         size_t nulstr_len = 0, strv_size = 0;
641
642         assert(device);
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                 buf_strv = GREEDY_REALLOC0(buf_strv, allocated_strv, strv_size + 2);
654                 if (!buf_strv)
655                         return -ENOMEM;
656
657                 buf_strv[++ strv_size] = (char *)&buf_nulstr[nulstr_len];
658                 strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL);
659                 nulstr_len += len + 1;
660         }
661
662         free(device->properties_nulstr);
663         free(device->properties_strv);
664         device->properties_nulstr = buf_nulstr;
665         device->properties_nulstr_len = nulstr_len;
666         device->properties_strv = buf_strv;
667
668         device->properties_buf_outdated = false;
669
670         return 0;
671 }
672
673 int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) {
674         int r;
675
676         assert(device);
677         assert(nulstr);
678         assert(len);
679
680         if (device->properties_buf_outdated) {
681                 r = device_update_properties_bufs(device);
682                 if (r < 0)
683                         return r;
684         }
685
686         *nulstr = device->properties_nulstr;
687         *len = device->properties_nulstr_len;
688
689         return 0;
690 }
691
692 int device_get_properties_strv(sd_device *device, char ***strv) {
693         int r;
694
695         assert(device);
696         assert(strv);
697
698         r = device_update_properties_bufs(device);
699         if (r < 0)
700                 return r;
701
702         *strv = device->properties_strv;
703
704         return 0;
705 }
706
707 int device_get_devlink_priority(sd_device *device, int *priority) {
708         int r;
709
710         assert(device);
711         assert(priority);
712
713         r = device_read_db(device);
714         if (r < 0)
715                 return r;
716
717         *priority = device->devlink_priority;
718
719         return 0;
720 }
721
722 int device_get_watch_handle(sd_device *device, int *handle) {
723         int r;
724
725         assert(device);
726         assert(handle);
727
728         r = device_read_db(device);
729         if (r < 0)
730                 return r;
731
732         *handle = device->watch_handle;
733
734         return 0;
735 }
736
737 void device_set_watch_handle(sd_device *device, int handle) {
738         assert(device);
739
740         device->watch_handle = handle;
741 }
742
743 int device_rename(sd_device *device, const char *name) {
744         _cleanup_free_ char *dirname = NULL;
745         char *new_syspath;
746         const char *interface;
747         int r;
748
749         assert(device);
750         assert(name);
751
752         dirname = dirname_malloc(device->syspath);
753         if (!dirname)
754                 return -ENOMEM;
755
756         new_syspath = strjoina(dirname, "/", name);
757
758         /* the user must trust that the new name is correct */
759         r = device_set_syspath(device, new_syspath, false);
760         if (r < 0)
761                 return r;
762
763         r = sd_device_get_property_value(device, "INTERFACE", &interface);
764         if (r >= 0) {
765                 r = device_add_property_internal(device, "INTERFACE", name);
766                 if (r < 0)
767                         return r;
768
769                 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
770                 r = device_add_property_internal(device, "INTERFACE_OLD", interface);
771                 if (r < 0)
772                         return r;
773         } else if (r != -ENOENT)
774                 return r;
775
776         return 0;
777 }
778
779 int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
780         _cleanup_device_unref_ sd_device *ret = NULL;
781         int r;
782
783         assert(old_device);
784         assert(new_device);
785
786         r = device_new_aux(&ret);
787         if (r < 0)
788                 return r;
789
790         r = device_set_syspath(ret, old_device->syspath, false);
791         if (r < 0)
792                 return r;
793
794         r = device_set_subsystem(ret, old_device->subsystem);
795         if (r < 0)
796                 return r;
797
798         ret->devnum = old_device->devnum;
799
800         *new_device = ret;
801         ret = NULL;
802
803         return 0;
804 }
805
806 int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
807         _cleanup_device_unref_ sd_device *ret = NULL;
808         int r;
809
810         assert(old_device);
811         assert(new_device);
812
813         r = device_shallow_clone(old_device, &ret);
814         if (r < 0)
815                 return r;
816
817         r = device_read_db(ret);
818         if (r < 0)
819                 return r;
820
821         ret->sealed = true;
822
823         *new_device = ret;
824         ret = NULL;
825
826         return 0;
827 }
828
829 int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
830         _cleanup_device_unref_ sd_device *ret = NULL;
831         int r;
832
833         assert(new_device);
834         assert(syspath);
835         assert(action);
836
837         r = sd_device_new_from_syspath(&ret, syspath);
838         if (r < 0)
839                 return r;
840
841         r = device_read_uevent_file(ret);
842         if (r < 0)
843                 return r;
844
845         r = device_add_property_internal(ret, "ACTION", action);
846         if (r < 0)
847                 return r;
848
849         *new_device = ret;
850         ret = NULL;
851
852         return 0;
853 }
854
855 int device_copy_properties(sd_device *device_dst, sd_device *device_src) {
856         const char *property, *value;
857         int r;
858
859         assert(device_dst);
860         assert(device_src);
861
862         FOREACH_DEVICE_PROPERTY(device_src, property, value) {
863                 r = device_add_property(device_dst, property, value);
864                 if (r < 0)
865                         return r;
866         }
867
868         return 0;
869 }
870
871 void device_cleanup_tags(sd_device *device) {
872         assert(device);
873
874         set_free_free(device->tags);
875         device->tags = NULL;
876         device->property_tags_outdated = true;
877         device->tags_generation ++;
878 }
879
880 void device_cleanup_devlinks(sd_device *device) {
881         assert(device);
882
883         set_free_free(device->devlinks);
884         device->devlinks = NULL;
885         device->property_devlinks_outdated = true;
886         device->devlinks_generation ++;
887 }
888
889 void device_remove_tag(sd_device *device, const char *tag) {
890         assert(device);
891         assert(tag);
892
893         free(set_remove(device->tags, tag));
894         device->property_tags_outdated = true;
895         device->tags_generation ++;
896 }
897
898 static int device_tag(sd_device *device, const char *tag, bool add) {
899         const char *id;
900         char *path;
901         int r;
902
903         assert(device);
904         assert(tag);
905
906         r = device_get_id_filename(device, &id);
907         if (r < 0)
908                 return r;
909
910         path = strjoina("/run/udev/tags/", tag, "/", id);
911
912         if (add) {
913                 r = touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
914                 if (r < 0)
915                         return r;
916         } else {
917                 r = unlink(path);
918                 if (r < 0 && errno != ENOENT)
919                         return -errno;
920         }
921
922         return 0;
923 }
924
925 int device_tag_index(sd_device *device, sd_device *device_old, bool add) {
926         const char *tag;
927         int r = 0, k;
928
929         if (add && device_old) {
930                 /* delete possible left-over tags */
931                 FOREACH_DEVICE_TAG(device_old, tag) {
932                         if (!sd_device_has_tag(device, tag)) {
933                                 k = device_tag(device_old, tag, false);
934                                 if (r >= 0 && k < 0)
935                                         r = k;
936                         }
937                 }
938         }
939
940         FOREACH_DEVICE_TAG(device, tag) {
941                 k = device_tag(device, tag, add);
942                 if (r >= 0 && k < 0)
943                         r = k;
944         }
945
946         return r;
947 }
948
949 static bool device_has_info(sd_device *device) {
950         assert(device);
951
952         if (!set_isempty(device->devlinks))
953                 return true;
954
955         if (device->devlink_priority != 0)
956                 return true;
957
958         if (!ordered_hashmap_isempty(device->properties_db))
959                 return true;
960
961         if (!set_isempty(device->tags))
962                 return true;
963
964         if (device->watch_handle >= 0)
965                 return true;
966
967         return false;
968 }
969
970 void device_set_db_persist(sd_device *device) {
971         assert(device);
972
973         device->db_persist = true;
974 }
975
976 int device_update_db(sd_device *device) {
977         const char *id;
978         char *path;
979         _cleanup_fclose_ FILE *f = NULL;
980         _cleanup_free_ char *path_tmp = NULL;
981         bool has_info;
982         int r;
983
984         assert(device);
985
986         has_info = device_has_info(device);
987
988         r = device_get_id_filename(device, &id);
989         if (r < 0)
990                 return r;
991
992         path = strjoina("/run/udev/data/", id);
993
994         /* do not store anything for otherwise empty devices */
995         if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) {
996                 r = unlink(path);
997                 if (r < 0 && errno != ENOENT)
998                         return -errno;
999
1000                 return 0;
1001         }
1002
1003         /* write a database file */
1004         r = mkdir_parents(path, 0755);
1005         if (r < 0)
1006                 return r;
1007
1008         r = fopen_temporary(path, &f, &path_tmp);
1009         if (r < 0)
1010                 return r;
1011
1012         /*
1013          * set 'sticky' bit to indicate that we should not clean the
1014          * database when we transition from initramfs to the real root
1015          */
1016         if (device->db_persist) {
1017                 r = fchmod(fileno(f), 01644);
1018                 if (r < 0) {
1019                         r = -errno;
1020                         goto fail;
1021                 }
1022         } else {
1023                 r = fchmod(fileno(f), 0644);
1024                 if (r < 0) {
1025                         r = -errno;
1026                         goto fail;
1027                 }
1028         }
1029
1030         if (has_info) {
1031                 const char *property, *value, *tag;
1032                 Iterator i;
1033
1034                 if (major(device->devnum) > 0) {
1035                         const char *devlink;
1036
1037                         FOREACH_DEVICE_DEVLINK(device, devlink)
1038                                 fprintf(f, "S:%s\n", devlink + strlen("/dev/"));
1039
1040                         if (device->devlink_priority != 0)
1041                                 fprintf(f, "L:%i\n", device->devlink_priority);
1042
1043                         if (device->watch_handle >= 0)
1044                                 fprintf(f, "W:%i\n", device->watch_handle);
1045                 }
1046
1047                 if (device->usec_initialized > 0)
1048                         fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized);
1049
1050                 ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i)
1051                         fprintf(f, "E:%s=%s\n", property, value);
1052
1053                 FOREACH_DEVICE_TAG(device, tag)
1054                         fprintf(f, "G:%s\n", tag);
1055         }
1056
1057         r = fflush_and_check(f);
1058         if (r < 0)
1059                 goto fail;
1060
1061         r = rename(path_tmp, path);
1062         if (r < 0) {
1063                 r = -errno;
1064                 goto fail;
1065         }
1066
1067         log_debug("created %s file '%s' for '%s'", has_info ? "db" : "empty",
1068                   path, device->devpath);
1069
1070         return 0;
1071
1072 fail:
1073         log_error_errno(r, "failed to create %s file '%s' for '%s'", has_info ? "db" : "empty",
1074                         path, device->devpath);
1075         unlink(path);
1076         unlink(path_tmp);
1077
1078         return r;
1079 }
1080
1081 int device_delete_db(sd_device *device) {
1082         const char *id;
1083         char *path;
1084         int r;
1085
1086         assert(device);
1087
1088         r = device_get_id_filename(device, &id);
1089         if (r < 0)
1090                 return r;
1091
1092         path = strjoina("/run/udev/data/", id);
1093
1094         r = unlink(path);
1095         if (r < 0 && errno != ENOENT)
1096                 return -errno;
1097
1098         return 0;
1099 }