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

Contents of /trunk/src/mountinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2882 - (hide annotations) (download) (as text)
Tue Sep 18 11:36:55 2007 UTC (6 years, 10 months 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 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 uberlord 2882 rc_strlist_addsortc (list, p);
121 uberlord 2881 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 2882 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