aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2026-01-30 21:16:30 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2026-01-30 21:16:30 +0100
commit2bfe3753d9f02ac01bf245610b4c39da727e2489 (patch)
treec8650b463099d571fa0407e7def9eb0e33eb12f2
parent8463ce06ca9aabc08909f34356b8b0342e5fb8ed (diff)
downloadbusybox-w32-2bfe3753d9f02ac01bf245610b4c39da727e2489.tar.gz
busybox-w32-2bfe3753d9f02ac01bf245610b4c39da727e2489.tar.bz2
busybox-w32-2bfe3753d9f02ac01bf245610b4c39da727e2489.zip
lkblk: list multiple MOUNTPOINTS
function old new delta lsblk_main 550 869 +319 .rodata 106977 107010 +33 process__sys_block_NAME 461 356 -105 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 352/-105) Total: 247 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--util-linux/lsblk.c80
1 files changed, 58 insertions, 22 deletions
diff --git a/util-linux/lsblk.c b/util-linux/lsblk.c
index 560ccbaf8..a482bfbbc 100644
--- a/util-linux/lsblk.c
+++ b/util-linux/lsblk.c
@@ -67,11 +67,12 @@ struct blockdev_info {
67 unsigned long long size; 67 unsigned long long size;
68 const char *type; 68 const char *type;
69 const char *majmin; 69 const char *majmin;
70 const char *mountpoint; 70 //const char *mountpoint;
71}; 71};
72 72
73struct globals { 73struct globals {
74 struct blockdev_info *list; 74 struct blockdev_info *list;
75 char *mountinfo;
75 unsigned count; 76 unsigned count;
76 unsigned exitcode; 77 unsigned exitcode;
77}; 78};
@@ -93,27 +94,47 @@ static struct blockdev_info *get_or_create_info(const char *devname)
93 return &G.list[G.count++]; 94 return &G.list[G.count++];
94} 95}
95 96
96static char *get_mountpoint(const char *devname) 97static char *get_mountpoints(const char *majmin)
97{ 98{
98 char devpath[256]; 99 unsigned len;
99 struct mntent *mnt; 100 char *p, *mountpoints;
100 FILE *mtab; 101
101 char *mountpoint = NULL; 102 mountpoints = NULL;
102 103 len = strlen(majmin);
103 snprintf(devpath, sizeof(devpath), "/dev/%s", devname); 104 p = G.mountinfo; // "/proc/self/mountinfo"
104//TODO: use /proc/self/mountinfo instead, it has MAJ:MIN column which is unambiguous 105 /* lines a-la "63 1 259:3 / /MNTPOINT per-mount_options - ext4 /dev/NAME per-superblock_options" */
105 mtab = setmntent(bb_path_mtab_file, "r"); 106 while (*p) {
106 if (mtab) { 107 char *e, *f;
107 while ((mnt = getmntent(mtab)) != NULL) { 108
108 if (strcmp(mnt->mnt_fsname, devpath) == 0) { 109 p = skip_non_whitespace(p);
109 mountpoint = xstrdup(mnt->mnt_dir); 110 if (*p != ' ') break;
111 // at " 1 259:3"
112 p = skip_non_whitespace(p + 1);
113 if (*p != ' ') break;
114 p++;
115 // at "259:3 / /MNTPOINT"
116 if (strncmp(p, majmin, len) != 0 || (p+=len)[0] != ' ') {
117 p = strchr(p, '\n');
118 if (!p)
110 break; 119 break;
111 } 120 p++;
121 continue;
112 } 122 }
113 endmntent(mtab); 123 // at " / /MNTPOINT"
124 p = skip_non_whitespace(p + 1);
125 if (*p != ' ') break;
126
127 // at " /MNTPOINT"
128 e = skip_non_whitespace(p + 1);
129 // e is at the end of " /MNTPOINT"
130 f = mountpoints;
131// NO. We return " /MNT1 /MNT2 /MNT3" _with_ leading space!
132// if (!f)
133// p++;
134 mountpoints = xasprintf("%s%.*s", f ? f : "", (int)(e - p), p);
135 free(f);
114 } 136 }
115 137 return mountpoints;
116 return mountpoint;
117} 138}
118 139
119static char *get_majmin_from_stat(const char *filename) 140static char *get_majmin_from_stat(const char *filename)
@@ -209,7 +230,7 @@ static void process__sys_dev_block_MAJMIN(const char *path, char *majmin, const
209 info->majmin = majmin; 230 info->majmin = majmin;
210 //info->rm = ...; 231 //info->rm = ...;
211 //info->ro = ...; 232 //info->ro = ...;
212 info->mountpoint = get_mountpoint(devname); 233 //info->mountpoint = get_mountpoint(majmin);
213 234
214 /* Scan for partititons */ 235 /* Scan for partititons */
215 dir = xopendir(path); 236 dir = xopendir(path);
@@ -254,6 +275,8 @@ int lsblk_main(int argc UNUSED_PARAM, char **argv)
254 getopt32(argv, "a"); 275 getopt32(argv, "a");
255 argv += optind; 276 argv += optind;
256 277
278 G.mountinfo = xmalloc_xopen_read_close("/proc/self/mountinfo", NULL);
279
257 /* If specific devices are requested, process them */ 280 /* If specific devices are requested, process them */
258 if (*argv) { 281 if (*argv) {
259 while (*argv) { 282 while (*argv) {
@@ -326,21 +349,34 @@ int lsblk_main(int argc UNUSED_PARAM, char **argv)
326 qsort(G.list, G.count, sizeof(G.list[0]), compare_devices); 349 qsort(G.list, G.count, sizeof(G.list[0]), compare_devices);
327 350
328 /* Print header */ 351 /* Print header */
329 printf("%-15s MAJ:MIN SIZE TYPE MOUNTPOINT\n", "NAME"); 352 printf("%-15s MAJ:MIN SIZE TYPE MOUNTPOINTS\n", "NAME");
330 //util-linux 2.41.1 default set of fields: 353 //util-linux 2.41.1 default set of fields:
331 //"NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS" 354 //"NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS"
332 355
333 /* Print devices */ 356 /* Print devices */
334 for (i = 0; i < G.count; i++) { 357 for (i = 0; i < G.count; i++) {
335 char buf6[6]; 358 char buf6[6];
359 char *mnt, *e;
360
361 mnt = (get_mountpoints(G.list[i].majmin) ? : (char*)"");
362 e = strchrnul(mnt[0] ? mnt + 1 : "", ' ');
336 smart_ulltoa5(G.list[i].size * 512, buf6, " KMGTPEZY"); 363 smart_ulltoa5(G.list[i].size * 512, buf6, " KMGTPEZY");
337 printf("%-15s %-7s %.5s %4s %s\n", 364 printf("%-15s %-7s %.5s %4s%.*s\n",
338 G.list[i].name, 365 G.list[i].name,
339 G.list[i].majmin, 366 G.list[i].majmin,
340 buf6, 367 buf6,
341 G.list[i].type, 368 G.list[i].type,
342 (G.list[i].mountpoint ? G.list[i].mountpoint : "") 369 (int)(e - mnt), mnt
343 ); 370 );
371 while (*mnt == ' ') {
372//util-linux prints multiple mountpoints on separate lines:
373//DEVNAME 259:3 0 475.4G 0 part /MNT1
374// /MNT2
375 mnt = skip_non_whitespace(mnt + 1);
376 if (!mnt[0]) break;
377 e = strchrnul(mnt + 1, ' ');
378 printf("%34s%.*s\n", "", (int)(e - mnt), mnt);
379 }
344 } 380 }
345 381
346 fflush_stdout_and_exit(G.exitcode); 382 fflush_stdout_and_exit(G.exitcode);