/[baselayout]/trunk/src/mountinfo.c
Gentoo

Contents of /trunk/src/mountinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2906 - (show annotations) (download) (as text)
Fri Sep 21 11:52:37 2007 UTC (7 years, 2 months ago) by uberlord
File MIME type: text/x-csrc
File size: 7813 byte(s)
Add extraopts to our usage
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
12 #if defined(__DragonFly__) || defined(__FreeBSD__) || \
13 defined(__NetBSD__) || defined(__OpenBSD__)
14 #define BSD
15 #include <sys/param.h>
16 #include <sys/ucred.h>
17 #include <sys/mount.h>
18 #endif
19
20 #include <errno.h>
21 #include <getopt.h>
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <regex.h>
27
28 #include "builtins.h"
29 #include "einfo.h"
30 #include "rc.h"
31 #include "rc-misc.h"
32 #include "strlist.h"
33
34 typedef enum {
35 mount_from,
36 mount_to,
37 mount_fstype,
38 mount_options
39 } mount_type;
40
41 struct args {
42 regex_t *node_regex;
43 regex_t *skip_node_regex;
44 regex_t *fstype_regex;
45 regex_t *skip_fstype_regex;
46 regex_t *options_regex;
47 regex_t *skip_options_regex;
48 char **mounts;
49 mount_type mount_type;
50 };
51
52 static int process_mount (char ***list, struct args *args,
53 char *from, char *to, char *fstype, char *options)
54 {
55 char *p;
56
57 errno = ENOENT;
58
59 #ifdef __linux__
60 /* Skip the really silly rootfs */
61 if (strcmp (fstype, "rootfs") == 0)
62 return (-1);
63 #endif
64
65 if (args->node_regex &&
66 regexec (args->node_regex, from, 0, NULL, 0) != 0)
67 return (1);
68 if (args->skip_node_regex &&
69 regexec (args->skip_node_regex, from, 0, NULL, 0) == 0)
70 return (1);
71
72 if (args->fstype_regex &&
73 regexec (args->fstype_regex, fstype, 0, NULL, 0) != 0)
74 return (-1);
75 if (args->skip_fstype_regex &&
76 regexec (args->skip_fstype_regex, fstype, 0, NULL, 0) == 0)
77 return (-1);
78
79 if (args->options_regex &&
80 regexec (args->options_regex, options, 0, NULL, 0) != 0)
81 return (-1);
82 if (args->skip_options_regex &&
83 regexec (args->skip_options_regex, options, 0, NULL, 0) == 0)
84 return (-1);
85
86 if (args->mounts) {
87 bool found = false;
88 int j;
89 char *mnt;
90 STRLIST_FOREACH (args->mounts, mnt, j)
91 if (strcmp (mnt, to) == 0) {
92 found = true;
93 break;
94 }
95 if (! found)
96 return (-1);
97 }
98
99 switch (args->mount_type) {
100 case mount_from:
101 p = from;
102 break;
103 case mount_to:
104 p = to;
105 break;
106 case mount_fstype:
107 p = fstype;
108 break;
109 case mount_options:
110 p = options;
111 break;
112 default:
113 p = NULL;
114 errno = EINVAL;
115 break;
116 }
117
118 if (p) {
119 errno = 0;
120 rc_strlist_addsortc (list, p);
121 return (0);
122 }
123
124 return (-1);
125 }
126
127 #ifdef BSD
128
129 /* Translate the mounted options to english
130 * This is taken directly from FreeBSD mount.c */
131 static struct opt {
132 int o_opt;
133 const char *o_name;
134 } optnames[] = {
135 { MNT_ASYNC, "asynchronous" },
136 { MNT_EXPORTED, "NFS exported" },
137 { MNT_LOCAL, "local" },
138 { MNT_NOATIME, "noatime" },
139 { MNT_NOEXEC, "noexec" },
140 { MNT_NOSUID, "nosuid" },
141 { MNT_NOSYMFOLLOW, "nosymfollow" },
142 { MNT_QUOTA, "with quotas" },
143 { MNT_RDONLY, "read-only" },
144 { MNT_SYNCHRONOUS, "synchronous" },
145 { MNT_UNION, "union" },
146 { MNT_NOCLUSTERR, "noclusterr" },
147 { MNT_NOCLUSTERW, "noclusterw" },
148 { MNT_SUIDDIR, "suiddir" },
149 { MNT_SOFTDEP, "soft-updates" },
150 { MNT_MULTILABEL, "multilabel" },
151 { MNT_ACLS, "acls" },
152 #ifdef MNT_GJOURNAL
153 { MNT_GJOURNAL, "gjournal" },
154 #endif
155 { 0, NULL }
156 };
157
158 static char **find_mounts (struct args *args)
159 {
160 struct statfs *mnts;
161 int nmnts;
162 int i;
163 char **list = NULL;
164 char *options = NULL;
165 int flags;
166 struct opt *o;
167
168 if ((nmnts = getmntinfo (&mnts, MNT_NOWAIT)) == 0)
169 eerrorx ("getmntinfo: %s", strerror (errno));
170
171 for (i = 0; i < nmnts; i++) {
172 flags = mnts[i].f_flags & MNT_VISFLAGMASK;
173 for (o = optnames; flags && o->o_opt; o++) {
174 if (flags & o->o_opt) {
175 if (! options)
176 options = rc_xstrdup (o->o_name);
177 else {
178 char *tmp = NULL;
179 asprintf (&tmp, "%s,%s", options, o->o_name);
180 free (options);
181 options = tmp;
182 }
183 }
184 flags &= ~o->o_opt;
185 }
186
187 process_mount (&list, args,
188 mnts[i].f_mntfromname,
189 mnts[i].f_mntonname,
190 mnts[i].f_fstypename,
191 options);
192
193 free (options);
194 options = NULL;
195 }
196
197 return (list);
198 }
199
200 #elif defined (__linux__)
201 static char **find_mounts (struct args *args)
202 {
203 FILE *fp;
204 char buffer[PATH_MAX * 3];
205 char *p;
206 char *from;
207 char *to;
208 char *fst;
209 char *opts;
210 char **list = NULL;
211
212 if ((fp = fopen ("/proc/mounts", "r")) == NULL)
213 eerrorx ("getmntinfo: %s", strerror (errno));
214
215 while (fgets (buffer, sizeof (buffer), fp)) {
216 p = buffer;
217 from = strsep (&p, " ");
218 to = strsep (&p, " ");
219 fst = strsep (&p, " ");
220 opts = strsep (&p, " ");
221
222 process_mount (&list, args, from, to, fst, opts);
223 }
224 fclose (fp);
225
226 return (list);
227 }
228
229 #else
230 # error "Operating system not supported!"
231 #endif
232
233 static regex_t *get_regex (char *string)
234 {
235 regex_t *reg = rc_xmalloc (sizeof (regex_t));
236 int result;
237 char buffer[256];
238
239 if ((result = regcomp (reg, string, REG_EXTENDED | REG_NOSUB)) != 0)
240 {
241 regerror (result, reg, buffer, sizeof (buffer));
242 eerrorx ("%s: invalid regex `%s'", APPLET, buffer);
243 }
244
245 return (reg);
246 }
247
248 #include "_usage.h"
249 #define extraopts "[mount1] [mount2] ..."
250 #define getoptstring "f:F:n:N:o:O:p:P:iqst" getoptstring_COMMON
251 static struct option longopts[] = {
252 { "fstype-regex", 1, NULL, 'f'},
253 { "skip-fstype-regex", 1, NULL, 'F'},
254 { "node-regex", 1, NULL, 'n'},
255 { "skip-node-regex", 1, NULL, 'N'},
256 { "options-regex", 1, NULL, 'o'},
257 { "skip-options-regex", 1, NULL, 'O'},
258 { "point-regex", 1, NULL, 'p'},
259 { "skip-point-regex", 1, NULL, 'P'},
260 { "options", 0, NULL, 'i'},
261 { "fstype", 0, NULL, 's'},
262 { "node", 0, NULL, 't'},
263 longopts_COMMON
264 { NULL, 0, NULL, 0}
265 };
266 #include "_usage.c"
267
268 int mountinfo (int argc, char **argv)
269 {
270 int i;
271 struct args args;
272 regex_t *point_regex = NULL;
273 regex_t *skip_point_regex = NULL;
274 char **nodes = NULL;
275 char *n;
276 int opt;
277 int result;
278
279 #define DO_REG(_var) \
280 if (_var) free (_var); \
281 _var = get_regex (optarg);
282
283 memset (&args, 0, sizeof (struct args));
284 args.mount_type = mount_to;
285
286 while ((opt = getopt_long (argc, argv, getoptstring,
287 longopts, (int *) 0)) != -1)
288 {
289 switch (opt) {
290 case 'f':
291 DO_REG (args.fstype_regex);
292 break;
293 case 'F':
294 DO_REG (args.skip_fstype_regex);
295 break;
296 case 'n':
297 DO_REG (args.node_regex);
298 break;
299 case 'N':
300 DO_REG (args.skip_node_regex);
301 break;
302 case 'o':
303 DO_REG (args.options_regex);
304 break;
305 case 'O':
306 DO_REG (args.skip_options_regex);
307 break;
308 case 'p':
309 DO_REG (point_regex);
310 break;
311 case 'P':
312 DO_REG (skip_point_regex);
313 break;
314 case 'i':
315 args.mount_type = mount_options;
316 break;
317 case 's':
318 args.mount_type = mount_fstype;
319 break;
320 case 't':
321 args.mount_type = mount_from;
322 break;
323
324 case_RC_COMMON_GETOPT
325 }
326 }
327
328 while (optind < argc) {
329 if (argv[optind][0] != '/')
330 eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]);
331 rc_strlist_add (&args.mounts, argv[optind++]);
332 }
333
334 nodes = find_mounts (&args);
335
336 if (args.fstype_regex)
337 regfree (args.fstype_regex);
338 if (args.skip_fstype_regex)
339 regfree (args.skip_fstype_regex);
340 if (args.node_regex)
341 regfree (args.node_regex);
342 if (args.skip_node_regex)
343 regfree (args.skip_node_regex);
344 if (args.options_regex)
345 regfree (args.options_regex);
346 if (args.skip_options_regex)
347 regfree (args.skip_options_regex);
348
349 rc_strlist_reverse (nodes);
350
351 result = EXIT_FAILURE;
352 STRLIST_FOREACH (nodes, n, i) {
353 if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0)
354 continue;
355 if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0)
356 continue;
357 if (! rc_is_env ("RC_QUIET", "yes"))
358 printf ("%s\n", n);
359 result = EXIT_SUCCESS;
360 }
361 rc_strlist_free (nodes);
362
363 if (point_regex)
364 regfree (point_regex);
365 if (skip_point_regex)
366 regfree (skip_point_regex);
367
368 exit (result);
369 }

  ViewVC Help
Powered by ViewVC 1.1.20