X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Flib%2Flibudev-device.c;h=55fcad655e2ba092d53d0e1a6288d13ff2de65da;hp=3437d69798706cd8c3730d25df34ad932845bd50;hb=31441f6a4b3a776fe56e98ef939ff8825355c285;hpb=bc8184ede9cff156709fe053e3e02ef309cb2920 diff --git a/udev/lib/libudev-device.c b/udev/lib/libudev-device.c index 3437d6979..55fcad655 100644 --- a/udev/lib/libudev-device.c +++ b/udev/lib/libudev-device.c @@ -77,29 +77,51 @@ static int device_read_db(struct udev_device *udev_device) syspath_to_db_path(udev_device, filename, sizeof(filename)); if (lstat(filename, &stats) != 0) { - info(udev_device->udev, "no db file to read %s: %s\n", filename, strerror(errno)); + info(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]; int target_len; + char *next; target_len = readlink(filename, target, sizeof(target)); if (target_len > 0) target[target_len] = '\0'; else { - info(udev_device->udev, "error reading db link %s: %s\n", filename, strerror(errno)); + info(udev_device->udev, "error reading db link %s: %m\n", filename); return -1; } + + next = strchr(target, ' '); + if (next != NULL) { + next[0] = '\0'; + next = &next[1]; + } if (asprintf(&udev_device->devnode, "%s/%s", udev_get_dev_path(udev_device->udev), target) < 0) return -ENOMEM; + while (next != NULL) { + char linkname[UTIL_PATH_SIZE]; + const char *lnk; + + lnk = next; + next = strchr(next, ' '); + if (next != NULL) { + next[0] = '\0'; + next = &next[1]; + } + util_strlcpy(linkname, udev_get_dev_path(udev_device->udev), sizeof(linkname)); + util_strlcat(linkname, "/", sizeof(linkname)); + util_strlcat(linkname, lnk, sizeof(linkname)); + device_add_devlink(udev_device, linkname); + } info(udev_device->udev, "device %p filled with db symlink data '%s'\n", udev_device, udev_device->devnode); return 0; } f = fopen(filename, "r"); if (f == NULL) { - info(udev_device->udev, "error reading db file %s: %s\n", filename, strerror(errno)); + info(udev_device->udev, "error reading db file %s: %m\n", filename); return -1; } while (fgets(line, sizeof(line), f)) { @@ -193,7 +215,7 @@ void device_set_info_loaded(struct udev_device *device) device->info_loaded = 1; } -struct udev_device *device_init(struct udev *udev) +struct udev_device *device_new(struct udev *udev) { struct udev_device *udev_device; @@ -231,8 +253,8 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * { size_t len; const char *subdir; - const char *pos; char path[UTIL_PATH_SIZE]; + char *pos; struct stat statbuf; struct udev_device *udev_device; @@ -260,6 +282,23 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * util_strlcpy(path, syspath, sizeof(path)); util_resolve_sys_link(udev, path, sizeof(path)); + /* try to resolve the silly block layout if needed */ + if (strncmp(&path[len], "/block/", 7) == 0) { + char block[UTIL_PATH_SIZE]; + char part[UTIL_PATH_SIZE]; + + util_strlcpy(block, path, sizeof(block)); + pos = strrchr(block, '/'); + if (pos == NULL) + return NULL; + util_strlcpy(part, pos, sizeof(part)); + pos[0] = '\0'; + if (util_resolve_sys_link(udev, block, sizeof(block)) == 0) { + util_strlcpy(path, block, sizeof(path)); + util_strlcat(path, part, sizeof(path)); + } + } + /* path exists in sys */ if (strncmp(&syspath[len], "/devices/", 9) == 0 || strncmp(&syspath[len], "/class/", 7) == 0 || @@ -281,7 +320,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } } - udev_device = device_init(udev); + udev_device = device_new(udev); if (udev_device == NULL) return NULL; @@ -295,7 +334,7 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de { char path[UTIL_PATH_SIZE]; const char *type_str; - struct udev_enumerate *enumerate; + struct udev_enumerate *udev_enumerate; struct udev_list_entry *list_entry; struct udev_device *device = NULL; @@ -312,25 +351,25 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de if (util_resolve_sys_link(udev, path, sizeof(path)) == 0) return udev_device_new_from_syspath(udev, path); + udev_enumerate = udev_enumerate_new(udev); + if (udev_enumerate == NULL) + return NULL; + /* fallback to search sys devices for the major/minor */ if (type == 'b') - enumerate = udev_enumerate_new_from_devices(udev, "block", NULL); + udev_enumerate_add_match_subsystem(udev_enumerate, "block"); else if (type == 'c') - enumerate = udev_enumerate_new_from_devices(udev, "!block", NULL); - if (enumerate == NULL) - return NULL; - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { + udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block"); + udev_enumerate_scan_devices(udev_enumerate); + udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) { struct udev_device *device_loop; device_loop = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry)); if (device_loop != NULL) { if (udev_device_get_devnum(device_loop) == devnum) { - const char *subsystem; - - subsystem = udev_device_get_subsystem(device_loop); - if (type == 'b' && strcmp(subsystem, "block") != 0) + if (type == 'b' && strcmp(udev_device_get_subsystem(device_loop), "block") != 0) continue; - if (type == 'c' && strcmp(subsystem, "block") == 0) + if (type == 'c' && strcmp(udev_device_get_subsystem(device_loop), "block") == 0) continue; device = device_loop; break; @@ -338,7 +377,7 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de udev_device_unref(device_loop); } } - udev_enumerate_unref(enumerate); + udev_enumerate_unref(udev_enumerate); return device; } @@ -387,6 +426,22 @@ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) return udev_device->parent_device; } +struct udev_device *udev_device_get_parent_with_subsystem(struct udev_device *udev_device, const char *subsystem) +{ + struct udev_device *parent; + + parent = udev_device_get_parent(udev_device); + while (parent != NULL) { + const char *parent_subsystem; + + parent_subsystem = udev_device_get_subsystem(parent); + if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0) + break; + parent = udev_device_get_parent(parent); + } + return parent; +} + /** * udev_device_get_udev: * @udev_device: udev device @@ -651,7 +706,7 @@ const char *udev_device_get_attr_value(struct udev_device *udev_device, const ch util_strlcat(path, attr, sizeof(path)); if (lstat(path, &statbuf) != 0) { - info(udev_device->udev, "stat '%s' failed: %s\n", path, strerror(errno)); + info(udev_device->udev, "stat '%s' failed: %m\n", path); goto out; }