blob: 1521680acfbe0f54b47dd2fe8944658289633c1a [file] [log] [blame]
Markus Gothe9c7ee142017-04-18 19:25:49 +02001/* 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
28static 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
51int lsscsi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
52int 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}