X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=libudev%2Flibudev-device.c;h=66f806316f55d75143f4d7a2e2242f99bcad805b;hp=d87b0c6c8ac92b87a9ef791dbc588d56577de8c1;hb=48a0170b111b55e961be769d2cc4890511bcd991;hpb=4281da1fa6fda10c15bee984825fc607a8385004 diff --git a/libudev/libudev-device.c b/libudev/libudev-device.c index d87b0c6c8..66f806316 100644 --- a/libudev/libudev-device.c +++ b/libudev/libudev-device.c @@ -81,6 +81,7 @@ struct udev_device { bool info_loaded; bool db_loaded; bool uevent_loaded; + bool is_initialized; }; struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value) @@ -232,70 +233,29 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons int udev_device_read_db(struct udev_device *udev_device) { const char *id; - struct stat stats; char filename[UTIL_PATH_SIZE]; char line[UTIL_LINE_SIZE]; FILE *f; if (udev_device->db_loaded) return 0; + udev_device->db_loaded = true; id = udev_device_get_id_filename(udev_device); if (id == NULL) return -1; util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.udev/db/", id, NULL); - - if (lstat(filename, &stats) != 0) { - dbg(udev_device->udev, "no db file to read %s: %m\n", filename); - return -1; - } - if ((stats.st_mode & S_IFMT) == S_IFLNK) { - char target[UTIL_PATH_SIZE]; - char devnode[UTIL_PATH_SIZE]; - int target_len; - char *next; - - target_len = readlink(filename, target, sizeof(target)); - if (target_len <= 0 || target_len == sizeof(target)) { - info(udev_device->udev, "error reading db link %s: %m\n", filename); - return -1; - } - target[target_len] = '\0'; - - next = strchr(target, ' '); - if (next != NULL) { - next[0] = '\0'; - next = &next[1]; - } - util_strscpyl(devnode, sizeof(devnode), udev_get_dev_path(udev_device->udev), "/", target, NULL); - udev_device_set_devnode(udev_device, devnode); - while (next != NULL) { - char devlink[UTIL_PATH_SIZE]; - const char *lnk; - - lnk = next; - next = strchr(next, ' '); - if (next != NULL) { - next[0] = '\0'; - next = &next[1]; - } - util_strscpyl(devlink, sizeof(devlink), udev_get_dev_path(udev_device->udev), "/", lnk, NULL); - udev_device_add_devlink(udev_device, devlink, 0); - } - info(udev_device->udev, "device %p filled with db symlink data '%s'\n", udev_device, udev_device->devnode); - return 0; - } - f = fopen(filename, "re"); if (f == NULL) { - dbg(udev_device->udev, "error reading db file %s: %m\n", filename); + info(udev_device->udev, "no db file to read %s: %m\n", filename); return -1; } - udev_device->db_loaded = true; + udev_device->is_initialized = true; while (fgets(line, sizeof(line), f)) { ssize_t len; const char *val; + struct udev_list_entry *entry; len = strlen(line); if (len < 4) @@ -314,11 +274,9 @@ int udev_device_read_db(struct udev_device *udev_device) case 'L': udev_device_set_devlink_priority(udev_device, atoi(val)); break; - case 'T': - udev_device_set_event_timeout(udev_device, atoi(val)); - break; case 'E': - udev_device_add_property_from_string(udev_device, val); + entry = udev_device_add_property_from_string(udev_device, val); + udev_list_entry_set_flags(entry, 1); break; case 'G': udev_device_add_tag(udev_device, val); @@ -519,6 +477,32 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de return udev_device_new_from_syspath(udev, path); } +struct udev_device *udev_device_new_from_id_filename(struct udev *udev, char *id) +{ + char type; + int maj, min; + char subsys[UTIL_PATH_SIZE]; + char *sysname; + + switch(id[0]) { + case 'b': + case 'c': + if (sscanf(id, "%c%i:%i", &type, &maj, &min) != 3) + return NULL; + return udev_device_new_from_devnum(udev, type, makedev(maj, min)); + case '+': + util_strscpy(subsys, sizeof(subsys), &id[1]); + sysname = strchr(subsys, ':'); + if (sysname == NULL) + return NULL; + sysname[0] = '\0'; + sysname = &sysname[1]; + return udev_device_new_from_subsystem_sysname(udev, subsys, sysname); + default: + return NULL; + } +} + /** * udev_device_new_from_subsystem_sysname: * @udev: udev library context @@ -888,9 +872,11 @@ const char *udev_device_get_devnode(struct udev_device *udev_device) /* we might get called before we handled an event and have a db, use the kernel-provided name */ if (udev_device->devnode == NULL && udev_device_get_knodename(udev_device) != NULL) { - if (asprintf(&udev_device->devnode, "%s/%s", - udev_get_dev_path(udev_device->udev), udev_device_get_knodename(udev_device)) < 0) - return NULL; + char filename[UTIL_NAME_SIZE]; + + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", + udev_device_get_knodename(udev_device), NULL); + udev_device_set_devnode(udev_device, filename); return udev_device->devnode; } @@ -1271,8 +1257,6 @@ int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode { free(udev_device->devnode); udev_device->devnode = strdup(devnode); - if (devnode == NULL) - return 0; if (udev_device->devnode == NULL) return -ENOMEM; udev_device_add_property(udev_device, "DEVNAME", udev_device->devnode); @@ -1305,7 +1289,7 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device) major(udev_device_get_devnum(udev_device)), minor(udev_device_get_devnum(udev_device))) < 0) udev_device->id_filename = NULL; - } else if (strcmp(udev_device_get_subsystem(udev_device), "net") == 0) { + } else if (udev_device_get_ifindex(udev_device) > 0) { /* use netdev ifindex -- n3 */ if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0) udev_device->id_filename = NULL; @@ -1326,6 +1310,31 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device) return udev_device->id_filename; } +/** + * udev_device_get_is_initialized: + * @udev_device: udev device + * + * Check if udev has already handled the device and has set up + * device node permissions and context, or has renamed a network + * device. + * + * For now, this is only implemented for devices with a device node + * or network interfaces. All other devices return 1 here. + * + * Returns: 1 if the device is set up. 0 otherwise. + **/ +int udev_device_get_is_initialized(struct udev_device *udev_device) +{ + if (!udev_device->info_loaded) + udev_device_read_db(udev_device); + return udev_device->is_initialized; +} + +void udev_device_set_is_initialized(struct udev_device *udev_device) +{ + udev_device->is_initialized = true; +} + int udev_device_add_tag(struct udev_device *udev_device, const char *tag) { if (strchr(tag, ':') != NULL || strchr(tag, ' ') != NULL) @@ -1516,7 +1525,9 @@ int udev_device_set_knodename(struct udev_device *udev_device, const char *knode udev_device->knodename = strdup(knodename); if (udev_device->knodename == NULL) return -ENOMEM; - udev_device_add_property(udev_device, "DEVNAME", udev_device->knodename); + /* do not overwrite the udev property with the kernel property */ + if (udev_device->devnode == NULL) + udev_device_add_property(udev_device, "DEVNAME", udev_device->knodename); return 0; } @@ -1598,6 +1609,8 @@ int udev_device_set_watch_handle(struct udev_device *udev_device, int handle) int udev_device_get_ifindex(struct udev_device *udev_device) { + if (!udev_device->info_loaded) + udev_device_read_uevent_file(udev_device); return udev_device->ifindex; }