X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=extras%2Fpath_id%2Fpath_id.c;h=dcee37881fcd0de1565743d658f9f379c7e8d3ef;hp=872f0c932e82a27ad1cd9666fbcf8fd799568e90;hb=1230d021bd75de9b1503bbaa807d6a59789963db;hpb=185ea6a76d3f3a9e9708239d2302bd98e00460fa diff --git a/extras/path_id/path_id.c b/extras/path_id/path_id.c index 872f0c932..dcee37881 100644 --- a/extras/path_id/path_id.c +++ b/extras/path_id/path_id.c @@ -1,8 +1,10 @@ /* - * compose persisistent device path + * compose persistent device path * * Copyright (C) 2009 Kay Sievers * + * Logic based on Hannes Reinecke's shell script. + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or @@ -28,10 +30,10 @@ #include #include -#include -#include <../../udev/udev.h> +#include "libudev.h" +#include "libudev-private.h" -int debug; +static int debug; static void log_fn(struct udev *udev, int priority, const char *file, int line, const char *fn, @@ -89,29 +91,131 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s return dev; } -/* find smallest number of instances of / */ -static int base_number(const char *syspath, const char *name) +static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) +{ + struct udev *udev = udev_device_get_udev(parent); + struct udev_device *targetdev; + struct udev_device *fcdev = NULL; + const char *port; + unsigned int lun; + + targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); + if (targetdev == NULL) + return NULL; + + fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev)); + if (fcdev == NULL) + return NULL; + port = udev_device_get_sysattr_value(fcdev, "port_name"); + if (port == NULL) { + parent = NULL; + goto out; + } + + lun = strtoul(udev_device_get_sysnum(parent), NULL, 10); + path_prepend(path, "fc-%s:0x%04x%04x00000000", port, lun & 0xffff, (lun >> 16) & 0xffff); +out: + udev_device_unref(fcdev); + return parent; +} + +static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) +{ + return NULL; +} + +static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) { + struct udev *udev = udev_device_get_udev(parent); + struct udev_device *transportdev; + struct udev_device *sessiondev = NULL; + const char *target; + char *connname; + struct udev_device *conndev = NULL; + const char *addr; + const char *port; + + /* find iscsi session */ + transportdev = parent; + while (1) { + transportdev = udev_device_get_parent(transportdev); + if (transportdev == NULL) + return NULL; + if (strncmp(udev_device_get_sysname(transportdev), "session", 7) == 0) + break; + } + if (transportdev == NULL) + return NULL; + + /* find iscsi session device */ + sessiondev = udev_device_new_from_subsystem_sysname(udev, "iscsi_session", udev_device_get_sysname(transportdev)); + if (sessiondev == NULL) + return NULL; + target = udev_device_get_sysattr_value(sessiondev, "targetname"); + if (target == NULL) { + parent = NULL; + goto out; + } + + if (asprintf(&connname, "connection%s:0", udev_device_get_sysnum(transportdev)) < 0) { + parent = NULL; + goto out; + } + conndev = udev_device_new_from_subsystem_sysname(udev, "iscsi_connection", connname); + free(connname); + if (conndev == NULL) { + parent = NULL; + goto out; + } + addr = udev_device_get_sysattr_value(conndev, "persistent_address"); + port = udev_device_get_sysattr_value(conndev, "persistent_port"); + if (addr == NULL || port == NULL) { + parent = NULL; + goto out; + } + + path_prepend(path, "ip-%s:%s-iscsi-%s-lun-%s", addr, port, target, udev_device_get_sysnum(parent)); +out: + udev_device_unref(sessiondev); + udev_device_unref(conndev); + return parent; +} + +static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path) +{ + struct udev_device *hostdev; + int host, bus, target, lun; + const char *name; char *base; char *pos; DIR *dir; struct dirent *dent; - size_t len; - int number = -1; + int basenum; - base = strdup(syspath); - if (base == NULL) - goto out; + hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); + if (hostdev == NULL) + return NULL; + + name = udev_device_get_sysname(parent); + if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) + return NULL; + /* rebase host offset to get the local relative number */ + basenum = -1; + base = strdup(udev_device_get_syspath(hostdev)); + if (base == NULL) + return NULL; pos = strrchr(base, '/'); - if (pos == NULL) + if (pos == NULL) { + parent = NULL; goto out; + } pos[0] = '\0'; - - len = strlen(name); dir = opendir(base); - if (dir == NULL) + if (dir == NULL) { + parent = NULL; goto out; + } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { char *rest; int i; @@ -120,49 +224,66 @@ static int base_number(const char *syspath, const char *name) continue; if (dent->d_type != DT_DIR && dent->d_type != DT_LNK) continue; - if (strncmp(dent->d_name, name, len) != 0) + if (strncmp(dent->d_name, "host", 4) != 0) continue; - i = strtoul(&dent->d_name[len], &rest, 10); + i = strtoul(&dent->d_name[4], &rest, 10); if (rest[0] != '\0') continue; - if (number == -1 || i < number) - number = i; + if (basenum == -1 || i < basenum) + basenum = i; } closedir(dir); + if (basenum == -1) { + parent = NULL; + goto out; + } + host -= basenum; + + path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun); out: free(base); - return number; + return hostdev; } -static struct udev_device *handle_scsi(struct udev_device *dev, char **path) +static struct udev_device *handle_scsi(struct udev_device *parent, char **path) { const char *devtype; - struct udev_device *hostdev; const char *name; - int host, bus, target, lun; - int base; + const char *id; - devtype = udev_device_get_devtype(dev); + devtype = udev_device_get_devtype(parent); if (devtype == NULL || strcmp(devtype, "scsi_device") != 0) - return dev; + return parent; - hostdev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_host"); - if (hostdev == NULL) - return dev; + /* firewire */ + id = udev_device_get_sysattr_value(parent, "ieee1394_id"); + if (id != NULL) { + parent = skip_subsystem(parent, "scsi"); + path_prepend(path, "ieee1394-0x%s", id); + goto out; + } - name = udev_device_get_sysname(dev); - if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) - return dev; + /* lousy scsi sysfs does not have a "subsystem" for the transport */ + name = udev_device_get_syspath(parent); - /* rebase host offset to get the local relative number */ - base = base_number(udev_device_get_syspath(hostdev), "host"); - if (base < 0) - return dev; - host -= base; + if (strstr(name, "/rport-") != NULL) { + parent = handle_scsi_fibre_channel(parent, path); + goto out; + } - path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun); - dev = skip_subsystem(dev, "scsi"); - return dev; + if (strstr(name, "/end_device-") != NULL) { + parent = handle_scsi_sas(parent, path); + goto out; + } + + if (strstr(name, "/session") != NULL) { + parent = handle_scsi_iscsi(parent, path); + goto out; + } + + parent = handle_scsi_default(parent, path); +out: + return parent; } static void handle_scsi_tape(struct udev_device *dev, char **suffix) @@ -176,42 +297,30 @@ static void handle_scsi_tape(struct udev_device *dev, char **suffix) asprintf(suffix, "st%c", name[2]); } -static struct udev_device *handle_usb(struct udev_device *dev, char **path) +static struct udev_device *handle_usb(struct udev_device *parent, char **path) { const char *devtype; const char *str; const char *port; - devtype = udev_device_get_devtype(dev); + devtype = udev_device_get_devtype(parent); if (devtype == NULL || strcmp(devtype, "usb_interface") != 0) - return dev; + return parent; - str = udev_device_get_sysname(dev); + str = udev_device_get_sysname(parent); port = strchr(str, '-'); if (port == NULL) - return dev; + return parent; port++; - dev = skip_subsystem(dev, "usb"); + parent = skip_subsystem(parent, "usb"); path_prepend(path, "usb-0:%s", port); - return dev; + return parent; } -static struct udev_device *handle_firewire(struct udev_device *parent, struct udev_device *dev, char **path) +static struct udev_device *handle_cciss(struct udev_device *parent, char **path) { - struct udev_device *scsi_dev; - - scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device"); - if (scsi_dev != NULL) { - const char *id; - - id = udev_device_get_sysattr_value(scsi_dev, "ieee1394_id"); - if (id != NULL) - path_prepend(path, "ieee1394-0x%s", id); - } - - parent = skip_subsystem(parent, "firewire"); - return parent; + return NULL; } static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev, char **path) @@ -259,7 +368,7 @@ int main(int argc, char **argv) if (udev == NULL) goto exit; - logging_init("usb_id"); + udev_log_init("path_id"); udev_set_log_fn(udev, log_fn); while (1) { @@ -303,6 +412,14 @@ int main(int argc, char **argv) path = NULL; path_suffix = NULL; + /* S390 ccw bus */ + parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL); + if (parent != NULL) { + handle_ccw(parent, dev, &path); + goto out; + } + + /* walk up the chain of devices and compose path */ parent = dev; while (parent != NULL) { const char *subsys; @@ -315,23 +432,13 @@ int main(int argc, char **argv) handle_scsi_tape(parent, &path_suffix); } else if (strcmp(subsys, "scsi") == 0) { parent = handle_scsi(parent, &path); - } else if (strcmp(subsys, "fc_transport") == 0) { - ; //handle_fc(); - } else if (strcmp(subsys, "sas_end_device") == 0) { - ; //handle_sas(); - } else if (strcmp(subsys, "iscsi_session") == 0) { - ; //handle_iscsi() - } else if (strcmp(subsys, "ccw") == 0) { - handle_ccw(parent, dev, &path); } else if (strcmp(subsys, "cciss") == 0) { - ; //handle_cciss(); + handle_cciss(parent, &path); } else if (strcmp(subsys, "usb") == 0) { parent = handle_usb(parent, &path); } else if (strcmp(subsys, "serio") == 0) { path_prepend(&path, "serio-%s", udev_device_get_sysnum(parent)); parent = skip_subsystem(parent, "serio"); - } else if (strcmp(subsys, "firewire") == 0 || strcmp(subsys, "ieee1394") == 0) { - parent = handle_firewire(parent, dev, &path); } else if (strcmp(subsys, "pci") == 0) { path_prepend(&path, "pci-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "pci"); @@ -345,7 +452,7 @@ int main(int argc, char **argv) parent = udev_device_get_parent(parent); } - +out: if (path != NULL) { if (path_suffix != NULL) { printf("ID_PATH=%s%s\n", path, path_suffix); @@ -360,6 +467,6 @@ int main(int argc, char **argv) udev_device_unref(dev); exit: udev_unref(udev); - logging_close(); + udev_log_close(); return rc; }