1 |
/* |
2 |
mountinfo.c |
3 |
Obtains information about mounted filesystems. |
4 |
|
5 |
Copyright 2007 Gentoo Foundation |
6 |
*/ |
7 |
|
8 |
#define APPLET "mountinfo" |
9 |
|
10 |
#include <sys/types.h> |
11 |
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) |
12 |
#include <sys/param.h> |
13 |
#include <sys/ucred.h> |
14 |
#include <sys/mount.h> |
15 |
#elif defined(__linux__) |
16 |
#include <limits.h> |
17 |
#endif |
18 |
|
19 |
#include <errno.h> |
20 |
#include <getopt.h> |
21 |
#include <limits.h> |
22 |
#include <regex.h> |
23 |
#include <stdio.h> |
24 |
#include <stdlib.h> |
25 |
#include <string.h> |
26 |
|
27 |
#include "einfo.h" |
28 |
#include "rc.h" |
29 |
#include "rc-misc.h" |
30 |
#include "strlist.h" |
31 |
|
32 |
|
33 |
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) |
34 |
static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, |
35 |
char **mounts, bool list_nodes, bool list_fstype) |
36 |
{ |
37 |
struct statfs *mnts; |
38 |
int nmnts; |
39 |
int i; |
40 |
char **list = NULL; |
41 |
|
42 |
if ((nmnts = getmntinfo (&mnts, MNT_NOWAIT)) == 0) |
43 |
eerrorx ("getmntinfo: %s", strerror (errno)); |
44 |
|
45 |
for (i = 0; i < nmnts; i++) { |
46 |
if (node_regex && |
47 |
regexec (node_regex, mnts[i].f_mntfromname, 0, NULL, 0) != 0) |
48 |
continue; |
49 |
if (fstype_regex && |
50 |
regexec (fstype_regex, mnts[i].f_fstypename, 0, NULL, 0) != 0) |
51 |
continue; |
52 |
|
53 |
if (mounts) { |
54 |
bool found = false; |
55 |
int j; |
56 |
char *mnt; |
57 |
STRLIST_FOREACH (mounts, mnt, j) |
58 |
if (strcmp (mnt, mnts[i].f_mntonname) == 0) { |
59 |
found = true; |
60 |
break; |
61 |
} |
62 |
if (! found) |
63 |
continue; |
64 |
} |
65 |
|
66 |
list = rc_strlist_addsortc (list, list_nodes ? |
67 |
mnts[i].f_mntfromname : |
68 |
list_fstype ? mnts[i].f_fstypename : |
69 |
mnts[i].f_mntonname); |
70 |
} |
71 |
|
72 |
return (list); |
73 |
} |
74 |
|
75 |
#elif defined (__linux__) |
76 |
static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, |
77 |
char **mounts, bool list_nodes, bool list_fstype) |
78 |
{ |
79 |
FILE *fp; |
80 |
char buffer[PATH_MAX * 3]; |
81 |
char *p; |
82 |
char *from; |
83 |
char *to; |
84 |
char *fstype; |
85 |
char **list = NULL; |
86 |
|
87 |
if ((fp = fopen ("/proc/mounts", "r")) == NULL) |
88 |
eerrorx ("getmntinfo: %s", strerror (errno)); |
89 |
|
90 |
while (fgets (buffer, sizeof (buffer), fp)) { |
91 |
p = buffer; |
92 |
from = strsep (&p, " "); |
93 |
if (node_regex && |
94 |
regexec (node_regex, from, 0, NULL, 0) != 0) |
95 |
continue; |
96 |
|
97 |
to = strsep (&p, " "); |
98 |
fstype = strsep (&p, " "); |
99 |
/* Skip the really silly rootfs */ |
100 |
if (strcmp (fstype, "rootfs") == 0) |
101 |
continue; |
102 |
if (fstype_regex && |
103 |
regexec (fstype_regex, fstype, 0, NULL, 0) != 0) |
104 |
continue; |
105 |
|
106 |
if (mounts) { |
107 |
bool found = false; |
108 |
int j; |
109 |
char *mnt; |
110 |
STRLIST_FOREACH (mounts, mnt, j) |
111 |
if (strcmp (mnt, to) == 0) { |
112 |
found = true; |
113 |
break; |
114 |
} |
115 |
if (! found) |
116 |
continue; |
117 |
} |
118 |
|
119 |
list = rc_strlist_addsortc (list, |
120 |
list_nodes ? |
121 |
list_fstype ? fstype : |
122 |
from : to); |
123 |
} |
124 |
fclose (fp); |
125 |
|
126 |
return (list); |
127 |
} |
128 |
|
129 |
#else |
130 |
# error "Operating system not supported!" |
131 |
#endif |
132 |
|
133 |
#define getoptstring "F:N:S:fnrhV" |
134 |
static struct option longopts[] = { |
135 |
{ "fstype-regex", 1, NULL, 'F'}, |
136 |
{ "node-regex", 1, NULL, 'N'}, |
137 |
{ "skip-regex", 1, NULL, 'S'}, |
138 |
{ "fstype", 0, NULL, 'f'}, |
139 |
{ "node", 0, NULL, 'n'}, |
140 |
{ "reverse", 0, NULL, 'r'}, |
141 |
{ "help", 0, NULL, 'h'}, |
142 |
{ NULL, 0, NULL, 0} |
143 |
}; |
144 |
#include "_usage.c" |
145 |
|
146 |
int main (int argc, char **argv) |
147 |
{ |
148 |
int i; |
149 |
regex_t *fstype_regex = NULL; |
150 |
regex_t *node_regex = NULL; |
151 |
regex_t *skip_regex = NULL; |
152 |
char **nodes = NULL; |
153 |
char *node; |
154 |
int result; |
155 |
char buffer[256]; |
156 |
bool list_nodes = false; |
157 |
bool list_fstype = false; |
158 |
bool reverse = false; |
159 |
char **mounts = NULL; |
160 |
int opt; |
161 |
|
162 |
while ((opt = getopt_long (argc, argv, getoptstring, |
163 |
longopts, (int *) 0)) != -1) |
164 |
switch (opt) { |
165 |
case 'F': |
166 |
if (fstype_regex) |
167 |
free (fstype_regex); |
168 |
fstype_regex = rc_xmalloc (sizeof (regex_t)); |
169 |
if ((result = regcomp (fstype_regex, optarg, |
170 |
REG_EXTENDED | REG_NOSUB)) != 0) |
171 |
{ |
172 |
regerror (result, fstype_regex, buffer, sizeof (buffer)); |
173 |
eerrorx ("%s: invalid regex `%s'", argv[0], buffer); |
174 |
} |
175 |
break; |
176 |
|
177 |
case 'N': |
178 |
if (node_regex) |
179 |
free (node_regex); |
180 |
node_regex = rc_xmalloc (sizeof (regex_t)); |
181 |
if ((result = regcomp (node_regex, optarg, |
182 |
REG_EXTENDED | REG_NOSUB)) != 0) |
183 |
{ |
184 |
regerror (result, node_regex, buffer, sizeof (buffer)); |
185 |
eerrorx ("%s: invalid regex `%s'", argv[0], buffer); |
186 |
} |
187 |
break; |
188 |
|
189 |
case 'S': |
190 |
if (skip_regex) |
191 |
free (skip_regex); |
192 |
skip_regex = rc_xmalloc (sizeof (regex_t)); |
193 |
if ((result = regcomp (skip_regex, optarg, |
194 |
REG_EXTENDED | REG_NOSUB)) != 0) |
195 |
{ |
196 |
regerror (result, skip_regex, buffer, sizeof (buffer)); |
197 |
eerrorx ("%s: invalid regex `%s'", argv[0], buffer); |
198 |
} |
199 |
break; |
200 |
|
201 |
case 'f': |
202 |
list_fstype = true; |
203 |
list_nodes = false; |
204 |
break; |
205 |
|
206 |
case 'n': |
207 |
list_nodes = true; |
208 |
list_fstype = false; |
209 |
break; |
210 |
|
211 |
case 'r': |
212 |
reverse = true; |
213 |
break; |
214 |
|
215 |
case_RC_COMMON_GETOPT |
216 |
} |
217 |
|
218 |
while (optind < argc) { |
219 |
if (argv[optind][0] != '/') |
220 |
eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]); |
221 |
mounts = rc_strlist_add (mounts, argv[optind++]); |
222 |
} |
223 |
nodes = find_mounts (node_regex, fstype_regex, mounts, |
224 |
list_nodes, list_fstype); |
225 |
|
226 |
if (node_regex) |
227 |
regfree (node_regex); |
228 |
if (fstype_regex) |
229 |
regfree (fstype_regex); |
230 |
|
231 |
if (reverse) |
232 |
rc_strlist_reverse (nodes); |
233 |
|
234 |
result = EXIT_FAILURE; |
235 |
STRLIST_FOREACH (nodes, node, i) { |
236 |
if (skip_regex && regexec (skip_regex, node, 0, NULL, 0) == 0) |
237 |
continue; |
238 |
printf ("%s\n", node); |
239 |
result = EXIT_SUCCESS; |
240 |
} |
241 |
rc_strlist_free (nodes); |
242 |
|
243 |
if (skip_regex) |
244 |
free (skip_regex); |
245 |
|
246 |
exit (result); |
247 |
} |