#include <dirent.h>
#include <getopt.h>
-#include <libudev.h>
-#include <../../udev/udev.h>
+#include "libudev.h"
+#include "libudev-private.h"
int debug;
return dev;
}
-/* find smallest number of instances of <syspath>/<name><number> */
-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;
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)
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)
if (udev == NULL)
goto exit;
- logging_init("usb_id");
+ udev_log_init("path_id");
udev_set_log_fn(udev, log_fn);
while (1) {
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;
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");
parent = udev_device_get_parent(parent);
}
-
+out:
if (path != NULL) {
if (path_suffix != NULL) {
printf("ID_PATH=%s%s\n", path, path_suffix);
udev_device_unref(dev);
exit:
udev_unref(udev);
- logging_close();
+ udev_log_close();
return rc;
}