]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | ||
c6648d2d | 19 | static 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 | ||
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 | ||
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 | 69 | struct 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 |
127 | done: |
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 | */ | |
137 | const 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 | |
170 | void lsblk_mnt_init(void) | |
171 | { | |
172 | mnt_init_debug(0); | |
173 | } | |
174 | ||
175 | void lsblk_mnt_deinit(void) | |
176 | { | |
177 | mnt_unref_table(mtab); | |
178 | mnt_unref_table(swaps); | |
179 | mnt_unref_cache(mntcache); | |
180 | } |