chiark / gitweb /
pam_elogind compiling
[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                 char *devlinks, *next;
423
424                 devlinks = strdupa(value);
425
426                 while ((next = strchr(devlinks, ' '))) {
427                         next[0] = '\0';
428
429                         r = device_add_devlink(device, devlinks);
430                         if (r < 0)
431                                 return log_debug_errno(r, "sd-device: could not add devlink '%s': %m", devlinks);
432
433                         devlinks = next + 1;
434                 }
435         } else if (streq(key, "TAGS")) {
436                 char *tags, *next;
437
438                 tags = strdupa(value);
439
440                 while ((next = strchr(tags, ':'))) {
441                         next[0] = '\0';
442
443                         r = device_add_tag(device, tags);
444                         if (r < 0)
445                                 return log_debug_errno(r, "sd-device: could not add tag '%s': %m", tags);
446
447                         tags = next + 1;
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_ammend(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         char **buf_strv = NULL;
640         uint8_t *buf_nulstr = NULL;
641         size_t allocated_nulstr = 0, allocated_strv = 0;
642         size_t nulstr_len = 0, strv_size = 0;
643
644         assert(device);
645
646         FOREACH_DEVICE_PROPERTY(device, prop, val) {
647                 size_t len = 0;
648
649                 len = strlen(prop) + 1 + strlen(val);
650
651                 buf_nulstr = GREEDY_REALLOC0(buf_nulstr, allocated_nulstr, nulstr_len + len + 2);
652                 if (!buf_nulstr)
653                         return -ENOMEM;
654
655                 buf_strv = GREEDY_REALLOC0(buf_strv, allocated_strv, strv_size + 2);
656                 if (!buf_strv)
657                         return -ENOMEM;
658
659                 buf_strv[++ strv_size] = (char *)&buf_nulstr[nulstr_len];
660                 strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL);
661                 nulstr_len += len + 1;
662         }
663
664         free(device->properties_nulstr);
665         free(device->properties_strv);
666         device->properties_nulstr = buf_nulstr;
667         device->properties_nulstr_len = nulstr_len;
668         device->properties_strv = buf_strv;
669
670         device->properties_buf_outdated = false;
671
672         return 0;
673 }
674
675 int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) {
676         int r;
677
678         assert(device);
679         assert(nulstr);
680         assert(len);
681
682         if (device->properties_buf_outdated) {
683                 r = device_update_properties_bufs(device);
684                 if (r < 0)
685                         return r;
686         }
687
688         *nulstr = device->properties_nulstr;
689         *len = device->properties_nulstr_len;
690
691         return 0;
692 }
693
694 int device_get_properties_strv(sd_device *device, char ***strv) {
695         int r;
696
697         assert(device);
698         assert(strv);
699
700         r = device_update_properties_bufs(device);
701         if (r < 0)
702                 return r;
703
704         *strv = device->properties_strv;
705
706         return 0;
707 }
708
709 int device_get_devlink_priority(sd_device *device, int *priority) {
710         int r;
711
712         assert(device);
713         assert(priority);
714
715         r = device_read_db(device);
716         if (r < 0)
717                 return r;
718
719         *priority = device->devlink_priority;
720
721         return 0;
722 }
723
724 int device_get_watch_handle(sd_device *device, int *handle) {
725         int r;
726
727         assert(device);
728         assert(handle);
729
730         r = device_read_db(device);
731         if (r < 0)
732                 return r;
733
734         *handle = device->watch_handle;
735
736         return 0;
737 }
738
739 void device_set_watch_handle(sd_device *device, int handle) {
740         assert(device);
741
742         device->watch_handle = handle;
743 }
744
745 int device_rename(sd_device *device, const char *name) {
746         _cleanup_free_ char *dirname = NULL;
747         char *new_syspath;
748         const char *interface;
749         int r;
750
751         assert(device);
752         assert(name);
753
754         dirname = dirname_malloc(device->syspath);
755         if (!dirname)
756                 return -ENOMEM;
757
758         new_syspath = strjoina(dirname, "/", name);
759
760         /* the user must trust that the new name is correct */
761         r = device_set_syspath(device, new_syspath, false);
762         if (r < 0)
763                 return r;
764
765         r = sd_device_get_property_value(device, "INTERFACE", &interface);
766         if (r >= 0) {
767                 r = device_add_property_internal(device, "INTERFACE", name);
768                 if (r < 0)
769                         return r;
770
771                 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
772                 r = device_add_property_internal(device, "INTERFACE_OLD", interface);
773                 if (r < 0)
774                         return r;
775         } else if (r != -ENOENT)
776                 return r;
777
778         return 0;
779 }
780
781 int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
782         _cleanup_device_unref_ sd_device *ret = NULL;
783         int r;
784
785         assert(old_device);
786         assert(new_device);
787
788         r = device_new_aux(&ret);
789         if (r < 0)
790                 return r;
791
792         r = device_set_syspath(ret, old_device->syspath, false);
793         if (r < 0)
794                 return r;
795
796         r = device_set_subsystem(ret, old_device->subsystem);
797         if (r < 0)
798                 return r;
799
800         ret->devnum = old_device->devnum;
801
802         *new_device = ret;
803         ret = NULL;
804
805         return 0;
806 }
807
808 int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
809         _cleanup_device_unref_ sd_device *ret = NULL;
810         int r;
811
812         assert(old_device);
813         assert(new_device);
814
815         r = device_shallow_clone(old_device, &ret);
816         if (r < 0)
817                 return r;
818
819         r = device_read_db(ret);
820         if (r < 0)
821                 return r;
822
823         ret->sealed = true;
824
825         *new_device = ret;
826         ret = NULL;
827
828         return 0;
829 }
830
831 int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
832         _cleanup_device_unref_ sd_device *ret = NULL;
833         int r;
834
835         assert(new_device);
836         assert(syspath);
837         assert(action);
838
839         r = sd_device_new_from_syspath(&ret, syspath);
840         if (r < 0)
841                 return r;
842
843         r = device_read_uevent_file(ret);
844         if (r < 0)
845                 return r;
846
847         r = device_add_property_internal(ret, "ACTION", action);
848         if (r < 0)
849                 return r;
850
851         *new_device = ret;
852         ret = NULL;
853
854         return 0;
855 }
856
857 int device_copy_properties(sd_device *device_dst, sd_device *device_src) {
858         const char *property, *value;
859         int r;
860
861         assert(device_dst);
862         assert(device_src);
863
864         FOREACH_DEVICE_PROPERTY(device_src, property, value) {
865                 r = device_add_property(device_dst, property, value);
866                 if (r < 0)
867                         return r;
868         }
869
870         return 0;
871 }
872
873 void device_cleanup_tags(sd_device *device) {
874         assert(device);
875
876         set_free_free(device->tags);
877         device->tags = NULL;
878         device->property_tags_outdated = true;
879         device->tags_generation ++;
880 }
881
882 void device_cleanup_devlinks(sd_device *device) {
883         assert(device);
884
885         set_free_free(device->devlinks);
886         device->devlinks = NULL;
887         device->property_devlinks_outdated = true;
888         device->devlinks_generation ++;
889 }
890
891 void device_remove_tag(sd_device *device, const char *tag) {
892         assert(device);
893         assert(tag);
894
895         free(set_remove(device->tags, tag));
896         device->property_tags_outdated = true;
897         device->tags_generation ++;
898 }
899
900 static int device_tag(sd_device *device, const char *tag, bool add) {
901         const char *id;
902         char *path;
903         int r;
904
905         assert(device);
906         assert(tag);
907
908         r = device_get_id_filename(device, &id);
909         if (r < 0)
910                 return r;
911
912         path = strjoina("/run/udev/tags/", tag, "/", id);
913
914         if (add) {
915                 r = touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
916                 if (r < 0)
917                         return r;
918         } else {
919                 r = unlink(path);
920                 if (r < 0 && errno != ENOENT)
921                         return -errno;
922         }
923
924         return 0;
925 }
926
927 int device_tag_index(sd_device *device, sd_device *device_old, bool add) {
928         const char *tag;
929         int r = 0, k;
930
931         if (add && device_old) {
932                 /* delete possible left-over tags */
933                 FOREACH_DEVICE_TAG(device_old, tag) {
934                         if (!sd_device_has_tag(device, tag)) {
935                                 k = device_tag(device_old, tag, false);
936                                 if (r >= 0 && k < 0)
937                                         r = k;
938                         }
939                 }
940         }
941
942         FOREACH_DEVICE_TAG(device, tag) {
943                 k = device_tag(device, tag, add);
944                 if (r >= 0 && k < 0)
945                         r = k;
946         }
947
948         return r;
949 }
950
951 static bool device_has_info(sd_device *device) {
952         assert(device);
953
954         if (!set_isempty(device->devlinks))
955                 return true;
956
957         if (device->devlink_priority != 0)
958                 return true;
959
960         if (!ordered_hashmap_isempty(device->properties_db))
961                 return true;
962
963         if (!set_isempty(device->tags))
964                 return true;
965
966         if (device->watch_handle >= 0)
967                 return true;
968
969         return false;
970 }
971
972 void device_set_db_persist(sd_device *device) {
973         assert(device);
974
975         device->db_persist = true;
976 }
977
978 int device_update_db(sd_device *device) {
979         const char *id;
980         char *path;
981         _cleanup_fclose_ FILE *f = NULL;
982         _cleanup_free_ char *path_tmp = NULL;
983         bool has_info;
984         int r;
985
986         assert(device);
987
988         has_info = device_has_info(device);
989
990         r = device_get_id_filename(device, &id);
991         if (r < 0)
992                 return r;
993
994         path = strjoina("/run/udev/data/", id);
995
996         /* do not store anything for otherwise empty devices */
997         if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) {
998                 r = unlink(path);
999                 if (r < 0 && errno != ENOENT)
1000                         return -errno;
1001
1002                 return 0;
1003         }
1004
1005         /* write a database file */
1006         r = mkdir_parents(path, 0755);
1007         if (r < 0)
1008                 return r;
1009
1010         r = fopen_temporary(path, &f, &path_tmp);
1011         if (r < 0)
1012                 return r;
1013
1014         /*
1015          * set 'sticky' bit to indicate that we should not clean the
1016          * database when we transition from initramfs to the real root
1017          */
1018         if (device->db_persist) {
1019                 r = fchmod(fileno(f), 01644);
1020                 if (r < 0) {
1021                         r = -errno;
1022                         goto fail;
1023                 }
1024         } else {
1025                 r = fchmod(fileno(f), 0644);
1026                 if (r < 0) {
1027                         r = -errno;
1028                         goto fail;
1029                 }
1030         }
1031
1032         if (has_info) {
1033                 const char *property, *value, *tag;
1034                 Iterator i;
1035
1036                 if (major(device->devnum) > 0) {
1037                         const char *devlink;
1038
1039                         FOREACH_DEVICE_DEVLINK(device, devlink)
1040                                 fprintf(f, "S:%s\n", devlink + strlen("/dev/"));
1041
1042                         if (device->devlink_priority != 0)
1043                                 fprintf(f, "L:%i\n", device->devlink_priority);
1044
1045                         if (device->watch_handle >= 0)
1046                                 fprintf(f, "W:%i\n", device->watch_handle);
1047                 }
1048
1049                 if (device->usec_initialized > 0)
1050                         fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized);
1051
1052                 ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i)
1053                         fprintf(f, "E:%s=%s\n", property, value);
1054
1055                 FOREACH_DEVICE_TAG(device, tag)
1056                         fprintf(f, "G:%s\n", tag);
1057         }
1058
1059         r = fflush_and_check(f);
1060         if (r < 0)
1061                 goto fail;
1062
1063         r = rename(path_tmp, path);
1064         if (r < 0) {
1065                 r = -errno;
1066                 goto fail;
1067         }
1068
1069         log_debug("created %s file '%s' for '%s'", has_info ? "db" : "empty",
1070                   path, device->devpath);
1071
1072         return 0;
1073
1074 fail:
1075         log_error_errno(r, "failed to create %s file '%s' for '%s'", has_info ? "db" : "empty",
1076                         path, device->devpath);
1077         unlink(path);
1078         unlink(path_tmp);
1079
1080         return r;
1081 }
1082
1083 int device_delete_db(sd_device *device) {
1084         const char *id;
1085         char *path;
1086         int r;
1087
1088         assert(device);
1089
1090         r = device_get_id_filename(device, &id);
1091         if (r < 0)
1092                 return r;
1093
1094         path = strjoina("/run/udev/data/", id);
1095
1096         r = unlink(path);
1097         if (r < 0 && errno != ENOENT)
1098                 return -errno;
1099
1100         return 0;
1101 }