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

Contents of /trunk/src/mountinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2882 - (show annotations) (download) (as text)
Tue Sep 18 11:36:55 2007 UTC (7 years ago) by uberlord
File MIME type: text/x-csrc
File size: 7852 byte(s)
    API change! rc_strlist_add and friends now take char *** instead of
    char ** and return a pointer to the item added instead of the new
    list head. This is so we can easily tell if the item was successfully
    added or not instead of iterating through the list looking for it.

    list = rc_strlist_add (list, item);
    becomes
    rc_strlist_add (&list, item);
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 getoptstring "f:F:n:N:o:O:p:P:iqst" getoptstring_COMMON
250 static struct option longopts[] = {
251 { "fstype-regex", 1, NULL, 'f'},
252 { "skip-fstype-regex", 1, NULL, 'F'},
253 { "node-regex", 1, NULL, 'n'},
254 { "skip-node-regex", 1, NULL, 'N'},
255 { "options-regex", 1, NULL, 'o'},
256 { "skip-options-regex", 1, NULL, 'O'},
257 { "point-regex", 1, NULL, 'p'},
258 { "skip-point-regex", 1, NULL, 'P'},
259 { "options", 0, NULL, 'i'},
260 { "fstype", 0, NULL, 's'},
261 { "node", 0, NULL, 't'},
262 { "quiet", 0, NULL, 'q'},
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 bool quiet = false;
278 int result;
279
280 #define DO_REG(_var) \
281 if (_var) free (_var); \
282 _var = get_regex (optarg);
283
284 memset (&args, 0, sizeof (struct args));
285 args.mount_type = mount_to;
286
287 while ((opt = getopt_long (argc, argv, getoptstring,
288 longopts, (int *) 0)) != -1)
289 {
290 switch (opt) {
291 case 'f':
292 DO_REG (args.fstype_regex);
293 break;
294 case 'F':
295 DO_REG (args.skip_fstype_regex);
296 break;
297 case 'n':
298 DO_REG (args.node_regex);
299 break;
300 case 'N':
301 DO_REG (args.skip_node_regex);
302 break;
303 case 'o':
304 DO_REG (args.options_regex);
305 break;
306 case 'O':
307 DO_REG (args.skip_options_regex);
308 break;
309 case 'p':
310 DO_REG (point_regex);
311 break;
312 case 'P':
313 DO_REG (skip_point_regex);
314 break;
315 case 'i':
316 args.mount_type = mount_options;
317 break;
318 case 's':
319 args.mount_type = mount_fstype;
320 break;
321 case 't':
322 args.mount_type = mount_from;
323 break;
324 case 'q':
325 quiet = true;
326 break;
327
328 case_RC_COMMON_GETOPT
329 }
330 }
331
332 while (optind < argc) {
333 if (argv[optind][0] != '/')
334 eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]);
335 rc_strlist_add (&args.mounts, argv[optind++]);
336 }
337
338 nodes = find_mounts (&args);
339
340 if (args.fstype_regex)
341 regfree (args.fstype_regex);
342 if (args.skip_fstype_regex)
343 regfree (args.skip_fstype_regex);
344 if (args.node_regex)
345 regfree (args.node_regex);
346 if (args.skip_node_regex)
347 regfree (args.skip_node_regex);
348 if (args.options_regex)
349 regfree (args.options_regex);
350 if (args.skip_options_regex)
351 regfree (args.skip_options_regex);
352
353 rc_strlist_reverse (nodes);
354
355 result = EXIT_FAILURE;
356 STRLIST_FOREACH (nodes, n, i) {
357 if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0)
358 continue;
359 if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0)
360 continue;
361 if (! quiet)
362 printf ("%s\n", n);
363 result = EXIT_SUCCESS;
364 }
365 rc_strlist_free (nodes);
366
367 if (point_regex)
368 regfree (point_regex);
369 if (skip_point_regex)
370 regfree (skip_point_regex);
371
372 exit (result);
373 }

  ViewVC Help
Powered by ViewVC 1.1.20