lsscsi.c 2.8 KB

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