1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "alloc-util.h"
10 #include "device-internal.h"
11 #include "device-private.h"
12 #include "device-util.h"
19 #include "nulstr-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
23 #include "stdio-util.h"
24 #include "string-table.h"
25 #include "string-util.h"
28 #include "tmpfile-util.h"
29 #include "user-util.h"
31 int device_add_property(sd_device
*device
, const char *key
, const char *value
) {
37 r
= device_add_property_aux(device
, key
, value
, false);
42 r
= device_add_property_aux(device
, key
, value
, true);
50 void device_set_devlink_priority(sd_device
*device
, int priority
) {
53 device
->devlink_priority
= priority
;
56 void device_set_is_initialized(sd_device
*device
) {
59 device
->is_initialized
= true;
62 int device_ensure_usec_initialized(sd_device
*device
, sd_device
*device_old
) {
67 if (device_old
&& device_old
->usec_initialized
> 0)
68 when
= device_old
->usec_initialized
;
70 when
= now(CLOCK_MONOTONIC
);
72 return device_set_usec_initialized(device
, when
);
75 uint64_t device_get_properties_generation(sd_device
*device
) {
78 return device
->properties_generation
;
81 uint64_t device_get_tags_generation(sd_device
*device
) {
84 return device
->tags_generation
;
87 uint64_t device_get_devlinks_generation(sd_device
*device
) {
90 return device
->devlinks_generation
;
93 int device_get_devnode_mode(sd_device
*device
, mode_t
*mode
) {
98 r
= device_read_db(device
);
102 if (device
->devmode
== MODE_INVALID
)
106 *mode
= device
->devmode
;
111 int device_get_devnode_uid(sd_device
*device
, uid_t
*uid
) {
116 r
= device_read_db(device
);
120 if (device
->devuid
== UID_INVALID
)
124 *uid
= device
->devuid
;
129 static int device_set_devuid(sd_device
*device
, const char *uid
) {
136 r
= safe_atou(uid
, &u
);
140 r
= device_add_property_internal(device
, "DEVUID", uid
);
149 int device_get_devnode_gid(sd_device
*device
, gid_t
*gid
) {
154 r
= device_read_db(device
);
158 if (device
->devgid
== GID_INVALID
)
162 *gid
= device
->devgid
;
167 static int device_set_devgid(sd_device
*device
, const char *gid
) {
174 r
= safe_atou(gid
, &g
);
178 r
= device_add_property_internal(device
, "DEVGID", gid
);
187 int device_set_action(sd_device
*device
, sd_device_action_t a
) {
191 assert(a
>= 0 && a
< _SD_DEVICE_ACTION_MAX
);
193 r
= device_add_property_internal(device
, "ACTION", device_action_to_string(a
));
202 static int device_set_action_from_string(sd_device
*device
, const char *action
) {
203 sd_device_action_t a
;
208 a
= device_action_from_string(action
);
212 return device_set_action(device
, a
);
215 static int device_set_seqnum(sd_device
*device
, const char *str
) {
222 r
= safe_atou64(str
, &seqnum
);
228 r
= device_add_property_internal(device
, "SEQNUM", str
);
232 device
->seqnum
= seqnum
;
237 static int device_set_diskseq(sd_device
*device
, const char *str
) {
244 r
= safe_atou64(str
, &diskseq
);
250 r
= device_add_property_internal(device
, "DISKSEQ", str
);
254 device
->diskseq
= diskseq
;
259 static int device_amend(sd_device
*device
, const char *key
, const char *value
) {
266 if (streq(key
, "DEVPATH")) {
269 path
= strjoina("/sys", value
);
271 /* the caller must verify or trust this data (e.g., if it comes from the kernel) */
272 r
= device_set_syspath(device
, path
, false);
274 return log_device_debug_errno(device
, r
, "sd-device: Failed to set syspath to '%s': %m", path
);
275 } else if (streq(key
, "SUBSYSTEM")) {
276 r
= device_set_subsystem(device
, value
);
278 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem to '%s': %m", value
);
279 } else if (streq(key
, "DEVTYPE")) {
280 r
= device_set_devtype(device
, value
);
282 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devtype to '%s': %m", value
);
283 } else if (streq(key
, "DEVNAME")) {
284 r
= device_set_devname(device
, value
);
286 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devname to '%s': %m", value
);
287 } else if (streq(key
, "USEC_INITIALIZED")) {
290 r
= safe_atou64(value
, &t
);
292 return log_device_debug_errno(device
, r
, "sd-device: Failed to parse timestamp '%s': %m", value
);
294 r
= device_set_usec_initialized(device
, t
);
296 return log_device_debug_errno(device
, r
, "sd-device: Failed to set usec-initialized to '%s': %m", value
);
297 } else if (streq(key
, "DRIVER")) {
298 r
= device_set_driver(device
, value
);
300 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver to '%s': %m", value
);
301 } else if (streq(key
, "IFINDEX")) {
302 r
= device_set_ifindex(device
, value
);
304 return log_device_debug_errno(device
, r
, "sd-device: Failed to set ifindex to '%s': %m", value
);
305 } else if (streq(key
, "DEVMODE")) {
306 r
= device_set_devmode(device
, value
);
308 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devmode to '%s': %m", value
);
309 } else if (streq(key
, "DEVUID")) {
310 r
= device_set_devuid(device
, value
);
312 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devuid to '%s': %m", value
);
313 } else if (streq(key
, "DEVGID")) {
314 r
= device_set_devgid(device
, value
);
316 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devgid to '%s': %m", value
);
317 } else if (streq(key
, "ACTION")) {
318 r
= device_set_action_from_string(device
, value
);
320 return log_device_debug_errno(device
, r
, "sd-device: Failed to set action to '%s': %m", value
);
321 } else if (streq(key
, "SEQNUM")) {
322 r
= device_set_seqnum(device
, value
);
324 return log_device_debug_errno(device
, r
, "sd-device: Failed to set SEQNUM to '%s': %m", value
);
325 } else if (streq(key
, "DISKSEQ")) {
326 r
= device_set_diskseq(device
, value
);
328 return log_device_debug_errno(device
, r
, "sd-device: Failed to set DISKSEQ to '%s': %m", value
);
329 } else if (streq(key
, "DEVLINKS")) {
330 for (const char *p
= value
;;) {
331 _cleanup_free_
char *word
= NULL
;
333 /* udev rules may set escaped strings, and sd-device does not modify the input
334 * strings. So, it is also necessary to keep the strings received through
335 * sd-device-monitor. */
336 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_RETAIN_ESCAPE
);
342 r
= device_add_devlink(device
, word
);
344 return log_device_debug_errno(device
, r
, "sd-device: Failed to add devlink '%s': %m", word
);
346 } else if (STR_IN_SET(key
, "TAGS", "CURRENT_TAGS")) {
347 for (const char *p
= value
;;) {
348 _cleanup_free_
char *word
= NULL
;
350 r
= extract_first_word(&p
, &word
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
356 r
= device_add_tag(device
, word
, streq(key
, "CURRENT_TAGS"));
358 return log_device_debug_errno(device
, r
, "sd-device: Failed to add tag '%s': %m", word
);
361 r
= device_add_property_internal(device
, key
, value
);
363 return log_device_debug_errno(device
, r
, "sd-device: Failed to add property '%s=%s': %m", key
, value
);
369 static int device_append(
373 const char **_minor
) {
375 const char *major
= NULL
, *minor
= NULL
;
384 value
= strchr(key
, '=');
386 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
),
387 "sd-device: Not a key-value pair: '%s'", key
);
393 if (streq(key
, "MAJOR"))
395 else if (streq(key
, "MINOR"))
398 r
= device_amend(device
, key
, value
);
412 void device_seal(sd_device
*device
) {
415 device
->sealed
= true;
418 static int device_verify(sd_device
*device
) {
423 if (!device
->devpath
|| !device
->subsystem
|| device
->action
< 0 || device
->seqnum
== 0)
424 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
),
425 "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum.");
427 if (streq(device
->subsystem
, "drivers")) {
428 r
= device_set_drivers_subsystem(device
);
433 device
->sealed
= true;
438 int device_new_from_strv(sd_device
**ret
, char **strv
) {
439 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
441 const char *major
= NULL
, *minor
= NULL
;
447 r
= device_new_aux(&device
);
451 STRV_FOREACH(key
, strv
) {
452 r
= device_append(device
, *key
, &major
, &minor
);
458 r
= device_set_devnum(device
, major
, minor
);
460 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devnum %s:%s: %m", major
, minor
);
463 r
= device_verify(device
);
467 *ret
= TAKE_PTR(device
);
472 int device_new_from_nulstr(sd_device
**ret
, uint8_t *nulstr
, size_t len
) {
473 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
474 const char *major
= NULL
, *minor
= NULL
;
481 r
= device_new_aux(&device
);
485 for (size_t i
= 0; i
< len
; ) {
489 key
= (char*) &nulstr
[i
];
490 end
= memchr(key
, '\0', len
- i
);
492 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
),
493 "sd-device: Failed to parse nulstr");
497 /* netlink messages for some devices contain an unwanted newline at the end of value.
498 * Let's drop the newline and remaining characters after the newline. */
501 r
= device_append(device
, key
, &major
, &minor
);
507 r
= device_set_devnum(device
, major
, minor
);
509 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devnum %s:%s: %m", major
, minor
);
512 r
= device_verify(device
);
516 *ret
= TAKE_PTR(device
);
521 static int device_update_properties_bufs(sd_device
*device
) {
522 const char *val
, *prop
;
523 _cleanup_free_
char **buf_strv
= NULL
;
524 _cleanup_free_
uint8_t *buf_nulstr
= NULL
;
525 size_t nulstr_len
= 0, num
= 0, i
= 0;
529 if (!device
->properties_buf_outdated
)
532 FOREACH_DEVICE_PROPERTY(device
, prop
, val
) {
535 len
= strlen(prop
) + 1 + strlen(val
);
537 buf_nulstr
= GREEDY_REALLOC0(buf_nulstr
, nulstr_len
+ len
+ 2);
541 strscpyl((char *)buf_nulstr
+ nulstr_len
, len
+ 1, prop
, "=", val
, NULL
);
542 nulstr_len
+= len
+ 1;
546 /* build buf_strv from buf_nulstr */
547 buf_strv
= new0(char *, num
+ 1);
551 NULSTR_FOREACH(val
, (char*) buf_nulstr
) {
552 buf_strv
[i
] = (char *) val
;
557 free_and_replace(device
->properties_nulstr
, buf_nulstr
);
558 device
->properties_nulstr_len
= nulstr_len
;
559 free_and_replace(device
->properties_strv
, buf_strv
);
561 device
->properties_buf_outdated
= false;
566 int device_get_properties_nulstr(sd_device
*device
, const uint8_t **nulstr
, size_t *len
) {
573 r
= device_update_properties_bufs(device
);
577 *nulstr
= device
->properties_nulstr
;
578 *len
= device
->properties_nulstr_len
;
583 int device_get_properties_strv(sd_device
*device
, char ***strv
) {
589 r
= device_update_properties_bufs(device
);
593 *strv
= device
->properties_strv
;
598 int device_get_devlink_priority(sd_device
*device
, int *priority
) {
604 r
= device_read_db(device
);
608 *priority
= device
->devlink_priority
;
613 int device_get_watch_handle(sd_device
*device
) {
614 char path_wd
[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
615 _cleanup_free_
char *buf
= NULL
;
616 const char *id
, *path_id
;
621 if (device
->watch_handle
>= 0)
622 return device
->watch_handle
;
624 r
= device_get_device_id(device
, &id
);
628 path_id
= strjoina("/run/udev/watch/", id
);
629 r
= readlink_malloc(path_id
, &buf
);
633 r
= safe_atoi(buf
, &wd
);
641 xsprintf(path_wd
, "/run/udev/watch/%d", wd
);
642 r
= readlink_malloc(path_wd
, &buf
);
649 return device
->watch_handle
= wd
;
652 static void device_remove_watch_handle(sd_device
*device
) {
658 /* First, remove the symlink from handle to device id. */
659 wd
= device_get_watch_handle(device
);
661 char path_wd
[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
663 xsprintf(path_wd
, "/run/udev/watch/%d", wd
);
664 if (unlink(path_wd
) < 0 && errno
!= ENOENT
)
665 log_device_debug_errno(device
, errno
,
666 "sd-device: failed to remove %s, ignoring: %m",
670 /* Next, remove the symlink from device id to handle. */
671 if (device_get_device_id(device
, &id
) >= 0) {
674 path_id
= strjoina("/run/udev/watch/", id
);
675 if (unlink(path_id
) < 0 && errno
!= ENOENT
)
676 log_device_debug_errno(device
, errno
,
677 "sd-device: failed to remove %s, ignoring: %m",
681 device
->watch_handle
= -1;
684 int device_set_watch_handle(sd_device
*device
, int wd
) {
685 char path_wd
[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
686 const char *id
, *path_id
;
691 if (wd
>= 0 && wd
== device_get_watch_handle(device
))
694 device_remove_watch_handle(device
);
697 /* negative wd means that the caller requests to clear saved watch handle. */
700 r
= device_get_device_id(device
, &id
);
704 path_id
= strjoina("/run/udev/watch/", id
);
705 xsprintf(path_wd
, "/run/udev/watch/%d", wd
);
707 r
= mkdir_parents(path_wd
, 0755);
711 if (symlink(id
, path_wd
) < 0)
714 if (symlink(path_wd
+ STRLEN("/run/udev/watch/"), path_id
) < 0) {
716 if (unlink(path_wd
) < 0 && errno
!= ENOENT
)
717 log_device_debug_errno(device
, errno
,
718 "sd-device: failed to remove %s, ignoring: %m",
723 device
->watch_handle
= wd
;
728 int device_new_from_watch_handle_at(sd_device
**ret
, int dirfd
, int wd
) {
729 char path_wd
[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
730 _cleanup_free_
char *id
= NULL
;
739 xsprintf(path_wd
, "%d", wd
);
740 r
= readlinkat_malloc(dirfd
, path_wd
, &id
);
742 xsprintf(path_wd
, "/run/udev/watch/%d", wd
);
743 r
= readlink_malloc(path_wd
, &id
);
748 return sd_device_new_from_device_id(ret
, id
);
751 int device_rename(sd_device
*device
, const char *name
) {
752 _cleanup_free_
char *dirname
= NULL
;
753 const char *new_syspath
, *interface
;
759 dirname
= dirname_malloc(device
->syspath
);
763 new_syspath
= prefix_roota(dirname
, name
);
765 /* the user must trust that the new name is correct */
766 r
= device_set_syspath(device
, new_syspath
, false);
770 r
= sd_device_get_property_value(device
, "INTERFACE", &interface
);
772 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
773 r
= device_add_property_internal(device
, "INTERFACE_OLD", interface
);
777 r
= device_add_property_internal(device
, "INTERFACE", name
);
780 } else if (r
!= -ENOENT
)
786 int device_shallow_clone(sd_device
*old_device
, sd_device
**new_device
) {
787 _cleanup_(sd_device_unrefp
) sd_device
*ret
= NULL
;
794 r
= device_new_aux(&ret
);
798 r
= device_set_syspath(ret
, old_device
->syspath
, false);
802 (void) sd_device_get_subsystem(old_device
, &val
);
803 r
= device_set_subsystem(ret
, val
);
806 if (streq_ptr(val
, "drivers")) {
807 r
= free_and_strdup(&ret
->driver_subsystem
, old_device
->driver_subsystem
);
812 /* The device may be already removed. Let's copy minimal set of information to make
813 * device_get_device_id() work without uevent file. */
815 if (sd_device_get_property_value(old_device
, "IFINDEX", &val
) >= 0) {
816 r
= device_set_ifindex(ret
, val
);
821 if (sd_device_get_property_value(old_device
, "MAJOR", &val
) >= 0) {
822 const char *minor
= NULL
;
824 (void) sd_device_get_property_value(old_device
, "MINOR", &minor
);
825 r
= device_set_devnum(ret
, val
, minor
);
830 /* And then read uevent file, but ignore errors, as some devices seem to return a spurious
831 * error on read, e.g. -ENODEV, and even if ifindex or devnum is set in the above,
832 * sd_device_get_ifindex() or sd_device_get_devnum() fails. See. #19788. */
833 (void) device_read_uevent_file(ret
);
835 *new_device
= TAKE_PTR(ret
);
839 int device_clone_with_db(sd_device
*old_device
, sd_device
**new_device
) {
840 _cleanup_(sd_device_unrefp
) sd_device
*ret
= NULL
;
846 r
= device_shallow_clone(old_device
, &ret
);
850 r
= device_read_db(ret
);
856 *new_device
= TAKE_PTR(ret
);
861 int device_copy_properties(sd_device
*device_dst
, sd_device
*device_src
) {
862 const char *property
, *value
;
868 r
= device_properties_prepare(device_src
);
872 ORDERED_HASHMAP_FOREACH_KEY(value
, property
, device_src
->properties_db
) {
873 r
= device_add_property_aux(device_dst
, property
, value
, true);
878 ORDERED_HASHMAP_FOREACH_KEY(value
, property
, device_src
->properties
) {
879 r
= device_add_property_aux(device_dst
, property
, value
, false);
887 void device_cleanup_tags(sd_device
*device
) {
890 device
->all_tags
= set_free_free(device
->all_tags
);
891 device
->current_tags
= set_free_free(device
->current_tags
);
892 device
->property_tags_outdated
= true;
893 device
->tags_generation
++;
896 void device_cleanup_devlinks(sd_device
*device
) {
899 set_free_free(device
->devlinks
);
900 device
->devlinks
= NULL
;
901 device
->property_devlinks_outdated
= true;
902 device
->devlinks_generation
++;
905 void device_remove_tag(sd_device
*device
, const char *tag
) {
909 free(set_remove(device
->current_tags
, tag
));
910 device
->property_tags_outdated
= true;
911 device
->tags_generation
++;
914 static int device_tag(sd_device
*device
, const char *tag
, bool add
) {
922 r
= device_get_device_id(device
, &id
);
926 path
= strjoina("/run/udev/tags/", tag
, "/", id
);
929 r
= touch_file(path
, true, USEC_INFINITY
, UID_INVALID
, GID_INVALID
, 0444);
934 if (r
< 0 && errno
!= ENOENT
)
941 int device_tag_index(sd_device
*device
, sd_device
*device_old
, bool add
) {
945 if (add
&& device_old
) {
946 /* delete possible left-over tags */
947 FOREACH_DEVICE_TAG(device_old
, tag
) {
948 if (!sd_device_has_tag(device
, tag
)) {
949 k
= device_tag(device_old
, tag
, false);
956 FOREACH_DEVICE_TAG(device
, tag
) {
957 k
= device_tag(device
, tag
, add
);
965 static bool device_has_info(sd_device
*device
) {
968 if (!set_isempty(device
->devlinks
))
971 if (device
->devlink_priority
!= 0)
974 if (!ordered_hashmap_isempty(device
->properties_db
))
977 if (!set_isempty(device
->all_tags
))
980 if (!set_isempty(device
->current_tags
))
986 void device_set_db_persist(sd_device
*device
) {
989 device
->db_persist
= true;
992 int device_update_db(sd_device
*device
) {
995 _cleanup_fclose_
FILE *f
= NULL
;
996 _cleanup_free_
char *path_tmp
= NULL
;
1002 has_info
= device_has_info(device
);
1004 r
= device_get_device_id(device
, &id
);
1008 path
= strjoina("/run/udev/data/", id
);
1010 /* do not store anything for otherwise empty devices */
1011 if (!has_info
&& major(device
->devnum
) == 0 && device
->ifindex
== 0) {
1013 if (r
< 0 && errno
!= ENOENT
)
1019 /* write a database file */
1020 r
= mkdir_parents(path
, 0755);
1024 r
= fopen_temporary(path
, &f
, &path_tmp
);
1029 * set 'sticky' bit to indicate that we should not clean the
1030 * database when we transition from initramfs to the real root
1032 if (fchmod(fileno(f
), device
->db_persist
? 01644 : 0644) < 0) {
1038 const char *property
, *value
, *tag
;
1040 if (major(device
->devnum
) > 0) {
1041 const char *devlink
;
1043 FOREACH_DEVICE_DEVLINK(device
, devlink
)
1044 fprintf(f
, "S:%s\n", devlink
+ STRLEN("/dev/"));
1046 if (device
->devlink_priority
!= 0)
1047 fprintf(f
, "L:%i\n", device
->devlink_priority
);
1050 if (device
->usec_initialized
> 0)
1051 fprintf(f
, "I:"USEC_FMT
"\n", device
->usec_initialized
);
1053 ORDERED_HASHMAP_FOREACH_KEY(value
, property
, device
->properties_db
)
1054 fprintf(f
, "E:%s=%s\n", property
, value
);
1056 FOREACH_DEVICE_TAG(device
, tag
)
1057 fprintf(f
, "G:%s\n", tag
); /* Any tag */
1059 SET_FOREACH(tag
, device
->current_tags
)
1060 fprintf(f
, "Q:%s\n", tag
); /* Current tag */
1062 /* Always write the latest database version here, instead of the value stored in
1063 * device->database_version, as which may be 0. */
1064 fputs("V:" STRINGIFY(LATEST_UDEV_DATABASE_VERSION
) "\n", f
);
1067 r
= fflush_and_check(f
);
1071 if (rename(path_tmp
, path
) < 0) {
1076 log_device_debug(device
, "sd-device: Created %s file '%s' for '%s'", has_info
? "db" : "empty",
1077 path
, device
->devpath
);
1082 (void) unlink(path
);
1083 (void) unlink(path_tmp
);
1085 return log_device_debug_errno(device
, r
, "sd-device: Failed to create %s file '%s' for '%s'", has_info
? "db" : "empty", path
, device
->devpath
);
1088 int device_delete_db(sd_device
*device
) {
1095 r
= device_get_device_id(device
, &id
);
1099 path
= strjoina("/run/udev/data/", id
);
1102 if (r
< 0 && errno
!= ENOENT
)
1108 static const char* const device_action_table
[_SD_DEVICE_ACTION_MAX
] = {
1109 [SD_DEVICE_ADD
] = "add",
1110 [SD_DEVICE_REMOVE
] = "remove",
1111 [SD_DEVICE_CHANGE
] = "change",
1112 [SD_DEVICE_MOVE
] = "move",
1113 [SD_DEVICE_ONLINE
] = "online",
1114 [SD_DEVICE_OFFLINE
] = "offline",
1115 [SD_DEVICE_BIND
] = "bind",
1116 [SD_DEVICE_UNBIND
] = "unbind",
1119 DEFINE_STRING_TABLE_LOOKUP(device_action
, sd_device_action_t
);
1121 void dump_device_action_table(void) {
1122 DUMP_STRING_TABLE(device_action
, sd_device_action_t
, _SD_DEVICE_ACTION_MAX
);