hexedit: new applet
[oweals/busybox.git] / miscutils / lsscsi.c
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.4 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
28 static char *get_line(const char *filename, char *buf, unsigned *bufsize_p)
29 {
30         unsigned bufsize = *bufsize_p;
31         ssize_t sz;
32
33         if ((int)(bufsize - 2) <= 0)
34                 return buf;
35
36         sz = open_read_close(filename, buf, bufsize - 2);
37         if (sz < 0)
38                 sz = 0;
39         buf[sz] = '\0';
40
41         sz = (trim(buf) - buf) + 1;
42         bufsize -= sz;
43         buf += sz;
44         buf[0] = '\0';
45
46         *bufsize_p = bufsize;
47         return buf;
48 }
49
50 int lsscsi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
51 int lsscsi_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
52 {
53         struct dirent *de;
54         DIR *dir;
55
56         xchdir("/sys/bus/scsi/devices");
57
58         dir = xopendir(".");
59         while ((de = readdir(dir)) != NULL) {
60                 char buf[256];
61                 char *ptr;
62                 unsigned bufsize;
63                 const char *vendor;
64                 const char *type_str;
65                 const char *type_name;
66                 const char *model;
67                 const char *rev;
68                 unsigned type;
69
70                 if (!isdigit(de->d_name[0]))
71                         continue;
72                 if (!strchr(de->d_name, ':'))
73                         continue;
74                 if (chdir(de->d_name) != 0)
75                         continue;
76
77                 bufsize = sizeof(buf);
78                 vendor = buf;
79                 ptr = get_line("vendor", buf, &bufsize);
80                 type_str = ptr;
81                 ptr = get_line("type", ptr, &bufsize);
82                 model = ptr;
83                 ptr = get_line("model", ptr, &bufsize);
84                 rev = ptr;
85                 ptr = get_line("rev", ptr, &bufsize);
86
87                 printf("[%s]\t", de->d_name);
88
89 #define scsi_device_types \
90         "disk\0"    "tape\0"    "printer\0" "process\0" \
91         "worm\0"    "\0"        "scanner\0" "optical\0" \
92         "mediumx\0" "comms\0"   "\0"        "\0"        \
93         "storage\0" "enclosu\0" "sim dsk\0" "opti rd\0" \
94         "bridge\0"  "osd\0"     "adi\0"     "\0"        \
95         "\0"        "\0"        "\0"        "\0"        \
96         "\0"        "\0"        "\0"        "\0"        \
97         "\0"        "\0"        "wlun\0"    "no dev"
98                 type = bb_strtou(type_str, NULL, 10);
99                 if (errno
100                  || type >= 0x20
101                  || (type_name = nth_string(scsi_device_types, type))[0] == '\0'
102                 ) {
103                         printf("(%s)\t", type_str);
104                 } else {
105                         printf("%s\t", type_name);
106                 }
107
108                 printf("%s\t""%s\t""%s\n",
109                         vendor,
110                         model,
111                         rev
112                 );
113                 /* TODO: also output device column, e.g. "/dev/sdX" */
114
115                 xchdir("..");
116         }
117
118         if (ENABLE_FEATURE_CLEAN_UP)
119                 closedir(dir);
120
121         return EXIT_SUCCESS;
122 }