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

Contents of /trunk/src/mountinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2928 - (hide annotations) (download) (as text)
Tue Sep 25 17:30:07 2007 UTC (7 years, 2 months ago) by uberlord
File MIME type: text/x-csrc
File size: 7816 byte(s)
Revert last patch
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 uberlord 2884 asprintf (&tmp, "%s,%s", options, o->o_name);
180 uberlord 2881 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 2908 static regex_t *get_regex (const char *string)
234 uberlord 2771 {
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 2906 #define extraopts "[mount1] [mount2] ..."
250 uberlord 2881 #define getoptstring "f:F:n:N:o:O:p:P:iqst" getoptstring_COMMON
251 vapier 2603 static struct option longopts[] = {
252 uberlord 2771 { "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 uberlord 2881 { "options-regex", 1, NULL, 'o'},
257     { "skip-options-regex", 1, NULL, 'O'},
258 uberlord 2771 { "point-regex", 1, NULL, 'p'},
259     { "skip-point-regex", 1, NULL, 'P'},
260 uberlord 2881 { "options", 0, NULL, 'i'},
261 uberlord 2784 { "fstype", 0, NULL, 's'},
262 uberlord 2881 { "node", 0, NULL, 't'},
263 uberlord 2734 longopts_COMMON
264 vapier 2603 { NULL, 0, NULL, 0}
265     };
266 vapier 2923 static const char * const longopts_help[] = {
267     "",
268     "",
269     "",
270     "",
271     "",
272     "",
273     "",
274     "",
275     "",
276     "",
277     "",
278     longopts_help_COMMON
279     };
280 vapier 2618 #include "_usage.c"
281 vapier 2603
282 uberlord 2799 int mountinfo (int argc, char **argv)
283 uberlord 2547 {
284 uberlord 2577 int i;
285 uberlord 2881 struct args args;
286 uberlord 2771 regex_t *point_regex = NULL;
287     regex_t *skip_point_regex = NULL;
288 uberlord 2577 char **nodes = NULL;
289 uberlord 2784 char *n;
290 uberlord 2698 int opt;
291 uberlord 2771 int result;
292 uberlord 2547
293 uberlord 2771 #define DO_REG(_var) \
294     if (_var) free (_var); \
295     _var = get_regex (optarg);
296 uberlord 2908 #define REG_FREE(_var) \
297     if (_var) { regfree (_var); free (_var); }
298 uberlord 2771
299 uberlord 2881 memset (&args, 0, sizeof (struct args));
300     args.mount_type = mount_to;
301    
302 uberlord 2698 while ((opt = getopt_long (argc, argv, getoptstring,
303     longopts, (int *) 0)) != -1)
304 uberlord 2771 {
305 uberlord 2698 switch (opt) {
306 uberlord 2771 case 'f':
307 uberlord 2881 DO_REG (args.fstype_regex);
308 uberlord 2771 break;
309 uberlord 2580 case 'F':
310 uberlord 2881 DO_REG (args.skip_fstype_regex);
311 uberlord 2580 break;
312 uberlord 2771 case 'n':
313 uberlord 2881 DO_REG (args.node_regex);
314 uberlord 2771 break;
315 uberlord 2580 case 'N':
316 uberlord 2881 DO_REG (args.skip_node_regex);
317 uberlord 2580 break;
318 uberlord 2865 case 'o':
319 uberlord 2881 DO_REG (args.options_regex);
320 uberlord 2865 break;
321 uberlord 2881 case 'O':
322     DO_REG (args.skip_options_regex);
323     break;
324 uberlord 2771 case 'p':
325     DO_REG (point_regex);
326 uberlord 2580 break;
327 uberlord 2771 case 'P':
328     DO_REG (skip_point_regex);
329 uberlord 2580 break;
330 uberlord 2881 case 'i':
331     args.mount_type = mount_options;
332     break;
333     case 's':
334     args.mount_type = mount_fstype;
335     break;
336     case 't':
337     args.mount_type = mount_from;
338     break;
339 uberlord 2580
340 uberlord 2771 case_RC_COMMON_GETOPT
341 uberlord 2577 }
342 uberlord 2771 }
343 uberlord 2547
344 uberlord 2580 while (optind < argc) {
345     if (argv[optind][0] != '/')
346     eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]);
347 uberlord 2882 rc_strlist_add (&args.mounts, argv[optind++]);
348 uberlord 2577 }
349 uberlord 2547
350 uberlord 2881 nodes = find_mounts (&args);
351 uberlord 2771
352 uberlord 2908 REG_FREE (args.fstype_regex);
353     REG_FREE (args.skip_fstype_regex);
354     REG_FREE (args.node_regex);
355     REG_FREE (args.skip_node_regex);
356     REG_FREE (args.options_regex);
357     REG_FREE (args.skip_options_regex);
358 uberlord 2881
359 uberlord 2771 rc_strlist_reverse (nodes);
360 uberlord 2547
361 uberlord 2577 result = EXIT_FAILURE;
362 uberlord 2784 STRLIST_FOREACH (nodes, n, i) {
363     if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0)
364 uberlord 2577 continue;
365 uberlord 2784 if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0)
366 uberlord 2771 continue;
367 uberlord 2928 if (! rc_is_env ("RC_QUIET", "yes"))
368 uberlord 2865 printf ("%s\n", n);
369 uberlord 2577 result = EXIT_SUCCESS;
370     }
371     rc_strlist_free (nodes);
372 uberlord 2547
373 uberlord 2908 REG_FREE (point_regex);
374     REG_FREE (skip_point_regex);
375 uberlord 2547
376 uberlord 2577 exit (result);
377 uberlord 2547 }

  ViewVC Help
Powered by ViewVC 1.1.20