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