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

Contents of /trunk/src/mountinfo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2897 - (show annotations) (download) (as text)
Wed Sep 19 16:27:37 2007 UTC (6 years, 6 months ago) by uberlord
File MIME type: text/x-csrc
File size: 7771 byte(s)
    Added the checkown applet based on the work by Renato Caldas, #192682
    checkdir ensures that the specified files (or directories) are owned
    by the current user/group or as specified on the command line. You can
    optionally check permissions too.
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 longopts_COMMON
263 { NULL, 0, NULL, 0}
264 };
265 #include "_usage.c"
266
267 int mountinfo (int argc, char **argv)
268 {
269 int i;
270 struct args args;
271 regex_t *point_regex = NULL;
272 regex_t *skip_point_regex = NULL;
273 char **nodes = NULL;
274 char *n;
275 int opt;
276 int result;
277
278 #define DO_REG(_var) \
279 if (_var) free (_var); \
280 _var = get_regex (optarg);
281
282 memset (&args, 0, sizeof (struct args));
283 args.mount_type = mount_to;
284
285 while ((opt = getopt_long (argc, argv, getoptstring,
286 longopts, (int *) 0)) != -1)
287 {
288 switch (opt) {
289 case 'f':
290 DO_REG (args.fstype_regex);
291 break;
292 case 'F':
293 DO_REG (args.skip_fstype_regex);
294 break;
295 case 'n':
296 DO_REG (args.node_regex);
297 break;
298 case 'N':
299 DO_REG (args.skip_node_regex);
300 break;
301 case 'o':
302 DO_REG (args.options_regex);
303 break;
304 case 'O':
305 DO_REG (args.skip_options_regex);
306 break;
307 case 'p':
308 DO_REG (point_regex);
309 break;
310 case 'P':
311 DO_REG (skip_point_regex);
312 break;
313 case 'i':
314 args.mount_type = mount_options;
315 break;
316 case 's':
317 args.mount_type = mount_fstype;
318 break;
319 case 't':
320 args.mount_type = mount_from;
321 break;
322
323 case_RC_COMMON_GETOPT
324 }
325 }
326
327 while (optind < argc) {
328 if (argv[optind][0] != '/')
329 eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]);
330 rc_strlist_add (&args.mounts, argv[optind++]);
331 }
332
333 nodes = find_mounts (&args);
334
335 if (args.fstype_regex)
336 regfree (args.fstype_regex);
337 if (args.skip_fstype_regex)
338 regfree (args.skip_fstype_regex);
339 if (args.node_regex)
340 regfree (args.node_regex);
341 if (args.skip_node_regex)
342 regfree (args.skip_node_regex);
343 if (args.options_regex)
344 regfree (args.options_regex);
345 if (args.skip_options_regex)
346 regfree (args.skip_options_regex);
347
348 rc_strlist_reverse (nodes);
349
350 result = EXIT_FAILURE;
351 STRLIST_FOREACH (nodes, n, i) {
352 if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0)
353 continue;
354 if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0)
355 continue;
356 if (! rc_is_env ("RC_QUIET", "yes"))
357 printf ("%s\n", n);
358 result = EXIT_SUCCESS;
359 }
360 rc_strlist_free (nodes);
361
362 if (point_regex)
363 regfree (point_regex);
364 if (skip_point_regex)
365 regfree (skip_point_regex);
366
367 exit (result);
368 }

  ViewVC Help
Powered by ViewVC 1.1.20