Add a simple lsblk utility that lists information about block devices. Reads from /sys/block to enumerate devices and displays their size, type, and mount point.
Features: - Lists all block devices or specific devices - Shows device size in human-readable format (B, K, M, G, T, P) - Shows device type (disk, loop, rom, etc.) - Shows mount point if device is mounted - Sorts devices alphabetically - Minimal implementation (~2.5 kb) - NOFORK applet for efficiency Signed-off-by: Osama Abdelkader <[email protected]> --- util-linux/lsblk.c | 219 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 util-linux/lsblk.c diff --git a/util-linux/lsblk.c b/util-linux/lsblk.c new file mode 100644 index 000000000..47f217fb8 --- /dev/null +++ b/util-linux/lsblk.c @@ -0,0 +1,219 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini lsblk implementation for busybox + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +//config:config LSBLK +//config: bool "lsblk (2.5 kb)" +//config: default y +//config: help +//config: List information about all available or specified block devices. + +//applet:IF_LSBLK(APPLET_NOFORK(lsblk, lsblk, BB_DIR_USR_BIN, BB_SUID_DROP, lsblk)) + +//kbuild:lib-$(CONFIG_LSBLK) += lsblk.o + +//usage:#define lsblk_trivial_usage +//usage: "[BLOCKDEVICE...]" +//usage:#define lsblk_full_usage "\n\n" +//usage: "List information about all available or specified block devices" + +#include "libbb.h" +#include <mntent.h> + +/* This is a NOFORK applet. Be very careful! */ + +struct blockdev_info { + char *name; + unsigned long long size; + char *type; + char *mountpoint; +}; + +static unsigned long long read_size_from_sysfs(const char *devname) +{ + char path[256]; + char buf[64]; + ssize_t len; + unsigned long long size = 0; + + snprintf(path, sizeof(path), "/sys/block/%s/size", devname); + len = open_read_close(path, buf, sizeof(buf) - 1); + if (len > 0) { + buf[len] = '\0'; + /* Remove trailing newline if present */ + if (buf[len - 1] == '\n') + buf[len - 1] = '\0'; + size = bb_strtoull(buf, NULL, 10); + /* size is in 512-byte sectors, convert to bytes */ + size *= 512; + } + return size; +} + +static char *get_device_type(const char *devname) +{ + char path[256]; + char *buf, *type = NULL; + size_t len; + + /* Try to read from uevent */ + snprintf(path, sizeof(path), "/sys/block/%s/uevent", devname); + buf = xmalloc_open_read_close(path, &len); + if (buf) { + char *p = buf; + while (*p) { + if (strncmp(p, "DEVTYPE=", 8) == 0) { + char *end; + type = xstrdup(p + 8); + /* Remove newline */ + end = strchr(type, '\n'); + if (end) *end = '\0'; + break; + } + p = strchr(p, '\n'); + if (!p) break; + p++; + } + free(buf); + } + + /* Fallback: guess from device name */ + if (!type) { + if (strncmp(devname, "loop", 4) == 0) + type = xstrdup("loop"); + else if (strncmp(devname, "ram", 3) == 0) + type = xstrdup("ram"); + else if (strncmp(devname, "nvme", 4) == 0 || strncmp(devname, "sd", 2) == 0 || + strncmp(devname, "hd", 2) == 0 || strncmp(devname, "vd", 2) == 0) + type = xstrdup("disk"); + else + type = xstrdup("disk"); + } + + return type; +} + +static char *get_mountpoint(const char *devname) +{ + char devpath[256]; + struct mntent *mnt; + FILE *mtab; + char *mountpoint = NULL; + + snprintf(devpath, sizeof(devpath), "/dev/%s", devname); + mtab = setmntent(bb_path_mtab_file, "r"); + if (mtab) { + while ((mnt = getmntent(mtab)) != NULL) { + if (strcmp(mnt->mnt_fsname, devpath) == 0) { + mountpoint = xstrdup(mnt->mnt_dir); + break; + } + } + endmntent(mtab); + } + + return mountpoint; +} + +static void print_size(unsigned long long size) +{ + const char *units[] = {"B", "K", "M", "G", "T", "P"}; + int unit_idx = 0; + double dsize = size; + + while (dsize >= 1024.0 && unit_idx < 5) { + dsize /= 1024.0; + unit_idx++; + } + + if (unit_idx == 0) + printf("%llu", size); + else + printf("%.1f%c", dsize, units[unit_idx][0]); +} + +static int compare_devices(const void *a, const void *b) +{ + const struct blockdev_info *da = (const struct blockdev_info *)a; + const struct blockdev_info *db = (const struct blockdev_info *)b; + return strcmp(da->name, db->name); +} + +int lsblk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int lsblk_main(int argc UNUSED_PARAM, char **argv) +{ + DIR *dir; + struct dirent *entry; + struct blockdev_info *devices = NULL; + int count = 0; + int i; + unsigned opt; + + opt = getopt32(argv, ""); + argv += optind; + + /* If specific devices are requested, process them */ + if (*argv) { + while (*argv) { + char *devname = *argv; + /* Remove /dev/ prefix if present */ + if (strncmp(devname, "/dev/", 5) == 0) + devname += 5; + + devices = xrealloc_vector(devices, 4, count); + devices[count].name = xstrdup(devname); + devices[count].size = read_size_from_sysfs(devname); + devices[count].type = get_device_type(devname); + devices[count].mountpoint = get_mountpoint(devname); + count++; + argv++; + } + } else { + /* Read all devices from /sys/block */ + dir = opendir("/sys/block"); + if (!dir) + bb_simple_perror_msg_and_die("/sys/block"); + + while ((entry = readdir(dir)) != NULL) { + if (DOT_OR_DOTDOT(entry->d_name)) + continue; + + devices = xrealloc_vector(devices, 4, count); + devices[count].name = xstrdup(entry->d_name); + devices[count].size = read_size_from_sysfs(entry->d_name); + devices[count].type = get_device_type(entry->d_name); + devices[count].mountpoint = get_mountpoint(entry->d_name); + count++; + } + closedir(dir); + } + + /* Sort devices by name */ + qsort(devices, count, sizeof(struct blockdev_info), compare_devices); + + /* Print header */ + printf("%-15s %8s %-6s %s\n", "NAME", "SIZE", "TYPE", "MOUNTPOINT"); + + /* Print devices */ + for (i = 0; i < count; i++) { + printf("%-15s ", devices[i].name); + print_size(devices[i].size); + printf(" %-6s ", devices[i].type); + if (devices[i].mountpoint) + printf("%s", devices[i].mountpoint); + printf("\n"); + + free(devices[i].name); + free(devices[i].type); + if (devices[i].mountpoint) + free(devices[i].mountpoint); + } + + if (devices) + free(devices); + + return fflush_all(); +} + -- 2.43.0 _______________________________________________ busybox mailing list [email protected] https://lists.busybox.net/mailman/listinfo/busybox
