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

Contents of /trunk/src/mountinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2881 - (hide annotations) (download) (as text)
Tue Sep 18 09:20:30 2007 UTC (7 years, 3 months ago) by uberlord
File MIME type: text/x-csrc
File size: 7874 byte(s)
Re-work mountinfo so that we have a lot less OS specific code
1 uberlord 2547 /*
2     mountinfo.c
3     Obtains information about mounted filesystems.
4    
5     Copyright 2007 Gentoo Foundation
6     */
7    
8 vapier 2618 #define APPLET "mountinfo"
9    
10 uberlord 2803 #include <sys/types.h>
11    
12 uberlord 2794 #if defined(__DragonFly__) || defined(__FreeBSD__) || \
13     defined(__NetBSD__) || defined(__OpenBSD__)
14     #define BSD
15 uberlord 2547 #include <sys/param.h>
16     #include <sys/ucred.h>
17     #include <sys/mount.h>
18     #endif
19    
20     #include <errno.h>
21 uberlord 2580 #include <getopt.h>
22 uberlord 2547 #include <limits.h>
23     #include <stdio.h>
24     #include <stdlib.h>
25     #include <string.h>
26 uberlord 2803 #include <regex.h>
27 uberlord 2547
28 uberlord 2799 #include "builtins.h"
29 uberlord 2547 #include "einfo.h"
30     #include "rc.h"
31     #include "rc-misc.h"
32     #include "strlist.h"
33    
34 uberlord 2881 typedef enum {
35     mount_from,
36     mount_to,
37     mount_fstype,
38     mount_options
39     } mount_type;
40 uberlord 2580
41 uberlord 2881 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     *list = rc_strlist_addsortc (*list, p);
121     return (0);
122     }
123    
124     return (-1);
125     }
126    
127 uberlord 2794 #ifdef BSD
128 uberlord 2881
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 uberlord 2547 {
160 uberlord 2577 struct statfs *mnts;
161     int nmnts;
162     int i;
163     char **list = NULL;
164 uberlord 2881 char *options = NULL;
165     int flags;
166     struct opt *o;
167 uberlord 2547
168 uberlord 2577 if ((nmnts = getmntinfo (&mnts, MNT_NOWAIT)) == 0)
169     eerrorx ("getmntinfo: %s", strerror (errno));
170 uberlord 2547
171 uberlord 2577 for (i = 0; i < nmnts; i++) {
172 uberlord 2881 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 uberlord 2577 }
183 uberlord 2881 }
184     flags &= ~o->o_opt;
185 uberlord 2577 }
186 uberlord 2547
187 uberlord 2881 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 uberlord 2577 }
196 uberlord 2547
197 uberlord 2577 return (list);
198 uberlord 2547 }
199    
200     #elif defined (__linux__)
201 uberlord 2881 static char **find_mounts (struct args *args)
202 uberlord 2547 {
203 uberlord 2577 FILE *fp;
204     char buffer[PATH_MAX * 3];
205     char *p;
206     char *from;
207     char *to;
208 uberlord 2784 char *fst;
209 uberlord 2881 char *opts;
210 uberlord 2577 char **list = NULL;
211 uberlord 2569
212 uberlord 2577 if ((fp = fopen ("/proc/mounts", "r")) == NULL)
213     eerrorx ("getmntinfo: %s", strerror (errno));
214 uberlord 2547
215 uberlord 2577 while (fgets (buffer, sizeof (buffer), fp)) {
216     p = buffer;
217     from = strsep (&p, " ");
218     to = strsep (&p, " ");
219 uberlord 2784 fst = strsep (&p, " ");
220 uberlord 2881 opts = strsep (&p, " ");
221 uberlord 2547
222 uberlord 2881 process_mount (&list, args, from, to, fst, opts);
223 uberlord 2577 }
224     fclose (fp);
225 uberlord 2547
226 uberlord 2577 return (list);
227 uberlord 2547 }
228    
229     #else
230     # error "Operating system not supported!"
231     #endif
232    
233 uberlord 2771 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 uberlord 2734 #include "_usage.h"
249 uberlord 2881 #define getoptstring "f:F:n:N:o:O:p:P:iqst" getoptstring_COMMON
250 vapier 2603 static struct option longopts[] = {
251 uberlord 2771 { "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 uberlord 2881 { "options-regex", 1, NULL, 'o'},
256     { "skip-options-regex", 1, NULL, 'O'},
257 uberlord 2771 { "point-regex", 1, NULL, 'p'},
258     { "skip-point-regex", 1, NULL, 'P'},
259 uberlord 2881 { "options", 0, NULL, 'i'},
260 uberlord 2784 { "fstype", 0, NULL, 's'},
261 uberlord 2881 { "node", 0, NULL, 't'},
262 uberlord 2865 { "quiet", 0, NULL, 'q'},
263 uberlord 2734 longopts_COMMON
264 vapier 2603 { NULL, 0, NULL, 0}
265     };
266 vapier 2618 #include "_usage.c"
267 vapier 2603
268 uberlord 2799 int mountinfo (int argc, char **argv)
269 uberlord 2547 {
270 uberlord 2577 int i;
271 uberlord 2881 struct args args;
272 uberlord 2771 regex_t *point_regex = NULL;
273     regex_t *skip_point_regex = NULL;
274 uberlord 2577 char **nodes = NULL;
275 uberlord 2784 char *n;
276 uberlord 2698 int opt;
277 uberlord 2865 bool quiet = false;
278 uberlord 2771 int result;
279 uberlord 2547
280 uberlord 2771 #define DO_REG(_var) \
281     if (_var) free (_var); \
282     _var = get_regex (optarg);
283    
284 uberlord 2881 memset (&args, 0, sizeof (struct args));
285     args.mount_type = mount_to;
286    
287 uberlord 2698 while ((opt = getopt_long (argc, argv, getoptstring,
288     longopts, (int *) 0)) != -1)
289 uberlord 2771 {
290 uberlord 2698 switch (opt) {
291 uberlord 2771 case 'f':
292 uberlord 2881 DO_REG (args.fstype_regex);
293 uberlord 2771 break;
294 uberlord 2580 case 'F':
295 uberlord 2881 DO_REG (args.skip_fstype_regex);
296 uberlord 2580 break;
297 uberlord 2771 case 'n':
298 uberlord 2881 DO_REG (args.node_regex);
299 uberlord 2771 break;
300 uberlord 2580 case 'N':
301 uberlord 2881 DO_REG (args.skip_node_regex);
302 uberlord 2580 break;
303 uberlord 2865 case 'o':
304 uberlord 2881 DO_REG (args.options_regex);
305 uberlord 2865 break;
306 uberlord 2881 case 'O':
307     DO_REG (args.skip_options_regex);
308     break;
309 uberlord 2771 case 'p':
310     DO_REG (point_regex);
311 uberlord 2580 break;
312 uberlord 2771 case 'P':
313     DO_REG (skip_point_regex);
314 uberlord 2580 break;
315 uberlord 2881 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 uberlord 2865 case 'q':
325     quiet = true;
326 uberlord 2580 break;
327    
328 uberlord 2771 case_RC_COMMON_GETOPT
329 uberlord 2577 }
330 uberlord 2771 }
331 uberlord 2547
332 uberlord 2580 while (optind < argc) {
333     if (argv[optind][0] != '/')
334     eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]);
335 uberlord 2881 args.mounts = rc_strlist_add (args.mounts, argv[optind++]);
336 uberlord 2577 }
337 uberlord 2547
338 uberlord 2881 nodes = find_mounts (&args);
339 uberlord 2771
340 uberlord 2881 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 uberlord 2771 rc_strlist_reverse (nodes);
354 uberlord 2547
355 uberlord 2577 result = EXIT_FAILURE;
356 uberlord 2784 STRLIST_FOREACH (nodes, n, i) {
357     if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0)
358 uberlord 2577 continue;
359 uberlord 2784 if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0)
360 uberlord 2771 continue;
361 uberlord 2865 if (! quiet)
362     printf ("%s\n", n);
363 uberlord 2577 result = EXIT_SUCCESS;
364     }
365     rc_strlist_free (nodes);
366 uberlord 2547
367 uberlord 2771 if (point_regex)
368     regfree (point_regex);
369     if (skip_point_regex)
370     regfree (skip_point_regex);
371 uberlord 2547
372 uberlord 2577 exit (result);
373 uberlord 2547 }

  ViewVC Help
Powered by ViewVC 1.1.20