(root)/
util-linux-2.39/
misc-utils/
lsblk-mnt.c
       1  #include "c.h"
       2  #include "pathnames.h"
       3  #include "xalloc.h"
       4  #include "nls.h"
       5  
       6  #include "lsblk.h"
       7  
       8  static struct libmnt_table *mtab, *swaps;
       9  static struct libmnt_cache *mntcache;
      10  
      11  static int table_parser_errcb(struct libmnt_table *tb __attribute__((__unused__)),
      12  			const char *filename, int line)
      13  {
      14  	if (filename)
      15  		warnx(_("%s: parse error at line %d -- ignored"), filename, line);
      16  	return 1;
      17  }
      18  
      19  static struct libmnt_fs *get_active_swap(const char *filename)
      20  {
      21  	assert(filename);
      22  
      23  	if (!swaps) {
      24  		swaps = mnt_new_table();
      25  		if (!swaps)
      26  			return 0;
      27  		if (!mntcache)
      28  			mntcache = mnt_new_cache();
      29  
      30  		mnt_table_set_parser_errcb(swaps, table_parser_errcb);
      31  		mnt_table_set_cache(swaps, mntcache);
      32  
      33  		if (!lsblk->sysroot)
      34  			mnt_table_parse_swaps(swaps, NULL);
      35  		else {
      36  			char buf[PATH_MAX];
      37  			snprintf(buf, sizeof(buf), "%s" _PATH_PROC_SWAPS, lsblk->sysroot);
      38  			mnt_table_parse_swaps(swaps, buf);
      39  		}
      40  	}
      41  
      42  	return mnt_table_find_srcpath(swaps, filename, MNT_ITER_BACKWARD);
      43  }
      44  
      45  void lsblk_device_free_filesystems(struct lsblk_device *dev)
      46  {
      47  	if (!dev)
      48  		return;
      49  
      50  	free(dev->fss);
      51  
      52  	dev->fss = NULL;
      53  	dev->nfss = 0;
      54  	dev->is_mounted = 0;
      55  	dev->is_swap = 0;
      56  }
      57  
      58  static void add_filesystem(struct lsblk_device *dev, struct libmnt_fs *fs)
      59  {
      60  	assert(dev);
      61  	assert(fs);
      62  
      63  	dev->fss = xrealloc(dev->fss, (dev->nfss + 1)
      64  					* sizeof(struct libmnt_fs *));
      65  	dev->fss[dev->nfss] = fs;
      66  	dev->nfss++;
      67  	dev->is_mounted = 1;
      68  }
      69  
      70  struct libmnt_fs **lsblk_device_get_filesystems(struct lsblk_device *dev, size_t *n)
      71  {
      72  	struct libmnt_fs *fs;
      73  	struct libmnt_iter *itr = NULL;
      74  	dev_t devno;
      75  
      76  	assert(dev);
      77  	assert(dev->filename);
      78  
      79  	if (dev->is_mounted)
      80  		goto done;
      81  
      82  	lsblk_device_free_filesystems(dev);	/* reset */
      83  
      84  	if (!mtab) {
      85  		mtab = mnt_new_table();
      86  		if (!mtab)
      87  			return NULL;
      88  		if (!mntcache)
      89  			mntcache = mnt_new_cache();
      90  
      91  		mnt_table_set_parser_errcb(mtab, table_parser_errcb);
      92  		mnt_table_set_cache(mtab, mntcache);
      93  
      94  		if (!lsblk->sysroot)
      95  			mnt_table_parse_mtab(mtab, NULL);
      96  		else {
      97  			char buf[PATH_MAX];
      98  			snprintf(buf, sizeof(buf), "%s" _PATH_PROC_MOUNTINFO, lsblk->sysroot);
      99  			mnt_table_parse_mtab(mtab, buf);
     100  		}
     101  	}
     102  
     103  	devno = makedev(dev->maj, dev->min);
     104  
     105  	/* All mounpoint where is used devno or device name
     106  	 */
     107  	itr = mnt_new_iter(MNT_ITER_BACKWARD);
     108  	while (mnt_table_next_fs(mtab, itr, &fs) == 0) {
     109  		if (mnt_fs_get_devno(fs) != devno &&
     110  		    !mnt_fs_streq_srcpath(fs, dev->filename))
     111  			continue;
     112  		add_filesystem(dev, fs);
     113  	}
     114  
     115  	/* Try mnt_table_find_srcpath() which also canonicalizes patches, etc.
     116  	 */
     117  	if (!dev->nfss) {
     118  		fs = get_active_swap(dev->filename);
     119  		if (!fs) {
     120  			fs = mnt_table_find_srcpath(mtab, dev->filename, MNT_ITER_BACKWARD);
     121  			if (fs)
     122  				dev->is_swap = 1;
     123  		}
     124  		if (fs)
     125  			add_filesystem(dev, fs);
     126  	}
     127  
     128  done:
     129  	mnt_free_iter(itr);
     130  	if (n)
     131  		*n = dev->nfss;
     132  	return dev->fss;
     133  }
     134  
     135  /* Returns mounpoint where the device is mounted. If the device is used for
     136   * more filesystems (subvolumes, ...) than returns the "best" one.
     137   */
     138  const char *lsblk_device_get_mountpoint(struct lsblk_device *dev)
     139  {
     140  	struct libmnt_fs *fs = NULL;
     141  	const char *root;
     142  
     143  	lsblk_device_get_filesystems(dev, NULL);
     144  	if (!dev->nfss)
     145  		return NULL;
     146  
     147  	/* lsblk_device_get_filesystems() scans mountinfo/swaps in backward
     148  	 * order. It means the first in fss[] is the last mounted FS. Let's
     149  	 * keep it as default */
     150  	fs = dev->fss[0];
     151  	root = mnt_fs_get_root(fs);
     152  
     153  	if (root && strcmp(root, "/") != 0) {
     154  		/* FS is subvolume (or subdirectory bind-mount). Try to get
     155  		 * FS with "/" root */
     156  		size_t i;
     157  
     158  		for (i = 1; i < dev->nfss; i++) {
     159  			root = mnt_fs_get_root(dev->fss[i]);
     160  			if (!root || strcmp(root, "/") == 0) {
     161  				fs = dev->fss[i];
     162  				break;
     163  			}
     164  		}
     165  	}
     166  	if (mnt_fs_is_swaparea(fs))
     167  		return "[SWAP]";
     168  	return mnt_fs_get_target(fs);
     169  }
     170  
     171  void lsblk_mnt_init(void)
     172  {
     173  	mnt_init_debug(0);
     174  }
     175  
     176  void lsblk_mnt_deinit(void)
     177  {
     178  	mnt_unref_table(mtab);
     179  	mnt_unref_table(swaps);
     180  	mnt_unref_cache(mntcache);
     181  }