diff options
author | Karel Zak | 2012-10-23 11:32:55 +0200 |
---|---|---|
committer | Karel Zak | 2012-10-23 12:18:57 +0200 |
commit | 23a11c74a6bacf129e170060c85ff32a65b13610 (patch) | |
tree | fe6cccecdb19b0e6fe393488d854bff2ad0b97de | |
parent | include/sysfs: add SCSI host:channel:target:lun support (diff) | |
download | kernel-qcow2-util-linux-23a11c74a6bacf129e170060c85ff32a65b13610.tar.gz kernel-qcow2-util-linux-23a11c74a6bacf129e170060c85ff32a65b13610.tar.xz kernel-qcow2-util-linux-23a11c74a6bacf129e170060c85ff32a65b13610.zip |
lib/sysfs: add functions for SCSI host attributes
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | include/sysfs.h | 3 | ||||
-rw-r--r-- | lib/sysfs.c | 52 | ||||
-rw-r--r-- | misc-utils/lsblk.c | 53 |
3 files changed, 66 insertions, 42 deletions
diff --git a/include/sysfs.h b/include/sysfs.h index 10875d421..f0d33611e 100644 --- a/include/sysfs.h +++ b/include/sysfs.h @@ -75,5 +75,8 @@ extern int sysfs_devno_to_wholedisk(dev_t dev, char *diskname, extern int sysfs_scsi_get_hctl(struct sysfs_cxt *cxt, int *h, int *c, int *t, int *l); +extern char *sysfs_scsi_host_strdup_attribute(struct sysfs_cxt *cxt, + const char *type, const char *attr); +extern int sysfs_scsi_host_is(struct sysfs_cxt *cxt, const char *type); #endif /* UTIL_LINUX_SYSFS_H */ diff --git a/lib/sysfs.c b/lib/sysfs.c index 4cb6284ca..d0c6c8944 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -672,6 +672,58 @@ done: return 0; } + +static char *sysfs_scsi_host_attribute_path(struct sysfs_cxt *cxt, + const char *type, char *buf, size_t bufsz, const char *attr) +{ + int len; + int host; + + if (sysfs_scsi_get_hctl(cxt, &host, NULL, NULL, NULL)) + return NULL; + + if (attr) + len = snprintf(buf, bufsz, "/sys/class/%s_host/host%d/%s", + type, host, attr); + else + len = snprintf(buf, bufsz, "/sys/class/%s_host/host%d", + type, host); + + return (len < 0 || (size_t) len + 1 > bufsz) ? NULL : buf; +} + +char *sysfs_scsi_host_strdup_attribute(struct sysfs_cxt *cxt, + const char *type, const char *attr) +{ + char buf[1024]; + int rc; + FILE *f; + + if (!attr || !type || + !sysfs_scsi_host_attribute_path(cxt, type, buf, sizeof(buf), attr)) + return NULL; + + if (!(f = fopen(buf, "r"))) + return NULL; + + rc = fscanf(f, "%1023[^\n]", buf); + fclose(f); + + return rc == 1 ? strdup(buf) : NULL; +} + +int sysfs_scsi_host_is(struct sysfs_cxt *cxt, const char *type) +{ + char buf[PATH_MAX]; + struct stat st; + + if (!type || !sysfs_scsi_host_attribute_path(cxt, type, + buf, sizeof(buf), NULL)) + return 0; + + return stat(buf, &st) == 0 && S_ISDIR(st.st_mode); +} + #ifdef TEST_PROGRAM_SYSFS #include <errno.h> #include <err.h> diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c index c3803d826..104270418 100644 --- a/misc-utils/lsblk.c +++ b/misc-utils/lsblk.c @@ -577,40 +577,6 @@ static char *get_type(struct blkdev_cxt *cxt) return res; } -static char *_sysfs_host_string(const char *type, int host, const char *attr) -{ - char path[PATH_MAX], tmp[64] = {0}; - int fd, r; - - if (snprintf(path, sizeof(path), "/sys/class/%s_host/host%d/%s", - type, host, attr) < 0) - return NULL; - if ((fd = open(path, O_RDONLY)) < 0) - return NULL; - r = read(fd, tmp, sizeof(tmp)); - close(fd); - - if (r <= 0) - return NULL; - - return xstrdup(tmp); -} - -static int _sysfs_host_exists(const char *type, int host) -{ - char buf[PATH_MAX]; - struct stat st; - - if (snprintf(buf, sizeof(buf), "/sys/class/%s_host/host%d", - type, host) < 0) - return 0; - - if (!stat(buf, &st) && S_ISDIR(st.st_mode)) - return 1; - - return 0; -} - static int _sysfs_scsi_attr_exists(const char *attr, int h, int c, int t, int l) { char buf[PATH_MAX]; @@ -647,19 +613,21 @@ static int _sysfs_scsi_path_contains(const char *pattern, int h, int c, int t, i /* Thanks to lsscsi code for idea of detection logic used here */ static char *get_transport(struct blkdev_cxt *cxt) { + struct sysfs_cxt *sysfs = &cxt->sysfs; int host, channel, target, lun; char *attr; - if (sysfs_scsi_get_hctl(&cxt->sysfs, &host, &channel, &target, &lun) != 0) + if (sysfs_scsi_get_hctl(sysfs, &host, &channel, &target, &lun) != 0) return NULL; /* SPI - Serial Peripheral Interface */ - if (_sysfs_host_exists("spi", host)) + if (sysfs_scsi_host_is(sysfs, "spi")) return xstrdup("spi"); /* FC/FCoE - Fibre Channel / Fibre Channel over Ethernet */ - if (_sysfs_host_exists("fc", host)) { - if (!(attr = _sysfs_host_string("fc", host, "symbolic_name"))) + if (sysfs_scsi_host_is(sysfs, "fc")) { + attr = sysfs_scsi_host_strdup_attribute(sysfs, "fc", "symbolic_name"); + if (!attr) return NULL; if (strstr(attr, " over ")) return xstrdup("fcoe"); @@ -667,7 +635,7 @@ static char *get_transport(struct blkdev_cxt *cxt) } /* SAS - Serial Attached SCSI */ - if (_sysfs_host_exists("sas", host)) + if (sysfs_scsi_host_is(sysfs, "sas")) return xstrdup("sas"); if (_sysfs_scsi_attr_exists("sas_device", host, channel, target, lun)) @@ -678,7 +646,7 @@ static char *get_transport(struct blkdev_cxt *cxt) return xstrdup("sbp"); /* iSCSI */ - if (_sysfs_host_exists("iscsi", host)) + if (sysfs_scsi_host_is(sysfs, "iscsi")) return xstrdup("iscsi"); /* USB - Universal Serial Bus */ @@ -686,8 +654,9 @@ static char *get_transport(struct blkdev_cxt *cxt) return xstrdup("usb"); /* ATA, SATA */ - if (_sysfs_host_exists("scsi", host)) { - if (!(attr = _sysfs_host_string("scsi", host, "proc_name"))) + if (sysfs_scsi_host_is(sysfs, "scsi")) { + attr = sysfs_scsi_host_strdup_attribute(sysfs, "scsi", "proc_name"); + if (!attr) return NULL; if (!strncmp(attr, "ahci", 4) || !strncmp(attr, "sata", 4)) |