busybox/miscutils/lsscsi.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * lsscsi implementation for busybox
   4 *
   5 * Copyright (C) 2017 Markus Gothe <nietzsche@lysator.liu.se>
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   8 */
   9//config:config LSSCSI
  10//config:       bool "lsscsi (2.5 kb)"
  11//config:       default y
  12//config:       #select PLATFORM_LINUX
  13//config:       help
  14//config:       lsscsi is a utility for displaying information about SCSI buses in the
  15//config:       system and devices connected to them.
  16//config:
  17//config:       This version uses sysfs (/sys/bus/scsi/devices) only.
  18
  19//applet:IF_LSSCSI(APPLET_NOEXEC(lsscsi, lsscsi, BB_DIR_USR_BIN, BB_SUID_DROP, lsscsi))
  20
  21//kbuild:lib-$(CONFIG_LSSCSI) += lsscsi.o
  22
  23//usage:#define lsscsi_trivial_usage NOUSAGE_STR
  24//usage:#define lsscsi_full_usage ""
  25
  26#include "libbb.h"
  27
  28static const char scsi_dir[] ALIGN1 = "/sys/bus/scsi/devices";
  29
  30static char *get_line(const char *filename, char *buf, unsigned *bufsize_p)
  31{
  32        unsigned bufsize = *bufsize_p;
  33        ssize_t sz;
  34
  35        if ((int)(bufsize - 2) <= 0)
  36                return buf;
  37
  38        sz = open_read_close(filename, buf, bufsize - 2);
  39        if (sz < 0)
  40                sz = 0;
  41        buf[sz] = '\0';
  42
  43        sz = (trim(buf) - buf) + 1;
  44        bufsize -= sz;
  45        buf += sz;
  46        buf[0] = '\0';
  47
  48        *bufsize_p = bufsize;
  49        return buf;
  50}
  51
  52int lsscsi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  53int lsscsi_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  54{
  55        struct dirent *de;
  56        DIR *dir;
  57
  58        xchdir(scsi_dir);
  59
  60        dir = xopendir(".");
  61        while ((de = readdir(dir)) != NULL) {
  62                char buf[256];
  63                char *ptr;
  64                unsigned bufsize;
  65                const char *vendor;
  66                const char *type_str;
  67                const char *type_name;
  68                const char *model;
  69                const char *rev;
  70                unsigned type;
  71
  72                if (!isdigit(de->d_name[0]))
  73                        continue;
  74                if (!strchr(de->d_name, ':'))
  75                        continue;
  76                if (chdir(de->d_name) != 0)
  77                        continue;
  78
  79                bufsize = sizeof(buf);
  80                vendor = buf;
  81                ptr = get_line("vendor", buf, &bufsize);
  82                type_str = ptr;
  83                ptr = get_line("type", ptr, &bufsize);
  84                model = ptr;
  85                ptr = get_line("model", ptr, &bufsize);
  86                rev = ptr;
  87                ptr = get_line("rev", ptr, &bufsize);
  88
  89                printf("[%s]\t", de->d_name);
  90
  91#define scsi_device_types \
  92        "disk\0"    "tape\0"    "printer\0" "process\0" \
  93        "worm\0"    "\0"        "scanner\0" "optical\0" \
  94        "mediumx\0" "comms\0"   "\0"        "\0"        \
  95        "storage\0" "enclosu\0" "sim dsk\0" "opti rd\0" \
  96        "bridge\0"  "osd\0"     "adi\0"     "\0"        \
  97        "\0"        "\0"        "\0"        "\0"        \
  98        "\0"        "\0"        "\0"        "\0"        \
  99        "\0"        "\0"        "wlun\0"    "no dev"
 100                type = bb_strtou(type_str, NULL, 10);
 101                if (errno
 102                 || type >= 0x20
 103                 || (type_name = nth_string(scsi_device_types, type))[0] == '\0'
 104                ) {
 105                        printf("(%s)\t", type_str);
 106                } else {
 107                        printf("%s\t", type_name);
 108                }
 109
 110                printf("%s\t""%s\t""%s\n",
 111                        vendor,
 112                        model,
 113                        rev
 114                );
 115                /* TODO: also output device column, e.g. "/dev/sdX" */
 116
 117                /* chdir("..") may not work as expected,
 118                 * since we might have followed a symlink.
 119                 */
 120                xchdir(scsi_dir);
 121        }
 122
 123        if (ENABLE_FEATURE_CLEAN_UP)
 124                closedir(dir);
 125
 126        return EXIT_SUCCESS;
 127}
 128