1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <sys/sysmacros.h>
9 #include "alloc-util.h"
10 #include "device-internal.h"
11 #include "device-private.h"
12 #include "device-util.h"
13 #include "extract-word.h"
19 #include "nulstr-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
23 #include "string-table.h"
24 #include "string-util.h"
27 #include "time-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 int device_add_propertyf(sd_device
*device
, const char *key
, const char *format
, ...) {
51 _cleanup_free_
char *value
= NULL
;
59 return device_add_property(device
, key
, NULL
);
62 r
= vasprintf(&value
, format
, ap
);
68 return device_add_property(device
, key
, value
);
71 void device_set_devlink_priority(sd_device
*device
, int priority
) {
74 device
->devlink_priority
= priority
;
77 void device_set_is_initialized(sd_device
*device
) {
80 device
->is_initialized
= true;
83 int device_ensure_usec_initialized(sd_device
*device
, sd_device
*device_old
) {
88 if (device_old
&& device_old
->usec_initialized
> 0)
89 when
= device_old
->usec_initialized
;
91 when
= now(CLOCK_MONOTONIC
);
93 return device_set_usec_initialized(device
, when
);
96 uint64_t device_get_properties_generation(sd_device
*device
) {
99 return device
->properties_generation
;
102 uint64_t device_get_tags_generation(sd_device
*device
) {
105 return device
->tags_generation
;
108 uint64_t device_get_devlinks_generation(sd_device
*device
) {
111 return device
->devlinks_generation
;
114 int device_get_devnode_mode(sd_device
*device
, mode_t
*ret
) {
119 r
= device_read_uevent_file(device
);
123 r
= device_read_db(device
);
127 if (device
->devmode
== MODE_INVALID
)
131 *ret
= device
->devmode
;
136 int device_get_devnode_uid(sd_device
*device
, uid_t
*ret
) {
141 r
= device_read_uevent_file(device
);
145 r
= device_read_db(device
);
149 if (device
->devuid
== UID_INVALID
)
153 *ret
= device
->devuid
;
158 int device_set_devuid(sd_device
*device
, const char *uid
) {
165 r
= parse_uid(uid
, &u
);
169 r
= device_add_property_internal(device
, "DEVUID", uid
);
178 int device_get_devnode_gid(sd_device
*device
, gid_t
*ret
) {
183 r
= device_read_uevent_file(device
);
187 r
= device_read_db(device
);
191 if (device
->devgid
== GID_INVALID
)
195 *ret
= device
->devgid
;
200 int device_set_devgid(sd_device
*device
, const char *gid
) {
207 r
= parse_gid(gid
, &g
);
211 r
= device_add_property_internal(device
, "DEVGID", gid
);
220 int device_set_action(sd_device
*device
, sd_device_action_t a
) {
224 assert(a
>= 0 && a
< _SD_DEVICE_ACTION_MAX
);
226 r
= device_add_property_internal(device
, "ACTION", device_action_to_string(a
));
235 static int device_set_action_from_string(sd_device
*device
, const char *action
) {
236 sd_device_action_t a
;
241 a
= device_action_from_string(action
);
245 return device_set_action(device
, a
);
248 static int device_set_seqnum(sd_device
*device
, const char *str
) {
255 r
= safe_atou64(str
, &seqnum
);
261 r
= device_add_property_internal(device
, "SEQNUM", str
);
265 device
->seqnum
= seqnum
;
270 static int device_amend(sd_device
*device
, const char *key
, const char *value
) {
277 if (streq(key
, "DEVPATH")) {
280 path
= strjoina("/sys", value
);
282 /* the caller must verify or trust this data (e.g., if it comes from the kernel) */
283 r
= device_set_syspath(device
, path
, false);
285 return log_device_debug_errno(device
, r
, "sd-device: Failed to set syspath to '%s': %m", path
);
286 } else if (streq(key
, "SUBSYSTEM")) {
287 r
= device_set_subsystem(device
, value
);
289 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem to '%s': %m", value
);
290 } else if (streq(key
, "DEVTYPE")) {
291 r
= device_set_devtype(device
, value
);
293 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devtype to '%s': %m", value
);
294 } else if (streq(key
, "DEVNAME")) {
295 r
= device_set_devname(device
, value
);
297 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devname to '%s': %m", value
);
298 } else if (streq(key
, "USEC_INITIALIZED")) {
301 r
= safe_atou64(value
, &t
);
303 return log_device_debug_errno(device
, r
, "sd-device: Failed to parse timestamp '%s': %m", value
);
305 r
= device_set_usec_initialized(device
, t
);
307 return log_device_debug_errno(device
, r
, "sd-device: Failed to set usec-initialized to '%s': %m", value
);
308 } else if (streq(key
, "DRIVER")) {
309 r
= device_set_driver(device
, value
);
311 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver to '%s': %m", value
);
312 } else if (streq(key
, "IFINDEX")) {
313 r
= device_set_ifindex(device
, value
);
315 return log_device_debug_errno(device
, r
, "sd-device: Failed to set ifindex to '%s': %m", value
);
316 } else if (streq(key
, "DEVMODE")) {
317 r
= device_set_devmode(device
, value
);
319 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devmode to '%s': %m", value
);
320 } else if (streq(key
, "DEVUID")) {
321 r
= device_set_devuid(device
, value
);
323 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devuid to '%s': %m", value
);
324 } else if (streq(key
, "DEVGID")) {
325 r
= device_set_devgid(device
, value
);
327 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devgid to '%s': %m", value
);
328 } else if (streq(key
, "ACTION")) {
329 r
= device_set_action_from_string(device
, value
);
331 return log_device_debug_errno(device
, r
, "sd-device: Failed to set action to '%s': %m", value
);
332 } else if (streq(key
, "SEQNUM")) {
333 r
= device_set_seqnum(device
, value
);
335 return log_device_debug_errno(device
, r
, "sd-device: Failed to set SEQNUM to '%s': %m", value
);
336 } else if (streq(key
, "DISKSEQ")) {
337 r
= device_set_diskseq(device
, value
);
339 return log_device_debug_errno(device
, r
, "sd-device: Failed to set DISKSEQ to '%s': %m", value
);
340 } else if (streq(key
, "DEVLINKS")) {
341 for (const char *p
= value
;;) {
342 _cleanup_free_
char *word
= NULL
;
344 /* udev rules may set escaped strings, and sd-device does not modify the input
345 * strings. So, it is also necessary to keep the strings received through
346 * sd-device-monitor. */
347 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_RETAIN_ESCAPE
);
353 r
= device_add_devlink(device
, word
);
355 return log_device_debug_errno(device
, r
, "sd-device: Failed to add devlink '%s': %m", word
);
357 } else if (STR_IN_SET(key
, "TAGS", "CURRENT_TAGS")) {
358 for (const char *p
= value
;;) {
359 _cleanup_free_
char *word
= NULL
;
361 r
= extract_first_word(&p
, &word
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
369 r
= device_add_tag(device
, word
, streq(key
, "CURRENT_TAGS"));
371 return log_device_debug_errno(device
, r
, "sd-device: Failed to add tag '%s': %m", word
);
373 } else if (streq(key
, "UDEV_DATABASE_VERSION")) {
374 r
= safe_atou(value
, &device
->database_version
);
376 return log_device_debug_errno(device
, r
, "sd-device: Failed to parse udev database version '%s': %m", value
);
378 r
= device_add_property_internal(device
, key
, value
);
380 return log_device_debug_errno(device
, r
, "sd-device: Failed to add property '%s=%s': %m", key
, value
);
386 static int device_append(
390 const char **_minor
) {
392 const char *major
= NULL
, *minor
= NULL
;
401 value
= strchr(key
, '=');
403 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
),
404 "sd-device: Not a key-value pair: '%s'", key
);
410 if (streq(key
, "MAJOR"))
412 else if (streq(key
, "MINOR"))
415 r
= device_amend(device
, key
, value
);
429 void device_seal(sd_device
*device
) {
432 device
->sealed
= true;
435 static int device_verify(sd_device
*device
) {
440 if (!device
->devpath
|| !device
->subsystem
|| device
->action
< 0 || device
->seqnum
== 0)
441 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
),
442 "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum.");
444 r
= device_in_subsystem(device
, "drivers");
446 return log_device_debug_errno(device
, r
, "sd-device: Failed to check if the device is a driver: %m");
448 r
= device_set_drivers_subsystem(device
);
450 return log_device_debug_errno(device
, r
,
451 "sd-device: Failed to set driver subsystem: %m");
454 device
->sealed
= true;
459 int device_new_from_strv(sd_device
**ret
, char **strv
) {
460 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
461 const char *major
= NULL
, *minor
= NULL
;
467 r
= device_new_aux(&device
);
471 STRV_FOREACH(key
, strv
) {
472 r
= device_append(device
, *key
, &major
, &minor
);
478 r
= device_set_devnum(device
, major
, minor
);
480 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devnum %s:%s: %m", major
, minor
);
483 r
= device_verify(device
);
487 *ret
= TAKE_PTR(device
);
492 int device_new_from_nulstr(sd_device
**ret
, char *nulstr
, size_t len
) {
493 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
494 const char *major
= NULL
, *minor
= NULL
;
501 r
= device_new_aux(&device
);
505 for (size_t i
= 0; i
< len
; ) {
510 end
= memchr(key
, '\0', len
- i
);
512 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
),
513 "sd-device: Failed to parse nulstr");
517 /* netlink messages for some devices contain an unwanted newline at the end of value.
518 * Let's drop the newline and remaining characters after the newline. */
521 r
= device_append(device
, key
, &major
, &minor
);
527 r
= device_set_devnum(device
, major
, minor
);
529 return log_device_debug_errno(device
, r
, "sd-device: Failed to set devnum %s:%s: %m", major
, minor
);
532 r
= device_verify(device
);
536 *ret
= TAKE_PTR(device
);
541 static int device_update_properties_bufs(sd_device
*device
) {
542 _cleanup_free_
char **buf_strv
= NULL
, *buf_nulstr
= NULL
;
543 size_t nulstr_len
= 0, num
= 0;
547 if (!device
->properties_buf_outdated
)
550 /* append udev database version */
551 buf_nulstr
= newdup(char, "UDEV_DATABASE_VERSION=" STRINGIFY(LATEST_UDEV_DATABASE_VERSION
) "\0",
552 STRLEN("UDEV_DATABASE_VERSION=" STRINGIFY(LATEST_UDEV_DATABASE_VERSION
)) + 2);
556 nulstr_len
+= STRLEN("UDEV_DATABASE_VERSION=" STRINGIFY(LATEST_UDEV_DATABASE_VERSION
)) + 1;
559 FOREACH_DEVICE_PROPERTY(device
, prop
, val
) {
562 len
= strlen(prop
) + 1 + strlen(val
);
564 buf_nulstr
= GREEDY_REALLOC0(buf_nulstr
, nulstr_len
+ len
+ 2);
568 strscpyl(buf_nulstr
+ nulstr_len
, len
+ 1, prop
, "=", val
, NULL
);
569 nulstr_len
+= len
+ 1;
573 /* build buf_strv from buf_nulstr */
574 buf_strv
= new0(char*, num
+ 1);
579 NULSTR_FOREACH(p
, buf_nulstr
)
583 free_and_replace(device
->properties_nulstr
, buf_nulstr
);
584 device
->properties_nulstr_len
= nulstr_len
;
585 free_and_replace(device
->properties_strv
, buf_strv
);
587 device
->properties_buf_outdated
= false;
591 int device_get_properties_nulstr(sd_device
*device
, const char **ret_nulstr
, size_t *ret_len
) {
596 r
= device_update_properties_bufs(device
);
601 *ret_nulstr
= device
->properties_nulstr
;
603 *ret_len
= device
->properties_nulstr_len
;
608 int device_get_properties_strv(sd_device
*device
, char ***ret
) {
613 r
= device_update_properties_bufs(device
);
618 *ret
= device
->properties_strv
;
623 int device_get_devlink_priority(sd_device
*device
, int *ret
) {
628 r
= device_read_db(device
);
633 *ret
= device
->devlink_priority
;
638 int device_clone_with_db(sd_device
*device
, sd_device
**ret
) {
639 _cleanup_(sd_device_unrefp
) sd_device
*dest
= NULL
;
640 const char *key
, *val
;
646 /* The device may be already removed. Let's copy minimal set of information that was obtained through
649 r
= device_new_aux(&dest
);
653 /* Seal device to prevent reading the uevent file, as the device may have been already removed. */
656 /* Copy syspath, then also devname, sysname or sysnum can be obtained. */
657 r
= device_set_syspath(dest
, device
->syspath
, false);
661 /* Copy other information stored in database. Here, do not use FOREACH_DEVICE_PROPERTY() and
662 * sd_device_get_property_value(), as they calls device_properties_prepare() ->
663 * device_read_uevent_file(), but as commented in the above, the device may be already removed and
664 * reading uevent file may fail. */
665 ORDERED_HASHMAP_FOREACH_KEY(val
, key
, device
->properties
) {
666 if (streq(key
, "MINOR"))
669 if (streq(key
, "MAJOR")) {
670 const char *minor
= NULL
;
672 minor
= ordered_hashmap_get(device
->properties
, "MINOR");
673 r
= device_set_devnum(dest
, val
, minor
);
675 r
= device_amend(dest
, key
, val
);
679 if (streq(key
, "SUBSYSTEM") && streq(val
, "drivers")) {
680 r
= free_and_strdup(&dest
->driver_subsystem
, device
->driver_subsystem
);
686 /* Finally, read the udev database. */
687 r
= device_read_db_internal(dest
, /* force = */ true);
691 *ret
= TAKE_PTR(dest
);
695 void device_cleanup_tags(sd_device
*device
) {
698 device
->all_tags
= set_free(device
->all_tags
);
699 device
->current_tags
= set_free(device
->current_tags
);
700 device
->property_tags_outdated
= true;
701 device
->tags_generation
++;
704 void device_cleanup_devlinks(sd_device
*device
) {
707 set_free(device
->devlinks
);
708 device
->devlinks
= NULL
;
709 device
->property_devlinks_outdated
= true;
710 device
->devlinks_generation
++;
713 void device_remove_tag(sd_device
*device
, const char *tag
) {
717 free(set_remove(device
->current_tags
, tag
));
718 device
->property_tags_outdated
= true;
719 device
->tags_generation
++;
722 static int device_tag(sd_device
*device
, const char *tag
, bool add
) {
730 r
= sd_device_get_device_id(device
, &id
);
734 path
= strjoina("/run/udev/tags/", tag
, "/", id
);
737 return touch_file(path
, true, USEC_INFINITY
, UID_INVALID
, GID_INVALID
, 0444);
739 if (unlink(path
) < 0 && errno
!= ENOENT
)
745 int device_tag_index(sd_device
*device
, sd_device
*device_old
, bool add
) {
748 if (add
&& device_old
)
749 /* delete possible left-over tags */
750 FOREACH_DEVICE_TAG(device_old
, tag
)
751 if (!sd_device_has_tag(device
, tag
)) {
752 k
= device_tag(device_old
, tag
, false);
757 FOREACH_DEVICE_TAG(device
, tag
) {
758 k
= device_tag(device
, tag
, add
);
766 static bool device_has_info(sd_device
*device
) {
769 if (!set_isempty(device
->devlinks
))
772 if (device
->devlink_priority
!= 0)
775 if (!ordered_hashmap_isempty(device
->properties_db
))
778 if (!set_isempty(device
->all_tags
))
781 if (!set_isempty(device
->current_tags
))
787 bool device_should_have_db(sd_device
*device
) {
790 if (device_has_info(device
))
793 if (major(device
->devnum
) != 0)
796 if (device
->ifindex
!= 0)
802 void device_set_db_persist(sd_device
*device
) {
805 device
->db_persist
= true;
808 static int device_get_db_path(sd_device
*device
, char **ret
) {
816 r
= sd_device_get_device_id(device
, &id
);
820 path
= path_join("/run/udev/data/", id
);
828 int device_has_db(sd_device
*device
) {
829 _cleanup_free_
char *path
= NULL
;
834 r
= device_get_db_path(device
, &path
);
838 return access(path
, F_OK
) >= 0;
841 int device_update_db(sd_device
*device
) {
842 _cleanup_(unlink_and_freep
) char *path
= NULL
, *path_tmp
= NULL
;
843 _cleanup_fclose_
FILE *f
= NULL
;
848 /* do not store anything for otherwise empty devices */
849 if (!device_should_have_db(device
))
850 return device_delete_db(device
);
852 r
= device_get_db_path(device
, &path
);
856 /* write a database file */
857 r
= mkdir_parents(path
, 0755);
859 return log_device_debug_errno(device
, r
,
860 "sd-device: Failed to create parent directories of '%s': %m",
863 r
= fopen_temporary(path
, &f
, &path_tmp
);
865 return log_device_debug_errno(device
, r
,
866 "sd-device: Failed to create temporary file for database file '%s': %m",
869 /* set 'sticky' bit to indicate that we should not clean the database when we transition from initrd
870 * to the real root */
871 if (fchmod(fileno(f
), device
->db_persist
? 01644 : 0644) < 0)
872 return log_device_debug_errno(device
, errno
,
873 "sd-device: Failed to chmod temporary database file '%s': %m",
876 if (device_has_info(device
)) {
877 const char *property
, *value
, *ct
;
879 if (major(device
->devnum
) > 0) {
880 FOREACH_DEVICE_DEVLINK(device
, devlink
)
881 fprintf(f
, "S:%s\n", devlink
+ STRLEN("/dev/"));
883 if (device
->devlink_priority
!= 0)
884 fprintf(f
, "L:%i\n", device
->devlink_priority
);
887 if (device
->usec_initialized
> 0)
888 fprintf(f
, "I:"USEC_FMT
"\n", device
->usec_initialized
);
890 ORDERED_HASHMAP_FOREACH_KEY(value
, property
, device
->properties_db
)
891 fprintf(f
, "E:%s=%s\n", property
, value
);
893 FOREACH_DEVICE_TAG(device
, tag
)
894 fprintf(f
, "G:%s\n", tag
); /* Any tag */
896 SET_FOREACH(ct
, device
->current_tags
)
897 fprintf(f
, "Q:%s\n", ct
); /* Current tag */
899 /* Always write the latest database version here, instead of the value stored in
900 * device->database_version, as which may be 0. */
901 fputs("V:" STRINGIFY(LATEST_UDEV_DATABASE_VERSION
) "\n", f
);
904 r
= fflush_and_check(f
);
906 return log_device_debug_errno(device
, r
,
907 "sd-device: Failed to flush temporary database file '%s': %m",
910 if (rename(path_tmp
, path
) < 0)
911 return log_device_debug_errno(device
, errno
,
912 "sd-device: Failed to rename temporary database file '%s' to '%s': %m",
915 log_device_debug(device
, "sd-device: Created database file '%s' for '%s'.", path
, device
->devpath
);
917 path_tmp
= mfree(path_tmp
);
923 int device_delete_db(sd_device
*device
) {
924 _cleanup_free_
char *path
= NULL
;
929 r
= device_get_db_path(device
, &path
);
933 if (unlink(path
) < 0 && errno
!= ENOENT
)
939 int device_read_db_internal(sd_device
*device
, bool force
) {
940 _cleanup_free_
char *path
= NULL
;
945 if (device
->db_loaded
|| (!force
&& device
->sealed
))
948 r
= device_get_db_path(device
, &path
);
952 return device_read_db_internal_filename(device
, path
);
955 static const char* const device_action_table
[_SD_DEVICE_ACTION_MAX
] = {
956 [SD_DEVICE_ADD
] = "add",
957 [SD_DEVICE_REMOVE
] = "remove",
958 [SD_DEVICE_CHANGE
] = "change",
959 [SD_DEVICE_MOVE
] = "move",
960 [SD_DEVICE_ONLINE
] = "online",
961 [SD_DEVICE_OFFLINE
] = "offline",
962 [SD_DEVICE_BIND
] = "bind",
963 [SD_DEVICE_UNBIND
] = "unbind",
966 DEFINE_STRING_TABLE_LOOKUP(device_action
, sd_device_action_t
);