1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <ctype.h>
4 #include <net/if.h>
5 #include <sys/types.h>
6 
7 #include "sd-device.h"
8 
9 #include "alloc-util.h"
10 #include "device-internal.h"
11 #include "device-private.h"
12 #include "device-util.h"
13 #include "fd-util.h"
14 #include "fileio.h"
15 #include "fs-util.h"
16 #include "hashmap.h"
17 #include "macro.h"
18 #include "mkdir.h"
19 #include "nulstr-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
22 #include "set.h"
23 #include "stdio-util.h"
24 #include "string-table.h"
25 #include "string-util.h"
26 #include "strv.h"
27 #include "strxcpyx.h"
28 #include "tmpfile-util.h"
29 #include "user-util.h"
30 
device_add_property(sd_device * device,const char * key,const char * value)31 int device_add_property(sd_device *device, const char *key, const char *value) {
32         int r;
33 
34         assert(device);
35         assert(key);
36 
37         r = device_add_property_aux(device, key, value, false);
38         if (r < 0)
39                 return r;
40 
41         if (key[0] != '.') {
42                 r = device_add_property_aux(device, key, value, true);
43                 if (r < 0)
44                         return r;
45         }
46 
47         return 0;
48 }
49 
device_add_propertyf(sd_device * device,const char * key,const char * format,...)50 int device_add_propertyf(sd_device *device, const char *key, const char *format, ...) {
51         _cleanup_free_ char *value = NULL;
52         va_list ap;
53         int r;
54 
55         assert(device);
56         assert(key);
57 
58         if (!format)
59                 return device_add_property(device, key, NULL);
60 
61         va_start(ap, format);
62         r = vasprintf(&value, format, ap);
63         va_end(ap);
64 
65         if (r < 0)
66                 return -ENOMEM;
67 
68         return device_add_property(device, key, value);
69 }
70 
device_set_devlink_priority(sd_device * device,int priority)71 void device_set_devlink_priority(sd_device *device, int priority) {
72         assert(device);
73 
74         device->devlink_priority = priority;
75 }
76 
device_set_is_initialized(sd_device * device)77 void device_set_is_initialized(sd_device *device) {
78         assert(device);
79 
80         device->is_initialized = true;
81 }
82 
device_ensure_usec_initialized(sd_device * device,sd_device * device_old)83 int device_ensure_usec_initialized(sd_device *device, sd_device *device_old) {
84         usec_t when;
85 
86         assert(device);
87 
88         if (device_old && device_old->usec_initialized > 0)
89                 when = device_old->usec_initialized;
90         else
91                 when = now(CLOCK_MONOTONIC);
92 
93         return device_set_usec_initialized(device, when);
94 }
95 
device_get_properties_generation(sd_device * device)96 uint64_t device_get_properties_generation(sd_device *device) {
97         assert(device);
98 
99         return device->properties_generation;
100 }
101 
device_get_tags_generation(sd_device * device)102 uint64_t device_get_tags_generation(sd_device *device) {
103         assert(device);
104 
105         return device->tags_generation;
106 }
107 
device_get_devlinks_generation(sd_device * device)108 uint64_t device_get_devlinks_generation(sd_device *device) {
109         assert(device);
110 
111         return device->devlinks_generation;
112 }
113 
device_get_devnode_mode(sd_device * device,mode_t * ret)114 int device_get_devnode_mode(sd_device *device, mode_t *ret) {
115         int r;
116 
117         assert(device);
118 
119         r = device_read_db(device);
120         if (r < 0)
121                 return r;
122 
123         if (device->devmode == MODE_INVALID)
124                 return -ENOENT;
125 
126         if (ret)
127                 *ret = device->devmode;
128 
129         return 0;
130 }
131 
device_get_devnode_uid(sd_device * device,uid_t * ret)132 int device_get_devnode_uid(sd_device *device, uid_t *ret) {
133         int r;
134 
135         assert(device);
136 
137         r = device_read_db(device);
138         if (r < 0)
139                 return r;
140 
141         if (device->devuid == UID_INVALID)
142                 return -ENOENT;
143 
144         if (ret)
145                 *ret = device->devuid;
146 
147         return 0;
148 }
149 
device_set_devuid(sd_device * device,const char * uid)150 static int device_set_devuid(sd_device *device, const char *uid) {
151         uid_t u;
152         int r;
153 
154         assert(device);
155         assert(uid);
156 
157         r = parse_uid(uid, &u);
158         if (r < 0)
159                 return r;
160 
161         r = device_add_property_internal(device, "DEVUID", uid);
162         if (r < 0)
163                 return r;
164 
165         device->devuid = u;
166 
167         return 0;
168 }
169 
device_get_devnode_gid(sd_device * device,gid_t * ret)170 int device_get_devnode_gid(sd_device *device, gid_t *ret) {
171         int r;
172 
173         assert(device);
174 
175         r = device_read_db(device);
176         if (r < 0)
177                 return r;
178 
179         if (device->devgid == GID_INVALID)
180                 return -ENOENT;
181 
182         if (ret)
183                 *ret = device->devgid;
184 
185         return 0;
186 }
187 
device_set_devgid(sd_device * device,const char * gid)188 static int device_set_devgid(sd_device *device, const char *gid) {
189         gid_t g;
190         int r;
191 
192         assert(device);
193         assert(gid);
194 
195         r = parse_gid(gid, &g);
196         if (r < 0)
197                 return r;
198 
199         r = device_add_property_internal(device, "DEVGID", gid);
200         if (r < 0)
201                 return r;
202 
203         device->devgid = g;
204 
205         return 0;
206 }
207 
device_set_action(sd_device * device,sd_device_action_t a)208 int device_set_action(sd_device *device, sd_device_action_t a) {
209         int r;
210 
211         assert(device);
212         assert(a >= 0 && a < _SD_DEVICE_ACTION_MAX);
213 
214         r = device_add_property_internal(device, "ACTION", device_action_to_string(a));
215         if (r < 0)
216                 return r;
217 
218         device->action = a;
219 
220         return 0;
221 }
222 
device_set_action_from_string(sd_device * device,const char * action)223 static int device_set_action_from_string(sd_device *device, const char *action) {
224         sd_device_action_t a;
225 
226         assert(device);
227         assert(action);
228 
229         a = device_action_from_string(action);
230         if (a < 0)
231                 return a;
232 
233         return device_set_action(device, a);
234 }
235 
device_set_seqnum(sd_device * device,const char * str)236 static int device_set_seqnum(sd_device *device, const char *str) {
237         uint64_t seqnum;
238         int r;
239 
240         assert(device);
241         assert(str);
242 
243         r = safe_atou64(str, &seqnum);
244         if (r < 0)
245                 return r;
246         if (seqnum == 0)
247                 return -EINVAL;
248 
249         r = device_add_property_internal(device, "SEQNUM", str);
250         if (r < 0)
251                 return r;
252 
253         device->seqnum = seqnum;
254 
255         return 0;
256 }
257 
device_amend(sd_device * device,const char * key,const char * value)258 static int device_amend(sd_device *device, const char *key, const char *value) {
259         int r;
260 
261         assert(device);
262         assert(key);
263         assert(value);
264 
265         if (streq(key, "DEVPATH")) {
266                 char *path;
267 
268                 path = strjoina("/sys", value);
269 
270                 /* the caller must verify or trust this data (e.g., if it comes from the kernel) */
271                 r = device_set_syspath(device, path, false);
272                 if (r < 0)
273                         return log_device_debug_errno(device, r, "sd-device: Failed to set syspath to '%s': %m", path);
274         } else if (streq(key, "SUBSYSTEM")) {
275                 r = device_set_subsystem(device, value);
276                 if (r < 0)
277                         return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem to '%s': %m", value);
278         } else if (streq(key, "DEVTYPE")) {
279                 r = device_set_devtype(device, value);
280                 if (r < 0)
281                         return log_device_debug_errno(device, r, "sd-device: Failed to set devtype to '%s': %m", value);
282         } else if (streq(key, "DEVNAME")) {
283                 r = device_set_devname(device, value);
284                 if (r < 0)
285                         return log_device_debug_errno(device, r, "sd-device: Failed to set devname to '%s': %m", value);
286         } else if (streq(key, "USEC_INITIALIZED")) {
287                 usec_t t;
288 
289                 r = safe_atou64(value, &t);
290                 if (r < 0)
291                         return log_device_debug_errno(device, r, "sd-device: Failed to parse timestamp '%s': %m", value);
292 
293                 r = device_set_usec_initialized(device, t);
294                 if (r < 0)
295                         return log_device_debug_errno(device, r, "sd-device: Failed to set usec-initialized to '%s': %m", value);
296         } else if (streq(key, "DRIVER")) {
297                 r = device_set_driver(device, value);
298                 if (r < 0)
299                         return log_device_debug_errno(device, r, "sd-device: Failed to set driver to '%s': %m", value);
300         } else if (streq(key, "IFINDEX")) {
301                 r = device_set_ifindex(device, value);
302                 if (r < 0)
303                         return log_device_debug_errno(device, r, "sd-device: Failed to set ifindex to '%s': %m", value);
304         } else if (streq(key, "DEVMODE")) {
305                 r = device_set_devmode(device, value);
306                 if (r < 0)
307                         return log_device_debug_errno(device, r, "sd-device: Failed to set devmode to '%s': %m", value);
308         } else if (streq(key, "DEVUID")) {
309                 r = device_set_devuid(device, value);
310                 if (r < 0)
311                         return log_device_debug_errno(device, r, "sd-device: Failed to set devuid to '%s': %m", value);
312         } else if (streq(key, "DEVGID")) {
313                 r = device_set_devgid(device, value);
314                 if (r < 0)
315                         return log_device_debug_errno(device, r, "sd-device: Failed to set devgid to '%s': %m", value);
316         } else if (streq(key, "ACTION")) {
317                 r = device_set_action_from_string(device, value);
318                 if (r < 0)
319                         return log_device_debug_errno(device, r, "sd-device: Failed to set action to '%s': %m", value);
320         } else if (streq(key, "SEQNUM")) {
321                 r = device_set_seqnum(device, value);
322                 if (r < 0)
323                         return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value);
324         } else if (streq(key, "DISKSEQ")) {
325                 r = device_set_diskseq(device, value);
326                 if (r < 0)
327                         return log_device_debug_errno(device, r, "sd-device: Failed to set DISKSEQ to '%s': %m", value);
328         } else if (streq(key, "DEVLINKS")) {
329                 for (const char *p = value;;) {
330                         _cleanup_free_ char *word = NULL;
331 
332                         /* udev rules may set escaped strings, and sd-device does not modify the input
333                          * strings. So, it is also necessary to keep the strings received through
334                          * sd-device-monitor. */
335                         r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
336                         if (r < 0)
337                                 return r;
338                         if (r == 0)
339                                 break;
340 
341                         r = device_add_devlink(device, word);
342                         if (r < 0)
343                                 return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", word);
344                 }
345         } else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) {
346                 for (const char *p = value;;) {
347                         _cleanup_free_ char *word = NULL;
348 
349                         r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
350                         if (r < 0)
351                                 return r;
352                         if (r == 0)
353                                 break;
354 
355                         r = device_add_tag(device, word, streq(key, "CURRENT_TAGS"));
356                         if (r < 0)
357                                 return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", word);
358                 }
359         } else {
360                 r = device_add_property_internal(device, key, value);
361                 if (r < 0)
362                         return log_device_debug_errno(device, r, "sd-device: Failed to add property '%s=%s': %m", key, value);
363         }
364 
365         return 0;
366 }
367 
device_append(sd_device * device,char * key,const char ** _major,const char ** _minor)368 static int device_append(
369                 sd_device *device,
370                 char *key,
371                 const char **_major,
372                 const char **_minor) {
373 
374         const char *major = NULL, *minor = NULL;
375         char *value;
376         int r;
377 
378         assert(device);
379         assert(key);
380         assert(_major);
381         assert(_minor);
382 
383         value = strchr(key, '=');
384         if (!value)
385                 return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
386                                               "sd-device: Not a key-value pair: '%s'", key);
387 
388         *value = '\0';
389 
390         value++;
391 
392         if (streq(key, "MAJOR"))
393                 major = value;
394         else if (streq(key, "MINOR"))
395                 minor = value;
396         else {
397                 r = device_amend(device, key, value);
398                 if (r < 0)
399                         return r;
400         }
401 
402         if (major)
403                 *_major = major;
404 
405         if (minor)
406                 *_minor = minor;
407 
408         return 0;
409 }
410 
device_seal(sd_device * device)411 void device_seal(sd_device *device) {
412         assert(device);
413 
414         device->sealed = true;
415 }
416 
device_verify(sd_device * device)417 static int device_verify(sd_device *device) {
418         int r;
419 
420         assert(device);
421 
422         if (!device->devpath || !device->subsystem || device->action < 0 || device->seqnum == 0)
423                 return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
424                                               "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum.");
425 
426         if (streq(device->subsystem, "drivers")) {
427                 r = device_set_drivers_subsystem(device);
428                 if (r < 0)
429                         return r;
430         }
431 
432         device->sealed = true;
433 
434         return 0;
435 }
436 
device_new_from_strv(sd_device ** ret,char ** strv)437 int device_new_from_strv(sd_device **ret, char **strv) {
438         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
439         const char *major = NULL, *minor = NULL;
440         int r;
441 
442         assert(ret);
443         assert(strv);
444 
445         r = device_new_aux(&device);
446         if (r < 0)
447                 return r;
448 
449         STRV_FOREACH(key, strv) {
450                 r = device_append(device, *key, &major, &minor);
451                 if (r < 0)
452                         return r;
453         }
454 
455         if (major) {
456                 r = device_set_devnum(device, major, minor);
457                 if (r < 0)
458                         return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
459         }
460 
461         r = device_verify(device);
462         if (r < 0)
463                 return r;
464 
465         *ret = TAKE_PTR(device);
466 
467         return 0;
468 }
469 
device_new_from_nulstr(sd_device ** ret,uint8_t * nulstr,size_t len)470 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
471         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
472         const char *major = NULL, *minor = NULL;
473         int r;
474 
475         assert(ret);
476         assert(nulstr);
477         assert(len);
478 
479         r = device_new_aux(&device);
480         if (r < 0)
481                 return r;
482 
483         for (size_t i = 0; i < len; ) {
484                 char *key;
485                 const char *end;
486 
487                 key = (char*) &nulstr[i];
488                 end = memchr(key, '\0', len - i);
489                 if (!end)
490                         return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
491                                                       "sd-device: Failed to parse nulstr");
492 
493                 i += end - key + 1;
494 
495                 /* netlink messages for some devices contain an unwanted newline at the end of value.
496                  * Let's drop the newline and remaining characters after the newline. */
497                 truncate_nl(key);
498 
499                 r = device_append(device, key, &major, &minor);
500                 if (r < 0)
501                         return r;
502         }
503 
504         if (major) {
505                 r = device_set_devnum(device, major, minor);
506                 if (r < 0)
507                         return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
508         }
509 
510         r = device_verify(device);
511         if (r < 0)
512                 return r;
513 
514         *ret = TAKE_PTR(device);
515 
516         return 0;
517 }
518 
device_update_properties_bufs(sd_device * device)519 static int device_update_properties_bufs(sd_device *device) {
520         const char *val, *prop;
521         _cleanup_free_ char **buf_strv = NULL;
522         _cleanup_free_ uint8_t *buf_nulstr = NULL;
523         size_t nulstr_len = 0, num = 0, i = 0;
524 
525         assert(device);
526 
527         if (!device->properties_buf_outdated)
528                 return 0;
529 
530         FOREACH_DEVICE_PROPERTY(device, prop, val) {
531                 size_t len = 0;
532 
533                 len = strlen(prop) + 1 + strlen(val);
534 
535                 buf_nulstr = GREEDY_REALLOC0(buf_nulstr, nulstr_len + len + 2);
536                 if (!buf_nulstr)
537                         return -ENOMEM;
538 
539                 strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL);
540                 nulstr_len += len + 1;
541                 ++num;
542         }
543 
544         /* build buf_strv from buf_nulstr */
545         buf_strv = new0(char *, num + 1);
546         if (!buf_strv)
547                 return -ENOMEM;
548 
549         NULSTR_FOREACH(val, (char*) buf_nulstr) {
550                 buf_strv[i] = (char *) val;
551                 assert(i < num);
552                 i++;
553         }
554 
555         free_and_replace(device->properties_nulstr, buf_nulstr);
556         device->properties_nulstr_len = nulstr_len;
557         free_and_replace(device->properties_strv, buf_strv);
558 
559         device->properties_buf_outdated = false;
560 
561         return 0;
562 }
563 
device_get_properties_nulstr(sd_device * device,const uint8_t ** nulstr,size_t * len)564 int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) {
565         int r;
566 
567         assert(device);
568         assert(nulstr);
569         assert(len);
570 
571         r = device_update_properties_bufs(device);
572         if (r < 0)
573                 return r;
574 
575         *nulstr = device->properties_nulstr;
576         *len = device->properties_nulstr_len;
577 
578         return 0;
579 }
580 
device_get_properties_strv(sd_device * device,char *** strv)581 int device_get_properties_strv(sd_device *device, char ***strv) {
582         int r;
583 
584         assert(device);
585         assert(strv);
586 
587         r = device_update_properties_bufs(device);
588         if (r < 0)
589                 return r;
590 
591         *strv = device->properties_strv;
592 
593         return 0;
594 }
595 
device_get_devlink_priority(sd_device * device,int * ret)596 int device_get_devlink_priority(sd_device *device, int *ret) {
597         int r;
598 
599         assert(device);
600 
601         r = device_read_db(device);
602         if (r < 0)
603                 return r;
604 
605         if (ret)
606                 *ret = device->devlink_priority;
607 
608         return 0;
609 }
610 
device_get_watch_handle(sd_device * device)611 int device_get_watch_handle(sd_device *device) {
612         char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
613         _cleanup_free_ char *buf = NULL;
614         const char *id, *path_id;
615         int wd, r;
616 
617         assert(device);
618 
619         if (device->watch_handle >= 0)
620                 return device->watch_handle;
621 
622         r = device_get_device_id(device, &id);
623         if (r < 0)
624                 return r;
625 
626         path_id = strjoina("/run/udev/watch/", id);
627         r = readlink_malloc(path_id, &buf);
628         if (r < 0)
629                 return r;
630 
631         r = safe_atoi(buf, &wd);
632         if (r < 0)
633                 return r;
634 
635         if (wd < 0)
636                 return -EBADF;
637 
638         buf = mfree(buf);
639         xsprintf(path_wd, "/run/udev/watch/%d", wd);
640         r = readlink_malloc(path_wd, &buf);
641         if (r < 0)
642                 return r;
643 
644         if (!streq(buf, id))
645                 return -EBADF;
646 
647         return device->watch_handle = wd;
648 }
649 
device_remove_watch_handle(sd_device * device)650 static void device_remove_watch_handle(sd_device *device) {
651         const char *id;
652         int wd;
653 
654         assert(device);
655 
656         /* First, remove the symlink from handle to device id. */
657         wd = device_get_watch_handle(device);
658         if (wd >= 0) {
659                 char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
660 
661                 xsprintf(path_wd, "/run/udev/watch/%d", wd);
662                 if (unlink(path_wd) < 0 && errno != ENOENT)
663                         log_device_debug_errno(device, errno,
664                                                "sd-device: failed to remove %s, ignoring: %m",
665                                                path_wd);
666         }
667 
668         /* Next, remove the symlink from device id to handle. */
669         if (device_get_device_id(device, &id) >= 0) {
670                 const char *path_id;
671 
672                 path_id = strjoina("/run/udev/watch/", id);
673                 if (unlink(path_id) < 0 && errno != ENOENT)
674                         log_device_debug_errno(device, errno,
675                                                "sd-device: failed to remove %s, ignoring: %m",
676                                                path_id);
677         }
678 
679         device->watch_handle = -1;
680 }
681 
device_set_watch_handle(sd_device * device,int wd)682 int device_set_watch_handle(sd_device *device, int wd) {
683         char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
684         const char *id, *path_id;
685         int r;
686 
687         assert(device);
688 
689         if (wd >= 0 && wd == device_get_watch_handle(device))
690                 return 0;
691 
692         device_remove_watch_handle(device);
693 
694         if (wd < 0)
695                 /* negative wd means that the caller requests to clear saved watch handle. */
696                 return 0;
697 
698         r = device_get_device_id(device, &id);
699         if (r < 0)
700                 return r;
701 
702         path_id = strjoina("/run/udev/watch/", id);
703         xsprintf(path_wd, "/run/udev/watch/%d", wd);
704 
705         r = mkdir_parents(path_wd, 0755);
706         if (r < 0)
707                 return r;
708 
709         if (symlink(id, path_wd) < 0)
710                 return -errno;
711 
712         if (symlink(path_wd + STRLEN("/run/udev/watch/"), path_id) < 0) {
713                 r = -errno;
714                 if (unlink(path_wd) < 0 && errno != ENOENT)
715                         log_device_debug_errno(device, errno,
716                                                "sd-device: failed to remove %s, ignoring: %m",
717                                                path_wd);
718                 return r;
719         }
720 
721         device->watch_handle = wd;
722 
723         return 0;
724 }
725 
device_new_from_watch_handle_at(sd_device ** ret,int dirfd,int wd)726 int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd) {
727         char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
728         _cleanup_free_ char *id = NULL;
729         int r;
730 
731         assert(ret);
732 
733         if (wd < 0)
734                 return -EBADF;
735 
736         if (dirfd >= 0) {
737                 xsprintf(path_wd, "%d", wd);
738                 r = readlinkat_malloc(dirfd, path_wd, &id);
739         } else {
740                 xsprintf(path_wd, "/run/udev/watch/%d", wd);
741                 r = readlink_malloc(path_wd, &id);
742         }
743         if (r < 0)
744                 return r;
745 
746         return sd_device_new_from_device_id(ret, id);
747 }
748 
device_rename(sd_device * device,const char * name)749 int device_rename(sd_device *device, const char *name) {
750         _cleanup_free_ char *new_syspath = NULL;
751         const char *interface;
752         int r;
753 
754         assert(device);
755         assert(name);
756 
757         if (!filename_is_valid(name))
758                 return -EINVAL;
759 
760         r = path_extract_directory(device->syspath, &new_syspath);
761         if (r < 0)
762                 return r;
763 
764         if (!path_extend(&new_syspath, name))
765                 return -ENOMEM;
766 
767         if (!path_is_safe(new_syspath))
768                 return -EINVAL;
769 
770         /* At the time this is called, the renamed device may not exist yet. Hence, we cannot validate
771          * the new syspath. */
772         r = device_set_syspath(device, new_syspath, false);
773         if (r < 0)
774                 return r;
775 
776         /* Here, only clear the sysname and sysnum. They will be set when requested. */
777         device->sysnum = NULL;
778         device->sysname = mfree(device->sysname);
779 
780         r = sd_device_get_property_value(device, "INTERFACE", &interface);
781         if (r == -ENOENT)
782                 return 0;
783         if (r < 0)
784                 return r;
785 
786         /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
787         r = device_add_property_internal(device, "INTERFACE_OLD", interface);
788         if (r < 0)
789                 return r;
790 
791         return device_add_property_internal(device, "INTERFACE", name);
792 }
793 
device_shallow_clone(sd_device * device,sd_device ** ret)794 int device_shallow_clone(sd_device *device, sd_device **ret) {
795         _cleanup_(sd_device_unrefp) sd_device *dest = NULL;
796         const char *val = NULL;
797         int r;
798 
799         assert(device);
800         assert(ret);
801 
802         r = device_new_aux(&dest);
803         if (r < 0)
804                 return r;
805 
806         r = device_set_syspath(dest, device->syspath, false);
807         if (r < 0)
808                 return r;
809 
810         (void) sd_device_get_subsystem(device, &val);
811         r = device_set_subsystem(dest, val);
812         if (r < 0)
813                 return r;
814         if (streq_ptr(val, "drivers")) {
815                 r = free_and_strdup(&dest->driver_subsystem, device->driver_subsystem);
816                 if (r < 0)
817                         return r;
818         }
819 
820         /* The device may be already removed. Let's copy minimal set of information to make
821          * device_get_device_id() work without uevent file. */
822 
823         if (sd_device_get_property_value(device, "IFINDEX", &val) >= 0) {
824                 r = device_set_ifindex(dest, val);
825                 if (r < 0)
826                         return r;
827         }
828 
829         if (sd_device_get_property_value(device, "MAJOR", &val) >= 0) {
830                 const char *minor = NULL;
831 
832                 (void) sd_device_get_property_value(device, "MINOR", &minor);
833                 r = device_set_devnum(dest, val, minor);
834                 if (r < 0)
835                         return r;
836         }
837 
838         r = device_read_uevent_file(dest);
839         if (r < 0)
840                 return r;
841 
842         *ret = TAKE_PTR(dest);
843         return 0;
844 }
845 
device_clone_with_db(sd_device * device,sd_device ** ret)846 int device_clone_with_db(sd_device *device, sd_device **ret) {
847         _cleanup_(sd_device_unrefp) sd_device *dest = NULL;
848         int r;
849 
850         assert(device);
851         assert(ret);
852 
853         r = device_shallow_clone(device, &dest);
854         if (r < 0)
855                 return r;
856 
857         r = device_read_db(dest);
858         if (r < 0)
859                 return r;
860 
861         dest->sealed = true;
862 
863         *ret = TAKE_PTR(dest);
864         return 0;
865 }
866 
device_copy_properties(sd_device * device_dst,sd_device * device_src)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         r = device_properties_prepare(device_src);
875         if (r < 0)
876                 return r;
877 
878         ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties_db) {
879                 r = device_add_property_aux(device_dst, property, value, true);
880                 if (r < 0)
881                         return r;
882         }
883 
884         ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties) {
885                 r = device_add_property_aux(device_dst, property, value, false);
886                 if (r < 0)
887                         return r;
888         }
889 
890         return 0;
891 }
892 
device_cleanup_tags(sd_device * device)893 void device_cleanup_tags(sd_device *device) {
894         assert(device);
895 
896         device->all_tags = set_free_free(device->all_tags);
897         device->current_tags = set_free_free(device->current_tags);
898         device->property_tags_outdated = true;
899         device->tags_generation++;
900 }
901 
device_cleanup_devlinks(sd_device * device)902 void device_cleanup_devlinks(sd_device *device) {
903         assert(device);
904 
905         set_free_free(device->devlinks);
906         device->devlinks = NULL;
907         device->property_devlinks_outdated = true;
908         device->devlinks_generation++;
909 }
910 
device_remove_tag(sd_device * device,const char * tag)911 void device_remove_tag(sd_device *device, const char *tag) {
912         assert(device);
913         assert(tag);
914 
915         free(set_remove(device->current_tags, tag));
916         device->property_tags_outdated = true;
917         device->tags_generation++;
918 }
919 
device_tag(sd_device * device,const char * tag,bool add)920 static int device_tag(sd_device *device, const char *tag, bool add) {
921         const char *id;
922         char *path;
923         int r;
924 
925         assert(device);
926         assert(tag);
927 
928         r = device_get_device_id(device, &id);
929         if (r < 0)
930                 return r;
931 
932         path = strjoina("/run/udev/tags/", tag, "/", id);
933 
934         if (add)
935                 return touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
936 
937         if (unlink(path) < 0 && errno != ENOENT)
938                 return -errno;
939 
940         return 0;
941 }
942 
device_tag_index(sd_device * device,sd_device * device_old,bool add)943 int device_tag_index(sd_device *device, sd_device *device_old, bool add) {
944         const char *tag;
945         int r = 0, k;
946 
947         if (add && device_old)
948                 /* delete possible left-over tags */
949                 FOREACH_DEVICE_TAG(device_old, tag)
950                         if (!sd_device_has_tag(device, tag)) {
951                                 k = device_tag(device_old, tag, false);
952                                 if (r >= 0 && k < 0)
953                                         r = k;
954                         }
955 
956         FOREACH_DEVICE_TAG(device, tag) {
957                 k = device_tag(device, tag, add);
958                 if (r >= 0 && k < 0)
959                         r = k;
960         }
961 
962         return r;
963 }
964 
device_has_info(sd_device * device)965 static bool device_has_info(sd_device *device) {
966         assert(device);
967 
968         if (!set_isempty(device->devlinks))
969                 return true;
970 
971         if (device->devlink_priority != 0)
972                 return true;
973 
974         if (!ordered_hashmap_isempty(device->properties_db))
975                 return true;
976 
977         if (!set_isempty(device->all_tags))
978                 return true;
979 
980         if (!set_isempty(device->current_tags))
981                 return true;
982 
983         return false;
984 }
985 
device_set_db_persist(sd_device * device)986 void device_set_db_persist(sd_device *device) {
987         assert(device);
988 
989         device->db_persist = true;
990 }
991 
device_update_db(sd_device * device)992 int device_update_db(sd_device *device) {
993         const char *id;
994         char *path;
995         _cleanup_fclose_ FILE *f = NULL;
996         _cleanup_free_ char *path_tmp = NULL;
997         bool has_info;
998         int r;
999 
1000         assert(device);
1001 
1002         has_info = device_has_info(device);
1003 
1004         r = device_get_device_id(device, &id);
1005         if (r < 0)
1006                 return r;
1007 
1008         path = strjoina("/run/udev/data/", id);
1009 
1010         /* do not store anything for otherwise empty devices */
1011         if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) {
1012                 if (unlink(path) < 0 && errno != ENOENT)
1013                         return -errno;
1014 
1015                 return 0;
1016         }
1017 
1018         /* write a database file */
1019         r = mkdir_parents(path, 0755);
1020         if (r < 0)
1021                 return r;
1022 
1023         r = fopen_temporary(path, &f, &path_tmp);
1024         if (r < 0)
1025                 return r;
1026 
1027         /*
1028          * set 'sticky' bit to indicate that we should not clean the
1029          * database when we transition from initramfs to the real root
1030          */
1031         if (fchmod(fileno(f), device->db_persist ? 01644 : 0644) < 0) {
1032                 r = -errno;
1033                 goto fail;
1034         }
1035 
1036         if (has_info) {
1037                 const char *property, *value, *tag;
1038 
1039                 if (major(device->devnum) > 0) {
1040                         const char *devlink;
1041 
1042                         FOREACH_DEVICE_DEVLINK(device, devlink)
1043                                 fprintf(f, "S:%s\n", devlink + STRLEN("/dev/"));
1044 
1045                         if (device->devlink_priority != 0)
1046                                 fprintf(f, "L:%i\n", device->devlink_priority);
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)
1053                         fprintf(f, "E:%s=%s\n", property, value);
1054 
1055                 FOREACH_DEVICE_TAG(device, tag)
1056                         fprintf(f, "G:%s\n", tag); /* Any tag */
1057 
1058                 SET_FOREACH(tag, device->current_tags)
1059                         fprintf(f, "Q:%s\n", tag); /* Current tag */
1060 
1061                 /* Always write the latest database version here, instead of the value stored in
1062                  * device->database_version, as which may be 0. */
1063                 fputs("V:" STRINGIFY(LATEST_UDEV_DATABASE_VERSION) "\n", f);
1064         }
1065 
1066         r = fflush_and_check(f);
1067         if (r < 0)
1068                 goto fail;
1069 
1070         if (rename(path_tmp, path) < 0) {
1071                 r = -errno;
1072                 goto fail;
1073         }
1074 
1075         log_device_debug(device, "sd-device: Created %s file '%s' for '%s'", has_info ? "db" : "empty",
1076                          path, device->devpath);
1077 
1078         return 0;
1079 
1080 fail:
1081         (void) unlink(path);
1082         (void) unlink(path_tmp);
1083 
1084         return log_device_debug_errno(device, r, "sd-device: Failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath);
1085 }
1086 
device_delete_db(sd_device * device)1087 int device_delete_db(sd_device *device) {
1088         const char *id;
1089         char *path;
1090         int r;
1091 
1092         assert(device);
1093 
1094         r = device_get_device_id(device, &id);
1095         if (r < 0)
1096                 return r;
1097 
1098         path = strjoina("/run/udev/data/", id);
1099 
1100         if (unlink(path) < 0 && errno != ENOENT)
1101                 return -errno;
1102 
1103         return 0;
1104 }
1105 
1106 static const char* const device_action_table[_SD_DEVICE_ACTION_MAX] = {
1107         [SD_DEVICE_ADD]     = "add",
1108         [SD_DEVICE_REMOVE]  = "remove",
1109         [SD_DEVICE_CHANGE]  = "change",
1110         [SD_DEVICE_MOVE]    = "move",
1111         [SD_DEVICE_ONLINE]  = "online",
1112         [SD_DEVICE_OFFLINE] = "offline",
1113         [SD_DEVICE_BIND]    = "bind",
1114         [SD_DEVICE_UNBIND]  = "unbind",
1115 };
1116 
1117 DEFINE_STRING_TABLE_LOOKUP(device_action, sd_device_action_t);
1118 
dump_device_action_table(void)1119 void dump_device_action_table(void) {
1120         DUMP_STRING_TABLE(device_action, sd_device_action_t, _SD_DEVICE_ACTION_MAX);
1121 }
1122