]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/lsblk-mnt.c
Merge branch 'meson-more-build-options' of https://github.com/jwillikers/util-linux
[thirdparty/util-linux.git] / misc-utils / lsblk-mnt.c
CommitLineData
cfb715ed
KZ
1#include "c.h"
2#include "pathnames.h"
3#include "xalloc.h"
4#include "nls.h"
5
cfb715ed
KZ
6#include "lsblk.h"
7
8static struct libmnt_table *mtab, *swaps;
9static struct libmnt_cache *mntcache;
10
11static 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
c6648d2d 19static struct libmnt_fs *get_active_swap(const char *filename)
cfb715ed 20{
c6648d2d
KZ
21 assert(filename);
22
cfb715ed
KZ
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
c6648d2d
KZ
42 return mnt_table_find_srcpath(swaps, filename, MNT_ITER_BACKWARD);
43}
44
45void 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
58static void add_filesystem(struct lsblk_device *dev, struct libmnt_fs *fs)
59{
60 assert(dev);
61 assert(fs);
62
64d6d400 63 dev->fss = xreallocarray(dev->fss, dev->nfss + 1, sizeof(struct libmnt_fs *));
c6648d2d
KZ
64 dev->fss[dev->nfss] = fs;
65 dev->nfss++;
66 dev->is_mounted = 1;
cfb715ed
KZ
67}
68
c6648d2d 69struct libmnt_fs **lsblk_device_get_filesystems(struct lsblk_device *dev, size_t *n)
cfb715ed
KZ
70{
71 struct libmnt_fs *fs;
c6648d2d
KZ
72 struct libmnt_iter *itr = NULL;
73 dev_t devno;
cfb715ed 74
fed34a1e
KZ
75 assert(dev);
76 assert(dev->filename);
cfb715ed 77
c6648d2d
KZ
78 if (dev->is_mounted)
79 goto done;
80
81 lsblk_device_free_filesystems(dev); /* reset */
cfb715ed
KZ
82
83 if (!mtab) {
84 mtab = mnt_new_table();
85 if (!mtab)
86 return NULL;
87 if (!mntcache)
88 mntcache = mnt_new_cache();
89
90 mnt_table_set_parser_errcb(mtab, table_parser_errcb);
91 mnt_table_set_cache(mtab, mntcache);
92
93 if (!lsblk->sysroot)
94 mnt_table_parse_mtab(mtab, NULL);
95 else {
96 char buf[PATH_MAX];
97 snprintf(buf, sizeof(buf), "%s" _PATH_PROC_MOUNTINFO, lsblk->sysroot);
98 mnt_table_parse_mtab(mtab, buf);
99 }
100 }
101
c6648d2d
KZ
102 devno = makedev(dev->maj, dev->min);
103
104 /* All mounpoint where is used devno or device name
105 */
106 itr = mnt_new_iter(MNT_ITER_BACKWARD);
107 while (mnt_table_next_fs(mtab, itr, &fs) == 0) {
108 if (mnt_fs_get_devno(fs) != devno &&
109 !mnt_fs_streq_srcpath(fs, dev->filename))
110 continue;
111 add_filesystem(dev, fs);
112 }
113
993556aa 114 /* Try mnt_table_find_srcpath() which also canonicalizes patches, etc.
cfb715ed 115 */
c6648d2d
KZ
116 if (!dev->nfss) {
117 fs = get_active_swap(dev->filename);
118 if (!fs) {
119 fs = mnt_table_find_srcpath(mtab, dev->filename, MNT_ITER_BACKWARD);
120 if (fs)
121 dev->is_swap = 1;
122 }
123 if (fs)
124 add_filesystem(dev, fs);
cfb715ed
KZ
125 }
126
c6648d2d
KZ
127done:
128 mnt_free_iter(itr);
129 if (n)
130 *n = dev->nfss;
131 return dev->fss;
132}
133
134/* Returns mounpoint where the device is mounted. If the device is used for
135 * more filesystems (subvolumes, ...) than returns the "best" one.
136 */
137const char *lsblk_device_get_mountpoint(struct lsblk_device *dev)
138{
139 struct libmnt_fs *fs = NULL;
140 const char *root;
141
142 lsblk_device_get_filesystems(dev, NULL);
143 if (!dev->nfss)
144 return NULL;
145
146 /* lsblk_device_get_filesystems() scans mountinfo/swaps in backward
147 * order. It means the first in fss[] is the last mounted FS. Let's
148 * keep it as default */
149 fs = dev->fss[0];
150 root = mnt_fs_get_root(fs);
151
152 if (root && strcmp(root, "/") != 0) {
153 /* FS is subvolume (or subdirectory bind-mount). Try to get
154 * FS with "/" root */
155 size_t i;
156
157 for (i = 1; i < dev->nfss; i++) {
158 root = mnt_fs_get_root(dev->fss[i]);
159 if (!root || strcmp(root, "/") == 0) {
160 fs = dev->fss[i];
cfb715ed
KZ
161 break;
162 }
163 }
cfb715ed 164 }
c6648d2d
KZ
165 if (mnt_fs_is_swaparea(fs))
166 return "[SWAP]";
167 return mnt_fs_get_target(fs);
cfb715ed 168}
e0c016f1
KZ
169
170void lsblk_mnt_init(void)
171{
172 mnt_init_debug(0);
173}
174
175void lsblk_mnt_deinit(void)
176{
177 mnt_unref_table(mtab);
178 mnt_unref_table(swaps);
179 mnt_unref_cache(mntcache);
180}