2 This file is part of systemd.
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
22 #include <sys/types.h>
28 #include "path-util.h"
36 #include "sd-device.h"
38 #include "device-util.h"
39 #include "device-internal.h"
40 #include "device-private.h"
42 int device_add_property(sd_device *device, const char *key, const char *value) {
48 r = device_add_property_aux(device, key, value, false);
53 r = device_add_property_aux(device, key, value, true);
61 static int device_add_property_internal_from_string(sd_device *device, const char *str) {
62 _cleanup_free_ char *key = NULL;
72 value = strchr(key, '=');
81 return device_add_property_internal(device, key, value);
84 static int handle_db_line(sd_device *device, char key, const char *value) {
93 path = strjoina("/dev/", value);
94 r = device_add_devlink(device, path);
100 r = safe_atoi(value, &device->devlink_priority);
106 r = device_add_property_internal_from_string(device, value);
112 r = device_add_tag(device, value);
118 r = safe_atoi(value, &device->watch_handle);
124 r = device_set_usec_initialized(device, value);
130 log_debug("device db: unknown key '%c'", key);
136 void device_set_devlink_priority(sd_device *device, int priority) {
139 device->devlink_priority = priority;
142 void device_set_is_initialized(sd_device *device) {
145 device->is_initialized = true;
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;
155 if (device_old && device_old->usec_initialized > 0)
156 usec_initialized = device_old->usec_initialized;
158 usec_initialized = now(CLOCK_MONOTONIC);
160 r = snprintf(num, sizeof(num), USEC_FMT, usec_initialized);
164 r = device_set_usec_initialized(device, num);
171 static int device_read_db(sd_device *device) {
172 _cleanup_free_ char *db = NULL;
174 const char *id, *value;
190 if (device->db_loaded || device->sealed)
193 r = device_get_id_filename(device, &id);
197 path = strjoina("/run/udev/data/", id);
199 r = read_full_file(path, &db, &db_len);
204 log_debug("sd-device: failed to read db '%s': %s", path, strerror(-r));
209 /* devices with a database entry are initialized */
210 device_set_is_initialized(device);
212 for (i = 0; i < db_len; i++) {
215 if (!strchr(NEWLINE, db[i])) {
224 log_debug("sd-device: ignoring invalid db entry with key '%c'", key);
226 state = INVALID_LINE;
241 if (strchr(NEWLINE, db[i]))
246 if (strchr(NEWLINE, db[i])) {
248 r = handle_db_line(device, key, value);
250 log_debug("sd-device: failed to handle db entry '%c:%s': %s", key, value, strerror(-r));
257 assert_not_reached("invalid state when parsing db");
261 device->db_loaded = true;
266 uint64_t device_get_properties_generation(sd_device *device) {
269 return device->properties_generation;
272 uint64_t device_get_tags_generation(sd_device *device) {
275 return device->tags_generation;
278 uint64_t device_get_devlinks_generation(sd_device *device) {
281 return device->devlinks_generation;
284 int device_get_devnode_mode(sd_device *device, mode_t *mode) {
290 r = device_read_db(device);
294 *mode = device->devmode;
299 int device_get_devnode_uid(sd_device *device, uid_t *uid) {
305 r = device_read_db(device);
309 *uid = device->devuid;
314 static int device_set_devuid(sd_device *device, const char *uid) {
321 r = safe_atou(uid, &u);
325 r = device_add_property_internal(device, "DEVUID", uid);
334 int device_get_devnode_gid(sd_device *device, gid_t *gid) {
340 r = device_read_db(device);
344 *gid = device->devgid;
349 static int device_set_devgid(sd_device *device, const char *gid) {
356 r = safe_atou(gid, &g);
360 r = device_add_property_internal(device, "DEVGID", gid);
369 static int device_amend(sd_device *device, const char *key, const char *value) {
376 if (streq(key, "DEVPATH")) {
379 path = strjoina("/sys", value);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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;
425 FOREACH_WORD(word, l, value, state) {
428 devlink = strndupa(word, l);
430 r = device_add_devlink(device, devlink);
432 return log_debug_errno(r, "sd-device: could not add devlink '%s': %m", devlink);
434 } else if (streq(key, "TAGS")) {
435 const char *word, *state;
438 FOREACH_WORD_SEPARATOR(word, l, value, ":", state) {
441 tag = strndupa(word, l);
443 r = device_add_tag(device, tag);
445 return log_debug_errno(r, "sd-device: could not add tag '%s': %m", tag);
448 r = device_add_property_internal(device, key, value);
450 return log_debug_errno(r, "sd-device: could not add property '%s=%s': %m", key, value);
456 static const char* const device_action_table[_DEVICE_ACTION_MAX] = {
457 [DEVICE_ACTION_ADD] = "add",
458 [DEVICE_ACTION_REMOVE] = "remove",
459 [DEVICE_ACTION_CHANGE] = "change",
460 [DEVICE_ACTION_MOVE] = "move",
461 [DEVICE_ACTION_ONLINE] = "online",
462 [DEVICE_ACTION_OFFLINE] = "offline",
465 DEFINE_STRING_TABLE_LOOKUP(device_action, DeviceAction);
467 static int device_append(sd_device *device, char *key, const char **_major, const char **_minor, uint64_t *_seqnum,
468 DeviceAction *_action) {
469 DeviceAction action = _DEVICE_ACTION_INVALID;
471 const char *major = NULL, *minor = NULL;
482 value = strchr(key, '=');
484 log_debug("sd-device: not a key-value pair: '%s'", key);
492 if (streq(key, "MAJOR"))
494 else if (streq(key, "MINOR"))
497 if (streq(key, "ACTION")) {
498 action = device_action_from_string(value);
499 if (action == _DEVICE_ACTION_INVALID)
501 } else if (streq(key, "SEQNUM")) {
502 r = safe_atou64(value, &seqnum);
505 else if (seqnum == 0)
506 /* kernel only sends seqnum > 0 */
510 r = device_amend(device, key, value);
521 if (action != _DEVICE_ACTION_INVALID)
530 void device_seal(sd_device *device) {
533 device->sealed = true;
536 static int device_verify(sd_device *device, DeviceAction action, uint64_t seqnum) {
539 if (!device->devpath || !device->subsystem || action == _DEVICE_ACTION_INVALID || seqnum == 0) {
540 log_debug("sd-device: device created from strv lacks devpath, subsystem, action or seqnum");
544 device->sealed = true;
549 int device_new_from_strv(sd_device **ret, char **strv) {
550 _cleanup_device_unref_ sd_device *device = NULL;
552 const char *major = NULL, *minor = NULL;
553 DeviceAction action = _DEVICE_ACTION_INVALID;
560 r = device_new_aux(&device);
564 STRV_FOREACH(key, strv) {
565 r = device_append(device, *key, &major, &minor, &seqnum, &action);
571 r = device_set_devnum(device, major, minor);
573 return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor);
576 r = device_verify(device, action, seqnum);
586 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
587 _cleanup_device_unref_ sd_device *device = NULL;
588 const char *major = NULL, *minor = NULL;
589 DeviceAction action = _DEVICE_ACTION_INVALID;
598 r = device_new_aux(&device);
606 key = (char*)&nulstr[i];
607 end = memchr(key, '\0', len - i);
609 log_debug("sd-device: failed to parse nulstr");
614 r = device_append(device, key, &major, &minor, &seqnum, &action);
620 r = device_set_devnum(device, major, minor);
622 return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor);
625 r = device_verify(device, action, seqnum);
635 static int device_update_properties_bufs(sd_device *device) {
636 const char *val, *prop;
637 char **buf_strv = NULL;
638 uint8_t *buf_nulstr = NULL;
639 size_t allocated_nulstr = 0, allocated_strv = 0;
640 size_t nulstr_len = 0, strv_size = 0;
644 if (!device->properties_buf_outdated)
647 FOREACH_DEVICE_PROPERTY(device, prop, val) {
650 len = strlen(prop) + 1 + strlen(val);
652 buf_nulstr = GREEDY_REALLOC0(buf_nulstr, allocated_nulstr, nulstr_len + len + 2);
656 buf_strv = GREEDY_REALLOC0(buf_strv, allocated_strv, strv_size + 2);
660 buf_strv[++ strv_size] = (char *)&buf_nulstr[nulstr_len];
661 strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL);
662 nulstr_len += len + 1;
665 free(device->properties_nulstr);
666 free(device->properties_strv);
667 device->properties_nulstr = buf_nulstr;
668 device->properties_nulstr_len = nulstr_len;
669 device->properties_strv = buf_strv;
671 device->properties_buf_outdated = false;
676 int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) {
683 r = device_update_properties_bufs(device);
687 *nulstr = device->properties_nulstr;
688 *len = device->properties_nulstr_len;
693 int device_get_properties_strv(sd_device *device, char ***strv) {
699 r = device_update_properties_bufs(device);
703 *strv = device->properties_strv;
708 int device_get_devlink_priority(sd_device *device, int *priority) {
714 r = device_read_db(device);
718 *priority = device->devlink_priority;
723 int device_get_watch_handle(sd_device *device, int *handle) {
729 r = device_read_db(device);
733 *handle = device->watch_handle;
738 void device_set_watch_handle(sd_device *device, int handle) {
741 device->watch_handle = handle;
744 int device_rename(sd_device *device, const char *name) {
745 _cleanup_free_ char *dirname = NULL;
747 const char *interface;
753 dirname = dirname_malloc(device->syspath);
757 new_syspath = strjoina(dirname, "/", name);
759 /* the user must trust that the new name is correct */
760 r = device_set_syspath(device, new_syspath, false);
764 r = sd_device_get_property_value(device, "INTERFACE", &interface);
766 r = device_add_property_internal(device, "INTERFACE", name);
770 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
771 r = device_add_property_internal(device, "INTERFACE_OLD", interface);
774 } else if (r != -ENOENT)
780 int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
781 _cleanup_device_unref_ sd_device *ret = NULL;
787 r = device_new_aux(&ret);
791 r = device_set_syspath(ret, old_device->syspath, false);
795 r = device_set_subsystem(ret, old_device->subsystem);
799 ret->devnum = old_device->devnum;
807 int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
808 _cleanup_device_unref_ sd_device *ret = NULL;
814 r = device_shallow_clone(old_device, &ret);
818 r = device_read_db(ret);
830 int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
831 _cleanup_device_unref_ sd_device *ret = NULL;
838 r = sd_device_new_from_syspath(&ret, syspath);
842 r = device_read_uevent_file(ret);
846 r = device_add_property_internal(ret, "ACTION", action);
856 int device_copy_properties(sd_device *device_dst, sd_device *device_src) {
857 const char *property, *value;
863 FOREACH_DEVICE_PROPERTY(device_src, property, value) {
864 r = device_add_property(device_dst, property, value);
872 void device_cleanup_tags(sd_device *device) {
875 set_free_free(device->tags);
877 device->property_tags_outdated = true;
878 device->tags_generation ++;
881 void device_cleanup_devlinks(sd_device *device) {
884 set_free_free(device->devlinks);
885 device->devlinks = NULL;
886 device->property_devlinks_outdated = true;
887 device->devlinks_generation ++;
890 void device_remove_tag(sd_device *device, const char *tag) {
894 free(set_remove(device->tags, tag));
895 device->property_tags_outdated = true;
896 device->tags_generation ++;
899 static int device_tag(sd_device *device, const char *tag, bool add) {
907 r = device_get_id_filename(device, &id);
911 path = strjoina("/run/udev/tags/", tag, "/", id);
914 r = touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
919 if (r < 0 && errno != ENOENT)
926 int device_tag_index(sd_device *device, sd_device *device_old, bool add) {
930 if (add && device_old) {
931 /* delete possible left-over tags */
932 FOREACH_DEVICE_TAG(device_old, tag) {
933 if (!sd_device_has_tag(device, tag)) {
934 k = device_tag(device_old, tag, false);
941 FOREACH_DEVICE_TAG(device, tag) {
942 k = device_tag(device, tag, add);
950 static bool device_has_info(sd_device *device) {
953 if (!set_isempty(device->devlinks))
956 if (device->devlink_priority != 0)
959 if (!ordered_hashmap_isempty(device->properties_db))
962 if (!set_isempty(device->tags))
965 if (device->watch_handle >= 0)
971 void device_set_db_persist(sd_device *device) {
974 device->db_persist = true;
977 int device_update_db(sd_device *device) {
980 _cleanup_fclose_ FILE *f = NULL;
981 _cleanup_free_ char *path_tmp = NULL;
987 has_info = device_has_info(device);
989 r = device_get_id_filename(device, &id);
993 path = strjoina("/run/udev/data/", id);
995 /* do not store anything for otherwise empty devices */
996 if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) {
998 if (r < 0 && errno != ENOENT)
1004 /* write a database file */
1005 r = mkdir_parents(path, 0755);
1009 r = fopen_temporary(path, &f, &path_tmp);
1014 * set 'sticky' bit to indicate that we should not clean the
1015 * database when we transition from initramfs to the real root
1017 if (device->db_persist) {
1018 r = fchmod(fileno(f), 01644);
1024 r = fchmod(fileno(f), 0644);
1032 const char *property, *value, *tag;
1035 if (major(device->devnum) > 0) {
1036 const char *devlink;
1038 FOREACH_DEVICE_DEVLINK(device, devlink)
1039 fprintf(f, "S:%s\n", devlink + strlen("/dev/"));
1041 if (device->devlink_priority != 0)
1042 fprintf(f, "L:%i\n", device->devlink_priority);
1044 if (device->watch_handle >= 0)
1045 fprintf(f, "W:%i\n", device->watch_handle);
1048 if (device->usec_initialized > 0)
1049 fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized);
1051 ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i)
1052 fprintf(f, "E:%s=%s\n", property, value);
1054 FOREACH_DEVICE_TAG(device, tag)
1055 fprintf(f, "G:%s\n", tag);
1058 r = fflush_and_check(f);
1062 r = rename(path_tmp, path);
1068 log_debug("created %s file '%s' for '%s'", has_info ? "db" : "empty",
1069 path, device->devpath);
1074 log_error_errno(r, "failed to create %s file '%s' for '%s'", has_info ? "db" : "empty",
1075 path, device->devpath);
1082 int device_delete_db(sd_device *device) {
1089 r = device_get_id_filename(device, &id);
1093 path = strjoina("/run/udev/data/", id);
1096 if (r < 0 && errno != ENOENT)