← Commit list

2bfe3753d

Denys Vlasenko
Denys Vlasenko
2026-01-30
SUCCESS Duration: 145s

Subject

lkblk: list multiple MOUNTPOINTS

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
gcc -Wp,-MD,applets/.usage.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer      -Iinclude -Iinclude -o applets/usage applets/usage.c

Build Log

(log yok)

Commit Diff GitHub →

util-linux/lsblk.c+58 -22
@@ -67,11 +67,12 @@ struct blockdev_info {
unsigned long long size;
const char *type;
const char *majmin;
- const char *mountpoint;
+ //const char *mountpoint;
};
struct globals {
struct blockdev_info *list;
+ char *mountinfo;
unsigned count;
unsigned exitcode;
};
@@ -93,27 +94,47 @@ static struct blockdev_info *get_or_create_info(const char *devname)
return &G.list[G.count++];
}
-static char *get_mountpoint(const char *devname)
+static char *get_mountpoints(const char *majmin)
{
- char devpath[256];
- struct mntent *mnt;
- FILE *mtab;
- char *mountpoint = NULL;
-
- snprintf(devpath, sizeof(devpath), "/dev/%s", devname);
-//TODO: use /proc/self/mountinfo instead, it has MAJ:MIN column which is unambiguous
- 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);
+ unsigned len;
+ char *p, *mountpoints;
+
+ mountpoints = NULL;
+ len = strlen(majmin);
+ p = G.mountinfo; // "/proc/self/mountinfo"
+ /* lines a-la "63 1 259:3 / /MNTPOINT per-mount_options - ext4 /dev/NAME per-superblock_options" */
+ while (*p) {
+ char *e, *f;
+
+ p = skip_non_whitespace(p);
+ if (*p != ' ') break;
+ // at " 1 259:3"
+ p = skip_non_whitespace(p + 1);
+ if (*p != ' ') break;
+ p++;
+ // at "259:3 / /MNTPOINT"
+ if (strncmp(p, majmin, len) != 0 || (p+=len)[0] != ' ') {
+ p = strchr(p, '\n');
+ if (!p)
break;
- }
+ p++;
+ continue;
}
- endmntent(mtab);
+ // at " / /MNTPOINT"
+ p = skip_non_whitespace(p + 1);
+ if (*p != ' ') break;
+
+ // at " /MNTPOINT"
+ e = skip_non_whitespace(p + 1);
+ // e is at the end of " /MNTPOINT"
+ f = mountpoints;
+// NO. We return " /MNT1 /MNT2 /MNT3" _with_ leading space!
+// if (!f)
+// p++;
+ mountpoints = xasprintf("%s%.*s", f ? f : "", (int)(e - p), p);
+ free(f);
}
-
- return mountpoint;
+ return mountpoints;
}
static 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
info->majmin = majmin;
//info->rm = ...;
//info->ro = ...;
- info->mountpoint = get_mountpoint(devname);
+ //info->mountpoint = get_mountpoint(majmin);
/* Scan for partititons */
dir = xopendir(path);
@@ -254,6 +275,8 @@ int lsblk_main(int argc UNUSED_PARAM, char **argv)
getopt32(argv, "a");
argv += optind;
+ G.mountinfo = xmalloc_xopen_read_close("/proc/self/mountinfo", NULL);
+
/* If specific devices are requested, process them */
if (*argv) {
while (*argv) {
@@ -326,21 +349,34 @@ int lsblk_main(int argc UNUSED_PARAM, char **argv)
qsort(G.list, G.count, sizeof(G.list[0]), compare_devices);
/* Print header */
- printf("%-15s MAJ:MIN SIZE TYPE MOUNTPOINT\n", "NAME");
+ printf("%-15s MAJ:MIN SIZE TYPE MOUNTPOINTS\n", "NAME");
//util-linux 2.41.1 default set of fields:
//"NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS"
/* Print devices */
for (i = 0; i < G.count; i++) {
char buf6[6];
+ char *mnt, *e;
+
+ mnt = (get_mountpoints(G.list[i].majmin) ? : (char*)"");
+ e = strchrnul(mnt[0] ? mnt + 1 : "", ' ');
smart_ulltoa5(G.list[i].size * 512, buf6, " KMGTPEZY");
- printf("%-15s %-7s %.5s %4s %s\n",
+ printf("%-15s %-7s %.5s %4s%.*s\n",
G.list[i].name,
G.list[i].majmin,
buf6,
G.list[i].type,
- (G.list[i].mountpoint ? G.list[i].mountpoint : "")
+ (int)(e - mnt), mnt
);
+ while (*mnt == ' ') {
+//util-linux prints multiple mountpoints on separate lines:
+//DEVNAME 259:3 0 475.4G 0 part /MNT1
+// /MNT2
+ mnt = skip_non_whitespace(mnt + 1);
+ if (!mnt[0]) break;
+ e = strchrnul(mnt + 1, ' ');
+ printf("%34s%.*s\n", "", (int)(e - mnt), mnt);
+ }
}
fflush_stdout_and_exit(G.exitcode);