summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2012-10-23 11:32:55 +0200
committerKarel Zak2012-10-23 12:18:57 +0200
commit23a11c74a6bacf129e170060c85ff32a65b13610 (patch)
treefe6cccecdb19b0e6fe393488d854bff2ad0b97de
parentinclude/sysfs: add SCSI host:channel:target:lun support (diff)
downloadkernel-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.h3
-rw-r--r--lib/sysfs.c52
-rw-r--r--misc-utils/lsblk.c53
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))