static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { struct udev *udev = udev_device_get_udev(names->pcidev); unsigned int bus; unsigned int slot; unsigned int func; unsigned int dev_id = 0; size_t l; char *s; const char *attr; struct udev_device *pci = NULL; char slots[256]; DIR *dir; struct dirent *dent; char str[256]; int hotplug_slot = 0; int err = 0; if (sscanf(udev_device_get_sysname(names->pcidev), "0000:%x:%x.%d", &bus, &slot, &func) != 3) return -ENOENT; /* kernel provided multi-device index */ attr = udev_device_get_sysattr_value(dev, "dev_id"); if (attr) dev_id = strtol(attr, NULL, 16); /* compose a name based on the raw kernel's PCI bus, slot numbers */ s = names->pci_path; l = util_strpcpyf(&s, sizeof(names->pci_path), "p%ds%d", bus, slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = util_strpcpyf(&s, l, "f%d", func); if (dev_id > 0) l = util_strpcpyf(&s, l, "d%d", dev_id); if (l == 0) names->pci_path[0] = '\0'; /* ACPI _SUN -- slot user number */ pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); if (!pci) { err = -ENOENT; goto out; } snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci)); dir = opendir(slots); if (!dir) { err = -errno; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { int i; char *rest; char *address; if (dent->d_name[0] == '.') continue; i = strtol(dent->d_name, &rest, 10); if (rest[0] != '\0') continue; if (i < 1) continue; snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name); if (read_one_line_file(str, &address) >= 0) { /* match slot address with device by stripping the function */ if (strncmp(address, udev_device_get_sysname(names->pcidev), strlen(address)) == 0) hotplug_slot = i; free(address); } if (hotplug_slot > 0) break; } closedir(dir); if (hotplug_slot > 0) { s = names->pci_slot; l = util_strpcpyf(&s, sizeof(names->pci_slot), "s%d", hotplug_slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = util_strpcpyf(&s, l, "f%d", func); if (dev_id > 0) l = util_strpcpyf(&s, l, "d%d", dev_id); if (l == 0) names->pci_path[0] = '\0'; } out: udev_device_unref(pci); return err; }
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { struct udev *udev = udev_device_get_udev(names->pcidev); unsigned domain, bus, slot, func, dev_port = 0; size_t l; char *s; const char *attr; struct udev_device *pci = NULL; char slots[256], str[256]; _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; int hotplug_slot = 0, err = 0; if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4) return -ENOENT; /* kernel provided port index for multiple ports on a single PCI function */ attr = udev_device_get_sysattr_value(dev, "dev_port"); if (attr) dev_port = strtol(attr, NULL, 10); /* compose a name based on the raw kernel's PCI bus, slot numbers */ s = names->pci_path; l = sizeof(names->pci_path); if (domain > 0) l = strpcpyf(&s, l, "P%u", domain); l = strpcpyf(&s, l, "p%us%u", bus, slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%u", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%u", dev_port); if (l == 0) names->pci_path[0] = '\0'; /* ACPI _SUN — slot user number */ pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); if (!pci) { err = -ENOENT; goto out; } xsprintf(slots, "%s/slots", udev_device_get_syspath(pci)); dir = opendir(slots); if (!dir) { err = -errno; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { int i; char *rest; char *address; if (dent->d_name[0] == '.') continue; i = strtol(dent->d_name, &rest, 10); if (rest[0] != '\0') continue; if (i < 1) continue; xsprintf(str, "%s/%s/address", slots, dent->d_name); if (read_one_line_file(str, &address) >= 0) { /* match slot address with device by stripping the function */ if (strneq(address, udev_device_get_sysname(names->pcidev), strlen(address))) hotplug_slot = i; free(address); } if (hotplug_slot > 0) break; } if (hotplug_slot > 0) { s = names->pci_slot; l = sizeof(names->pci_slot); if (domain > 0) l = strpcpyf(&s, l, "P%d", domain); l = strpcpyf(&s, l, "s%d", hotplug_slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%d", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%d", dev_port); if (l == 0) names->pci_slot[0] = '\0'; } out: udev_device_unref(pci); return err; }