]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - misc-utils/lsblk-mnt.c
lsblk: move mount stuff to lsblk-mnt.c
[thirdparty/util-linux.git] / misc-utils / lsblk-mnt.c
diff --git a/misc-utils/lsblk-mnt.c b/misc-utils/lsblk-mnt.c
new file mode 100644 (file)
index 0000000..4e1e328
--- /dev/null
@@ -0,0 +1,111 @@
+#include "c.h"
+#include "pathnames.h"
+#include "xalloc.h"
+#include "nls.h"
+
+#include <libmount.h>
+
+#include "lsblk.h"
+
+static struct libmnt_table *mtab, *swaps;
+static struct libmnt_cache *mntcache;
+
+static int table_parser_errcb(struct libmnt_table *tb __attribute__((__unused__)),
+                       const char *filename, int line)
+{
+       if (filename)
+               warnx(_("%s: parse error at line %d -- ignored"), filename, line);
+       return 1;
+}
+
+static int is_active_swap(const char *filename)
+{
+       if (!swaps) {
+               swaps = mnt_new_table();
+               if (!swaps)
+                       return 0;
+               if (!mntcache)
+                       mntcache = mnt_new_cache();
+
+               mnt_table_set_parser_errcb(swaps, table_parser_errcb);
+               mnt_table_set_cache(swaps, mntcache);
+
+               if (!lsblk->sysroot)
+                       mnt_table_parse_swaps(swaps, NULL);
+               else {
+                       char buf[PATH_MAX];
+                       snprintf(buf, sizeof(buf), "%s" _PATH_PROC_SWAPS, lsblk->sysroot);
+                       mnt_table_parse_swaps(swaps, buf);
+               }
+       }
+
+       return mnt_table_find_srcpath(swaps, filename, MNT_ITER_BACKWARD) != NULL;
+}
+
+char *get_device_mountpoint(struct blkdev_cxt *cxt)
+{
+       struct libmnt_fs *fs;
+       const char *fsroot;
+
+       assert(cxt);
+       assert(cxt->filename);
+
+       if (cxt->is_mounted)
+               return cxt->mountpoint;
+
+       if (!mtab) {
+               mtab = mnt_new_table();
+               if (!mtab)
+                       return NULL;
+               if (!mntcache)
+                       mntcache = mnt_new_cache();
+
+               mnt_table_set_parser_errcb(mtab, table_parser_errcb);
+               mnt_table_set_cache(mtab, mntcache);
+
+               if (!lsblk->sysroot)
+                       mnt_table_parse_mtab(mtab, NULL);
+               else {
+                       char buf[PATH_MAX];
+                       snprintf(buf, sizeof(buf), "%s" _PATH_PROC_MOUNTINFO, lsblk->sysroot);
+                       mnt_table_parse_mtab(mtab, buf);
+               }
+       }
+
+       /* Note that maj:min in /proc/self/mountinfo does not have to match with
+        * devno as returned by stat(), so we have to try devname too
+        */
+       fs = mnt_table_find_devno(mtab, makedev(cxt->maj, cxt->min), MNT_ITER_BACKWARD);
+       if (!fs)
+               fs = mnt_table_find_srcpath(mtab, cxt->filename, MNT_ITER_BACKWARD);
+       if (!fs) {
+               cxt->mountpoint = is_active_swap(cxt->filename) ? xstrdup("[SWAP]") : NULL;
+               cxt->is_mounted = 1;
+               return cxt->mountpoint;
+       }
+
+       /* found */
+       fsroot = mnt_fs_get_root(fs);
+       if (fsroot && strcmp(fsroot, "/") != 0) {
+               /* hmm.. we found bind mount or btrfs subvolume, let's try to
+                * get real FS root mountpoint */
+               struct libmnt_fs *rfs;
+               struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_BACKWARD);
+
+               mnt_table_set_iter(mtab, itr, fs);
+               while (mnt_table_next_fs(mtab, itr, &rfs) == 0) {
+                       fsroot = mnt_fs_get_root(rfs);
+                       if ((!fsroot || strcmp(fsroot, "/") == 0)
+                           && mnt_fs_match_source(rfs, cxt->filename, mntcache)) {
+                               fs = rfs;
+                               break;
+                       }
+               }
+               mnt_free_iter(itr);
+       }
+
+       DBG(DEV, ul_debugobj(cxt, "mountpoint: %s", mnt_fs_get_target(fs)));
+       cxt->mountpoint = xstrdup(mnt_fs_get_target(fs));
+       cxt->is_mounted = 1;
+       return cxt->mountpoint;
+}