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