]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsblk: use generic sysfs functions
authorKarel Zak <kzak@redhat.com>
Mon, 16 May 2011 13:24:26 +0000 (15:24 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 16 May 2011 18:22:52 +0000 (20:22 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
misc-utils/Makefile.am
misc-utils/lsblk.c

index d3ada1de1a88394aa6b5669a46bde16fb4e006a7..54e4fe271db42fba121bc915c9e0060ab62b6fea 100644 (file)
@@ -58,7 +58,9 @@ lsblk_SOURCES = lsblk.c \
                $(top_srcdir)/lib/ismounted.c \
                $(top_srcdir)/lib/tt.c \
                $(top_srcdir)/lib/mbsalign.c \
-               $(top_srcdir)/lib/strutils.c
+               $(top_srcdir)/lib/strutils.c \
+               $(top_srcdir)/lib/sysfs.c \
+               $(top_srcdir)/lib/at.c
 lsblk_LDADD = $(ul_libblkid_la)
 lsblk_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir)
 endif
index 2110113dd66a6e6775d120ea74ade74bc73b1049..5d34aebf42a980aa699a79ecfbe28fe688524f3e 100644 (file)
@@ -52,6 +52,7 @@
 #include "xalloc.h"
 #include "strutils.h"
 #include "c.h"
+#include "sysfs.h"
 
 /* column IDs */
 enum {
@@ -147,7 +148,8 @@ struct blkdev_cxt {
        char *dm_name;          /* DM name (dm/block) */
 
        char *filename;         /* path to device node */
-       int sysfs_fd;           /* O_RDONLY file desciptor to /sys/block/<dev> */
+
+       struct sysfs_cxt  sysfs;
 
        int partition;          /* is partition? TRUE/FALSE */
 
@@ -176,7 +178,6 @@ static int is_maj_excluded(int maj)
        return 0;
 }
 
-
 /* array with IDs of enabled columns */
 static int get_column_id(int num)
 {
@@ -191,7 +192,6 @@ static struct colinfo *get_column_info(int num)
        return &infos[ get_column_id(num) ];
 }
 
-
 static int column_name_to_id(const char *name, size_t namesz)
 {
        int i;
@@ -217,8 +217,7 @@ static void reset_blkdev_cxt(struct blkdev_cxt *cxt)
        free(cxt->uuid);
        free(cxt->label);
 
-       if (cxt->sysfs_fd >= 0)
-               close(cxt->sysfs_fd);
+       sysfs_deinit(&cxt->sysfs);
 
        memset(cxt, 0, sizeof(*cxt));
 }
@@ -245,27 +244,6 @@ static struct dirent *xreaddir(DIR *dp)
        return d;
 }
 
-
-static int is_partition_dirent(DIR *dir, struct dirent *d, const char *parent_name)
-{
-       char path[256];
-
-       assert(dir);
-       assert(d);
-
-#ifdef _DIRENT_HAVE_D_TYPE
-       if (d->d_type != DT_DIR)
-               return 0;
-#endif
-       if (strncmp(parent_name, d->d_name, strlen(parent_name)))
-               return 0;
-
-       /* Cannot use /partition file, not supported on old sysfs */
-       snprintf(path, sizeof(path), "%s/start", d->d_name);
-
-       return faccessat(dirfd(dir), path, R_OK, 0) == 0;
-}
-
 static char *get_device_path(struct blkdev_cxt *cxt)
 {
        char path[PATH_MAX];
@@ -280,141 +258,6 @@ static char *get_device_path(struct blkdev_cxt *cxt)
        return xstrdup(path);
 }
 
-static char *get_sysfs_path(struct blkdev_cxt *cxt)
-{
-       char path[PATH_MAX];
-
-       assert(cxt);
-       assert(cxt->name);
-
-       if (cxt->partition && cxt->parent)
-               snprintf(path, sizeof(path), _PATH_SYS_BLOCK "/%s/%s",
-                        cxt->parent->name, cxt->name);
-       else
-               snprintf(path, sizeof(path), _PATH_SYS_BLOCK "/%s", cxt->name);
-
-       return xstrdup(path);
-}
-
-static int sysfs_open(struct blkdev_cxt *cxt, const char *attr)
-{
-       int fd;
-
-       assert(cxt);
-       assert(cxt->sysfs_fd >= 0);
-
-       fd = openat(cxt->sysfs_fd, attr, O_RDONLY);
-       if (fd == -1 && errno == ENOENT && !strncmp(attr, "queue/", 6) && cxt->parent) {
-               fd = openat(cxt->parent->sysfs_fd, attr, O_RDONLY);
-       }
-       return fd;
-}
-
-static FILE *sysfs_fopen(struct blkdev_cxt *cxt, const char *attr)
-{
-       int fd = sysfs_open(cxt, attr);
-
-       return fd < 0 ? NULL : fdopen(fd, "r");
-}
-
-static DIR *sysfs_opendir(struct blkdev_cxt *cxt, const char *attr)
-{
-       DIR *dir;
-       int fd;
-
-       if (attr)
-               fd = sysfs_open(cxt, attr);
-       else {
-               /* request to open root of device in sysfs (/sys/block/<dev>)
-                * -- we cannot use cxt->sysfs_fd directly, because closedir()
-                * will close this our persistent file descriptor.
-                */
-               assert(cxt);
-               assert(cxt->sysfs_fd >= 0);
-
-               fd = dup(cxt->sysfs_fd);
-       }
-
-       if (fd < 0)
-               return NULL;
-       dir = fdopendir(fd);
-       if (!dir) {
-               close(fd);
-               return NULL;
-       }
-       if (!attr)
-                rewinddir(dir);
-       return dir;
-}
-
-static __attribute__ ((format (scanf, 3, 4)))
-int sysfs_scanf(struct blkdev_cxt *cxt,  const char *attr, const char *fmt, ...)
-{
-       FILE *f = sysfs_fopen(cxt, attr);
-       va_list ap;
-       int rc;
-
-       if (!f)
-               return -EINVAL;
-       va_start(ap, fmt);
-       rc = vfscanf(f, fmt, ap);
-       va_end(ap);
-
-       fclose(f);
-       return rc;
-}
-
-static uint64_t sysfs_read_u64(struct blkdev_cxt *cxt, const char *attr)
-{
-       uint64_t x;
-       return sysfs_scanf(cxt, attr, "%"SCNu64, &x) == 1 ? x : 0;
-}
-
-static int sysfs_read_int(struct blkdev_cxt *cxt, const char *attr)
-{
-       int x;
-       return sysfs_scanf(cxt, attr, "%d", &x) == 1 ? x : 0;
-}
-
-static char *sysfs_strdup(struct blkdev_cxt *cxt, const char *attr)
-{
-       char buf[1024];
-       return sysfs_scanf(cxt, attr, "%1024[^\n]", buf) == 1 ?
-                                               xstrdup(buf) : NULL;
-}
-
-static int sysfs_count_dirents(struct blkdev_cxt *cxt, const char *attr)
-{
-       DIR *dir;
-       int r = 0;
-
-       if (!(dir = sysfs_opendir(cxt, attr)))
-               return 0;
-
-       while (xreaddir(dir)) r++;
-
-       closedir(dir);
-       return r;
-}
-
-static int sysfs_count_partitions(struct blkdev_cxt *cxt)
-{
-       DIR *dir;
-       struct dirent *d;
-       int r = 0;
-
-       if (!(dir = sysfs_opendir(cxt, NULL)))
-               return 0;
-
-       while ((d = xreaddir(dir))) {
-               if (is_partition_dirent(dir, d, cxt->name))
-                       r++;
-       }
-
-       closedir(dir);
-       return r;
-}
-
 static char *get_device_mountpoint(struct blkdev_cxt *cxt)
 {
        int fl = 0;
@@ -478,7 +321,7 @@ static int is_readonly_device(struct blkdev_cxt *cxt)
 {
        int fd, ro = 0;
 
-       if (sysfs_scanf(cxt, "ro", "%d", &ro) == 0)
+       if (sysfs_scanf(&cxt->sysfs, "ro", "%d", &ro) == 0)
                return ro;
 
        /* fallback if "ro" attribute does not exist */
@@ -492,7 +335,7 @@ static int is_readonly_device(struct blkdev_cxt *cxt)
 
 static char *get_scheduler(struct blkdev_cxt *cxt)
 {
-       char *str = sysfs_strdup(cxt, "queue/scheduler");
+       char *str = sysfs_strdup(&cxt->sysfs, "queue/scheduler");
        char *p, *res = NULL;
 
        if (!str)
@@ -516,7 +359,7 @@ static char *get_type(struct blkdev_cxt *cxt)
        char *res = NULL, *p;
 
        if (is_dm(cxt->name)) {
-               char *dm_uuid = sysfs_strdup(cxt, "dm/uuid");
+               char *dm_uuid = sysfs_strdup(&cxt->sysfs, "dm/uuid");
 
                /* The DM_UUID prefix should be set to subsystem owning
                 * the device - LVM, CRYPT, DMRAID, MPATH, PART */
@@ -542,13 +385,13 @@ static char *get_type(struct blkdev_cxt *cxt)
                res = xstrdup("loop");
 
        } else if (!strncmp(cxt->name, "md", 2)) {
-               char *md_level = sysfs_strdup(cxt, "md/level");
+               char *md_level = sysfs_strdup(&cxt->sysfs, "md/level");
                res = md_level ? md_level : xstrdup("md");
 
        } else {
                const char *type = cxt->partition ? "part" : "disk";
 
-               switch (sysfs_read_int(cxt, "device/type")) {
+               switch (sysfs_read_int(&cxt->sysfs, "device/type")) {
                        case 0x0c: /* TYPE_RAID */
                                type = "raid"; break;
                        case 0x01: /* TYPE_TAPE */
@@ -646,20 +489,20 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line
                                        xstrdup("1") : xstrdup("0"));
                break;
        case COL_RM:
-               p = sysfs_strdup(cxt, "removable");
+               p = sysfs_strdup(&cxt->sysfs, "removable");
                if (!p && cxt->parent)
-                       p = sysfs_strdup(cxt->parent, "removable");
+                       p = sysfs_strdup(&cxt->parent->sysfs, "removable");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_ROTA:
-               p = sysfs_strdup(cxt, "queue/rotational");
+               p = sysfs_strdup(&cxt->sysfs, "queue/rotational");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_MODEL:
                if (!cxt->partition && cxt->nslaves == 0) {
-                       p = sysfs_strdup(cxt, "device/model");
+                       p = sysfs_strdup(&cxt->sysfs, "device/model");
                        if (p)
                                tt_line_set_data(ln, col, p);
                }
@@ -676,27 +519,27 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line
                }
                break;
        case COL_ALIOFF:
-               p = sysfs_strdup(cxt, "alignment_offset");
+               p = sysfs_strdup(&cxt->sysfs, "alignment_offset");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_MINIO:
-               p = sysfs_strdup(cxt, "queue/minimum_io_size");
+               p = sysfs_strdup(&cxt->sysfs, "queue/minimum_io_size");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_OPTIO:
-               p = sysfs_strdup(cxt, "queue/optimal_io_size");
+               p = sysfs_strdup(&cxt->sysfs, "queue/optimal_io_size");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_PHYSEC:
-               p = sysfs_strdup(cxt, "queue/physical_block_size");
+               p = sysfs_strdup(&cxt->sysfs, "queue/physical_block_size");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_LOGSEC:
-               p = sysfs_strdup(cxt, "queue/logical_block_size");
+               p = sysfs_strdup(&cxt->sysfs, "queue/logical_block_size");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
@@ -711,19 +554,19 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line
                        tt_line_set_data(ln, col, p);
                break;
        case COL_DALIGN:
-               p = sysfs_strdup(cxt, "discard_alignment");
+               p = sysfs_strdup(&cxt->sysfs, "discard_alignment");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_DGRAN:
-               p = sysfs_strdup(cxt, "queue/discard_granularity");
+               p = sysfs_strdup(&cxt->sysfs, "queue/discard_granularity");
                if (!lsblk->bytes)
                        p = size_to_human_string(atoi(p));
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
        case COL_DMAX:
-               p = sysfs_strdup(cxt, "queue/discard_max_bytes");
+               p = sysfs_strdup(&cxt->sysfs, "queue/discard_max_bytes");
 
                if (!lsblk->bytes)
                        p = size_to_human_string(atoi(p));
@@ -731,7 +574,7 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line
                        tt_line_set_data(ln, col, p);
                break;
        case COL_DZERO:
-               p = sysfs_strdup(cxt, "queue/discard_zeroes_data");
+               p = sysfs_strdup(&cxt->sysfs, "queue/discard_zeroes_data");
                if (p)
                        tt_line_set_data(ln, col, p);
                break;
@@ -753,7 +596,7 @@ static int set_cxt(struct blkdev_cxt *cxt,
                    const char *name,
                    int partition)
 {
-       char *p;
+       dev_t devno;
 
        cxt->parent = parent;
        cxt->name = xstrdup(name);
@@ -761,28 +604,32 @@ static int set_cxt(struct blkdev_cxt *cxt,
 
        cxt->filename = get_device_path(cxt);
 
-       /* open /sys/block/<name> */
-       p = get_sysfs_path(cxt);
-       cxt->sysfs_fd = open(p, O_RDONLY);
-       if (cxt->sysfs_fd < 0)
-               err(EXIT_FAILURE, _("%s: open failed"), p);
-       free(p);
+       devno = sysfs_devname_to_devno(name,
+                       partition && parent ? parent->name : NULL);
+       if (!devno)
+               err(EXIT_FAILURE, _("%s: unknown device name"), name);
 
-       if (sysfs_scanf(cxt, "dev", "%u:%u", &cxt->maj, &cxt->min) != 2)
-               return -1;
+       if (sysfs_init(&cxt->sysfs, devno, &parent->sysfs))
+               err(EXIT_FAILURE, _("%s: failed to initialize sysfs handler"), name);
+
+       cxt->maj = major(devno);
+       cxt->min = minor(devno);
 
-       cxt->size = sysfs_read_u64(cxt, "size") << 9;
+       cxt->size = sysfs_read_u64(&cxt->sysfs, "size") << 9;
 
        /* Ignore devices of zero size */
        if (!lsblk->all_devices && cxt->size == 0)
                return -1;
 
-       if (is_dm(name))
-               cxt->dm_name = sysfs_strdup(cxt, "dm/name");
+       if (is_dm(name)) {
+               cxt->dm_name = sysfs_strdup(&cxt->sysfs, "dm/name");
+               if (!cxt->dm_name)
+                       err(XALLOC_EXIT_CODE, _("cannot duplicate string"));
+       }
+       cxt->nholders = sysfs_count_dirents(&cxt->sysfs, "holders") +
+                       sysfs_count_partitions(&cxt->sysfs, name);
 
-       cxt->nholders = sysfs_count_dirents(cxt, "holders") +
-                       sysfs_count_partitions(cxt);
-       cxt->nslaves = sysfs_count_dirents(cxt, "slaves");
+       cxt->nslaves = sysfs_count_dirents(&cxt->sysfs, "slaves");
 
        return 0;
 }
@@ -797,7 +644,6 @@ static int list_holders(struct blkdev_cxt *cxt)
        struct blkdev_cxt holder = {};
 
        assert(cxt);
-       assert(cxt->sysfs_fd >= 0);
 
        if (lsblk->nodeps)
                return 0;
@@ -806,12 +652,12 @@ static int list_holders(struct blkdev_cxt *cxt)
                return 0;
 
        /* Partitions */
-       dir = sysfs_opendir(cxt, NULL);
+       dir = sysfs_opendir(&cxt->sysfs, NULL);
        if (!dir)
                err(EXIT_FAILURE, _("failed to open device directory in sysfs"));
 
        while ((d = xreaddir(dir))) {
-               if (!is_partition_dirent(dir, d, cxt->name))
+               if (!sysfs_is_partition_dirent(dir, d, cxt->name))
                        continue;
 
                set_cxt(&holder, cxt, d->d_name, 1);
@@ -822,7 +668,7 @@ static int list_holders(struct blkdev_cxt *cxt)
        closedir(dir);
 
        /* Holders */
-       dir = sysfs_opendir(cxt, "holders");
+       dir = sysfs_opendir(&cxt->sysfs, "holders");
        if (!dir)
                return 0;
 
@@ -897,10 +743,10 @@ static int process_one_device(char *devname)
                ssize_t len;
                char path[PATH_MAX], *diskname, *name;
 
-               snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
-                                   major(st.st_rdev), minor(st.st_rdev));
-               diskname = xstrdup(buf);
+               if (!sysfs_devno_path(st.st_rdev, path, sizeof(path)))
+                       err(EXIT_FAILURE, _("failed to compose sysfs path for %s"), devname);
 
+               diskname = xstrdup(buf);
                len = readlink(path, buf, PATH_MAX);
                if (len < 0) {
                        warn(_("%s: failed to read link"), path);