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