]> git.ipfire.org Git - thirdparty/util-linux.git/blob - mount-deprecated/mount.c
e3e1bfe4660f200a51ef950c86b266845291fc2d
[thirdparty/util-linux.git] / mount-deprecated / mount.c
1 /*
2 * A mount(8) for Linux.
3 *
4 * Modifications by many people. Distributed under GPL.
5 */
6
7 #include <unistd.h>
8 #include <ctype.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <getopt.h>
12 #include <stdio.h>
13
14 #include <pwd.h>
15 #include <grp.h>
16
17 #include <sys/types.h>
18 #include <sys/ioctl.h>
19 #include <sys/stat.h>
20 #include <sys/wait.h>
21 #include <sys/mount.h>
22
23 #include <mntent.h>
24
25 #ifdef HAVE_LIBSELINUX
26 #include <selinux/selinux.h>
27 #include <selinux/context.h>
28 #endif
29
30 #include "pathnames.h"
31 #include "fsprobe.h"
32 #include "devname.h"
33 #include "mount_constants.h"
34 #include "sundries.h"
35 #include "mount_mntent.h"
36 #include "fstab.h"
37 #include "loopdev.h"
38 #include "linux_version.h"
39 #include "getusername.h"
40 #include "env.h"
41 #include "nls.h"
42 #include "blkdev.h"
43 #include "strutils.h"
44 #include "closestream.h"
45 #include "xgetpass.h"
46
47 #define DO_PS_FIDDLING
48
49 #ifdef DO_PS_FIDDLING
50 #include "setproctitle.h"
51 #endif
52
53 /* True for fake mount (-f). */
54 static int fake = 0;
55
56 /* True if we are allowed to call /sbin/mount.${FSTYPE} */
57 static int external_allowed = 1;
58
59 /* Don't write an entry in /etc/mtab (-n). */
60 static int nomtab = 0;
61
62 /* True for explicit readonly (-r). */
63 static int readonly = 0;
64
65 /* Nonzero for sloppy (-s). */
66 static int sloppy = 0;
67
68 /* True for explicit read/write (-w). */
69 static int readwrite = 0;
70
71 /* True for all mount (-a). */
72 static int mount_all = 0;
73
74 /* True for fork() during all mount (-F). */
75 static int optfork = 0;
76
77 /* Add volumelabel in a listing of mounted devices (-l). */
78 static int list_with_volumelabel = 0;
79
80 /* Nonzero for mount {bind|move|make-shared|make-private|
81 * make-unbindable|make-slave}
82 */
83 static int mounttype = 0;
84
85 /* True if (ruid != euid) or (0 != ruid), i.e. only "user" mounts permitted. */
86 static int restricted = 1;
87
88 /* Contains the fd to read the passphrase from, if any. */
89 static int pfd = -1;
90
91 /* mount(2) options */
92 struct mountargs {
93 const char *spec;
94 const char *node;
95 const char *type;
96 int flags;
97 void *data;
98 };
99
100 /* Map from -o and fstab option strings to the flag argument to mount(2). */
101 struct opt_map {
102 const char *opt; /* option name */
103 int skip; /* skip in mtab option string */
104 int inv; /* true if flag value should be inverted */
105 int mask; /* flag mask value */
106 int cmask; /* comments mask */
107 };
108
109 /* Custom mount options for our own purposes. */
110 /* Maybe these should now be freed for kernel use again */
111 #define MS_NOAUTO 0x80000000
112 #define MS_USERS 0x40000000
113 #define MS_USER 0x20000000
114 #define MS_OWNER 0x10000000
115 #define MS_GROUP 0x08000000
116 #define MS_COMMENT 0x02000000
117 #define MS_LOOP 0x00010000
118
119 #define MS_COMMENT_NOFAIL (1 << 1)
120 #define MS_COMMENT_NETDEV (1 << 2)
121
122 /* Options that we keep the mount system call from seeing. */
123 #define MS_NOSYS (MS_NOAUTO|MS_USERS|MS_USER|MS_COMMENT|MS_LOOP)
124
125 /* Options that we keep from appearing in the options field in the mtab. */
126 #define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER)
127
128 #define MS_PROPAGATION (MS_SHARED|MS_SLAVE|MS_UNBINDABLE|MS_PRIVATE)
129
130 /* Options that we make ordinary users have by default. */
131 #define MS_SECURE (MS_NOEXEC|MS_NOSUID|MS_NODEV)
132
133 /* Options that we make owner-mounted devices have by default */
134 #define MS_OWNERSECURE (MS_NOSUID|MS_NODEV)
135
136 static const struct opt_map opt_map[] = {
137 { "defaults", 0, 0, 0 }, /* default options */
138 { "ro", 1, 0, MS_RDONLY }, /* read-only */
139 { "rw", 1, 1, MS_RDONLY }, /* read-write */
140 { "exec", 0, 1, MS_NOEXEC }, /* permit execution of binaries */
141 { "noexec", 0, 0, MS_NOEXEC }, /* don't execute binaries */
142 { "suid", 0, 1, MS_NOSUID }, /* honor suid executables */
143 { "nosuid", 0, 0, MS_NOSUID }, /* don't honor suid executables */
144 { "dev", 0, 1, MS_NODEV }, /* interpret device files */
145 { "nodev", 0, 0, MS_NODEV }, /* don't interpret devices */
146 { "sync", 0, 0, MS_SYNCHRONOUS}, /* synchronous I/O */
147 { "async", 0, 1, MS_SYNCHRONOUS}, /* asynchronous I/O */
148 { "dirsync", 0, 0, MS_DIRSYNC}, /* synchronous directory modifications */
149 { "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */
150 { "bind", 0, 0, MS_BIND }, /* Remount part of tree elsewhere */
151 { "rbind", 0, 0, MS_BIND|MS_REC }, /* Idem, plus mounted subtrees */
152 { "auto", 0, 1, MS_NOAUTO }, /* Can be mounted using -a */
153 { "noauto", 0, 0, MS_NOAUTO }, /* Can only be mounted explicitly */
154 { "users", 0, 0, MS_USERS }, /* Allow ordinary user to mount */
155 { "nousers", 0, 1, MS_USERS }, /* Forbid ordinary user to mount */
156 { "user", 0, 0, MS_USER }, /* Allow ordinary user to mount */
157 { "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */
158 { "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */
159 { "noowner", 0, 1, MS_OWNER }, /* Device owner has no special privs */
160 { "group", 0, 0, MS_GROUP }, /* Let the group of the device mount */
161 { "nogroup", 0, 1, MS_GROUP }, /* Device group has no special privs */
162 { "_netdev", 0, 0, MS_COMMENT, MS_COMMENT_NETDEV }, /* Device requires network */
163 { "comment", 0, 0, MS_COMMENT}, /* fstab comment only (kudzu,_netdev)*/
164
165 /* add new options here */
166 #ifdef MS_NOSUB
167 { "sub", 0, 1, MS_NOSUB }, /* allow submounts */
168 { "nosub", 0, 0, MS_NOSUB }, /* don't allow submounts */
169 #endif
170 #ifdef MS_SILENT
171 { "silent", 0, 0, MS_SILENT }, /* be quiet */
172 { "loud", 0, 1, MS_SILENT }, /* print out messages. */
173 #endif
174 #ifdef MS_MANDLOCK
175 { "mand", 0, 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */
176 { "nomand", 0, 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */
177 #endif
178 { "loop", 1, 0, MS_LOOP }, /* use a loop device */
179 #ifdef MS_NOATIME
180 { "atime", 0, 1, MS_NOATIME }, /* Update access time */
181 { "noatime", 0, 0, MS_NOATIME }, /* Do not update access time */
182 #endif
183 #ifdef MS_I_VERSION
184 { "iversion", 0, 0, MS_I_VERSION }, /* Update inode I_version time */
185 { "noiversion", 0, 1, MS_I_VERSION }, /* Don't update inode I_version time */
186 #endif
187 #ifdef MS_NODIRATIME
188 { "diratime", 0, 1, MS_NODIRATIME }, /* Update dir access times */
189 { "nodiratime", 0, 0, MS_NODIRATIME },/* Do not update dir access times */
190 #endif
191 #ifdef MS_RELATIME
192 { "relatime", 0, 0, MS_RELATIME }, /* Update access times relative to
193 mtime/ctime */
194 { "norelatime", 0, 1, MS_RELATIME }, /* Update access time without regard
195 to mtime/ctime */
196 #endif
197 #ifdef MS_STRICTATIME
198 { "strictatime", 0, 0, MS_STRICTATIME }, /* Strict atime semantics */
199 { "nostrictatime", 0, 1, MS_STRICTATIME }, /* kernel default atime */
200 #endif
201 { "nofail", 0, 0, MS_COMMENT, MS_COMMENT_NOFAIL }, /* Do not fail if ENOENT on dev */
202 { NULL, 0, 0, 0 }
203 };
204
205 static int opt_nofail;
206 static int invuser_flags;
207 static int comment_flags;
208
209 static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_sizelimit,
210 *opt_encryption, *opt_speed, *opt_comment, *opt_uhelper, *opt_helper;
211
212 static int is_readonly(const char *node);
213 static int mounted (const char *spec0, const char *node0, struct mntentchn *fstab_mc);
214 static int check_special_mountprog(const char *spec, const char *node,
215 const char *type, int flags, char *extra_opts, int *status);
216
217 static struct string_opt_map {
218 char *tag;
219 int skip;
220 const char **valptr;
221 } string_opt_map[] = {
222 { "loop=", 0, &opt_loopdev },
223 { "vfs=", 1, &opt_vfstype },
224 { "offset=", 0, &opt_offset },
225 { "sizelimit=", 0, &opt_sizelimit },
226 { "encryption=", 0, &opt_encryption },
227 { "speed=", 0, &opt_speed },
228 { "comment=", 1, &opt_comment },
229 { "uhelper=", 0, &opt_uhelper },
230 { "helper=", 0, &opt_helper },
231 { NULL, 0, NULL }
232 };
233
234 static void
235 clear_string_opts(void) {
236 struct string_opt_map *m;
237
238 for (m = &string_opt_map[0]; m->tag; m++)
239 *(m->valptr) = NULL;
240 }
241
242 static void
243 clear_flags_opts(void) {
244 invuser_flags = 0;
245 comment_flags = 0;
246 opt_nofail = 0;
247 }
248
249 static int
250 parse_string_opt(char *s) {
251 struct string_opt_map *m;
252 int lth;
253
254 for (m = &string_opt_map[0]; m->tag; m++) {
255 lth = strlen(m->tag);
256 if (!strncmp(s, m->tag, lth)) {
257 *(m->valptr) = xstrdup(s + lth);
258 return 1;
259 }
260 }
261 return 0;
262 }
263
264 /* Report on a single mount. */
265 static void
266 print_one (const struct my_mntent *me) {
267
268 char *fsname = NULL;
269
270 if (mount_quiet)
271 return;
272
273 /* users assume backing file name rather than /dev/loopN in
274 * mount(8) output if the device has been initialized by mount(8).
275 */
276 if (strncmp(me->mnt_fsname, "/dev/loop", 9) == 0 &&
277 loopdev_is_autoclear(me->mnt_fsname))
278 fsname = loopdev_get_backing_file(me->mnt_fsname);
279
280 if (!fsname)
281 fsname = (char *) me->mnt_fsname;
282
283 printf ("%s on %s", fsname, me->mnt_dir);
284 if (me->mnt_type != NULL && *(me->mnt_type) != '\0')
285 printf (" type %s", me->mnt_type);
286 if (me->mnt_opts != NULL)
287 printf (" (%s)", me->mnt_opts);
288 if (list_with_volumelabel && is_pseudo_fs(me->mnt_type) == 0) {
289 const char *devname = spec_to_devname(me->mnt_fsname);
290
291 if (devname) {
292 const char *label;
293
294 label = fsprobe_get_label_by_devname(devname);
295 my_free(devname);
296
297 if (label) {
298 printf (" [%s]", label);
299 my_free(label);
300 }
301 }
302 }
303 printf ("\n");
304 }
305
306 /* Report on everything in mtab (of the specified types if any). */
307 static int
308 print_all (char *types) {
309 struct mntentchn *mc, *mc0;
310
311 mc0 = mtab_head();
312 for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
313 if (matching_type (mc->m.mnt_type, types))
314 print_one (&(mc->m));
315 }
316
317 if (!mtab_does_not_exist() && !mtab_is_a_symlink() && is_readonly(_PATH_MOUNTED))
318 printf(_("\n"
319 "mount: warning: /etc/mtab is not writable (e.g. read-only filesystem).\n"
320 " It's possible that information reported by mount(8) is not\n"
321 " up to date. For actual information about system mount points\n"
322 " check the /proc/mounts file.\n\n"));
323
324 exit (0);
325 }
326
327 /* reallocates its first arg */
328 static char *
329 append_opt(char *s, const char *opt, const char *val)
330 {
331 if (!opt)
332 return s;
333 if (!s) {
334 if (!val)
335 return xstrdup(opt); /* opt */
336
337 return xstrconcat3(NULL, opt, val); /* opt=val */
338 }
339 if (!val)
340 return xstrconcat3(s, ",", opt); /* s,opt */
341
342 return xstrconcat4(s, ",", opt, val); /* s,opt=val */
343 }
344
345 static char *
346 append_numopt(char *s, const char *opt, unsigned int num)
347 {
348 char buf[32];
349
350 snprintf(buf, sizeof(buf), "%u", num);
351 return append_opt(s, opt, buf);
352 }
353
354 #ifdef HAVE_LIBSELINUX
355 /* strip quotes from a "string"
356 * Warning: This function modify the "str" argument.
357 */
358 static char *
359 strip_quotes(char *str)
360 {
361 char *end = NULL;
362
363 if (*str != '"')
364 return str;
365
366 end = strrchr(str, '"');
367 if (end == NULL || end == str)
368 die (EX_USAGE, _("mount: improperly quoted option string '%s'"), str);
369
370 *end = '\0';
371 return str+1;
372 }
373
374 /* translates SELinux context from human to raw format and
375 * appends it to the mount extra options.
376 *
377 * returns -1 on error and 0 on success
378 */
379 static int
380 append_context(const char *optname, char *optdata, char **extra_opts)
381 {
382 security_context_t raw = NULL;
383 char *data = NULL;
384
385 if (is_selinux_enabled() != 1)
386 /* ignore the option if we running without selinux */
387 return 0;
388
389 if (optdata==NULL || *optdata=='\0' || optname==NULL)
390 return -1;
391
392 /* TODO: use strip_quotes() for all mount options? */
393 data = *optdata =='"' ? strip_quotes(optdata) : optdata;
394
395 if (selinux_trans_to_raw_context(
396 (security_context_t) data, &raw) == -1 ||
397 raw == NULL)
398 return -1;
399
400 if (verbose)
401 printf(_("mount: translated %s '%s' to '%s'\n"),
402 optname, data, (char *) raw);
403
404 *extra_opts = append_opt(*extra_opts, optname, NULL);
405 *extra_opts = xstrconcat4(*extra_opts, "\"", (char *) raw, "\"");
406
407 freecon(raw);
408 return 0;
409 }
410
411 /* returns newly allocated string without *context= options */
412 static char *remove_context_options(char *opts)
413 {
414 char *begin = NULL, *end = NULL, *p;
415 int open_quote = 0, changed = 0;
416
417 if (!opts)
418 return NULL;
419
420 opts = xstrdup(opts);
421
422 for (p = opts; p && *p; p++) {
423 if (!begin)
424 begin = p; /* begin of the option item */
425 if (*p == '"')
426 open_quote ^= 1; /* reverse the status */
427 if (open_quote)
428 continue; /* still in quoted block */
429 if (*p == ',')
430 end = p; /* terminate the option item */
431 else if (*(p + 1) == '\0')
432 end = p + 1; /* end of optstr */
433 if (!begin || !end)
434 continue;
435
436 if (strncmp(begin, "context=", 8) == 0 ||
437 strncmp(begin, "fscontext=", 10) == 0 ||
438 strncmp(begin, "defcontext=", 11) == 0 ||
439 strncmp(begin, "rootcontext=", 12) == 0 ||
440 strncmp(begin, "seclabel", 8) == 0) {
441 size_t sz;
442
443 if ((begin == opts || *(begin - 1) == ',') && *end == ',')
444 end++;
445 sz = strlen(end);
446
447 memmove(begin, end, sz + 1);
448 if (!*begin && *(begin - 1) == ',')
449 *(begin - 1) = '\0';
450
451 p = begin;
452 changed = 1;
453 }
454 begin = end = NULL;
455 }
456
457 if (changed && verbose)
458 printf (_("mount: SELinux *context= options are ignore on remount.\n"));
459
460 return opts;
461 }
462
463 static int has_context_option(char *opts)
464 {
465 if (get_option("context=", opts, NULL) ||
466 get_option("fscontext=", opts, NULL) ||
467 get_option("defcontext=", opts, NULL) ||
468 get_option("rootcontext=", opts, NULL))
469 return 1;
470
471 return 0;
472 }
473
474 #endif
475
476 /*
477 * Look for OPT in opt_map table and return mask value.
478 * If OPT isn't found, tack it onto extra_opts (which is non-NULL).
479 * For the options uid= and gid= replace user or group name by its value.
480 */
481 static inline void
482 parse_opt(char *opt, int *mask, int *inv_user, char **extra_opts) {
483 const struct opt_map *om;
484
485 for (om = opt_map; om->opt != NULL; om++)
486 if (streq (opt, om->opt)) {
487 if (om->inv)
488 *mask &= ~om->mask;
489 else
490 *mask |= om->mask;
491 if (om->inv && ((*mask & MS_USER) || (*mask & MS_USERS))
492 && (om->mask & MS_SECURE))
493 *inv_user |= om->mask;
494 if ((om->mask == MS_USER || om->mask == MS_USERS)
495 && !om->inv)
496 *mask |= MS_SECURE;
497 if ((om->mask == MS_OWNER || om->mask == MS_GROUP)
498 && !om->inv)
499 *mask |= MS_OWNERSECURE;
500 #ifdef MS_SILENT
501 if (om->mask == MS_SILENT && om->inv) {
502 mount_quiet = 1;
503 verbose = 0;
504 }
505 #endif
506 if (om->mask == MS_COMMENT) {
507 comment_flags |= om->cmask;
508 if (om->cmask == MS_COMMENT_NOFAIL)
509 opt_nofail = 1;
510 }
511 return;
512 }
513
514 /* convert nonnumeric ids to numeric */
515 if (!strncmp(opt, "uid=", 4) && !isdigit(opt[4])) {
516 struct passwd *pw = getpwnam(opt+4);
517
518 if (pw) {
519 *extra_opts = append_numopt(*extra_opts,
520 "uid=", pw->pw_uid);
521 return;
522 }
523 }
524 if (!strncmp(opt, "gid=", 4) && !isdigit(opt[4])) {
525 struct group *gr = getgrnam(opt+4);
526
527 if (gr) {
528 *extra_opts = append_numopt(*extra_opts,
529 "gid=", gr->gr_gid);
530 return;
531 }
532 }
533
534 #ifdef HAVE_LIBSELINUX
535 if (strncmp(opt, "context=", 8) == 0 && *(opt+8)) {
536 if (append_context("context=", opt+8, extra_opts) == 0)
537 return;
538 }
539 if (strncmp(opt, "fscontext=", 10) == 0 && *(opt+10)) {
540 if (append_context("fscontext=", opt+10, extra_opts) == 0)
541 return;
542 }
543 if (strncmp(opt, "defcontext=", 11) == 0 && *(opt+11)) {
544 if (append_context("defcontext=", opt+11, extra_opts) == 0)
545 return;
546 }
547 if (strncmp(opt, "rootcontext=", 12) == 0 && *(opt+12)) {
548 if (append_context("rootcontext=", opt+12, extra_opts) == 0)
549 return;
550 }
551 #endif
552 *extra_opts = append_opt(*extra_opts, opt, NULL);
553 }
554
555
556 /* Take -o options list and compute 4th and 5th args to mount(2). flags
557 gets the standard options (indicated by bits) and extra_opts all the rest */
558 static void
559 parse_opts (const char *options, int *flags, char **extra_opts) {
560 *flags = 0;
561 *extra_opts = NULL;
562
563 clear_string_opts();
564 clear_flags_opts();
565
566 if (options != NULL) {
567 char *opts = xstrdup(options);
568 int open_quote = 0;
569 char *opt, *p;
570
571 for (p=opts, opt=NULL; p && *p; p++) {
572 if (!opt)
573 opt = p; /* begin of the option item */
574 if (*p == '"')
575 open_quote ^= 1; /* reverse the status */
576 if (open_quote)
577 continue; /* still in quoted block */
578 if (*p == ',')
579 *p = '\0'; /* terminate the option item */
580 /* end of option item or last item */
581 if (*p == '\0' || *(p+1) == '\0') {
582 if (!parse_string_opt(opt))
583 parse_opt(opt, flags, &invuser_flags, extra_opts);
584 opt = NULL;
585 }
586 }
587 free(opts);
588 }
589
590 if (readonly)
591 *flags |= MS_RDONLY;
592 if (readwrite)
593 *flags &= ~MS_RDONLY;
594
595 *flags |= mounttype;
596
597 /* The propagation flags should not be used together with any
598 * other flags (except MS_REC and MS_SILENT) */
599 if (*flags & MS_PROPAGATION)
600 *flags &= (MS_PROPAGATION | MS_REC | MS_SILENT);
601 }
602
603 /* Try to build a canonical options string. */
604 static char *
605 fix_opts_string (int flags, const char *extra_opts,
606 const char *user, int inv_user)
607 {
608 const struct opt_map *om;
609 const struct string_opt_map *m;
610 char *new_opts;
611
612 new_opts = append_opt(NULL, (flags & MS_RDONLY) ? "ro" : "rw", NULL);
613 for (om = opt_map; om->opt != NULL; om++) {
614 if (om->skip)
615 continue;
616 if (om->inv || !om->mask || (flags & om->mask) != om->mask)
617 continue;
618 if (om->mask == MS_COMMENT && !(comment_flags & om->cmask))
619 continue;
620 new_opts = append_opt(new_opts, om->opt, NULL);
621 flags &= ~om->mask;
622 }
623 for (m = &string_opt_map[0]; m->tag; m++) {
624 if (!m->skip && *(m->valptr))
625 new_opts = append_opt(new_opts, m->tag, *(m->valptr));
626 }
627 if (extra_opts && *extra_opts)
628 new_opts = append_opt(new_opts, extra_opts, NULL);
629
630 if (user)
631 new_opts = append_opt(new_opts, "user=", user);
632
633 if (inv_user) {
634 for (om = opt_map; om->opt != NULL; om++) {
635 if (om->mask && om->inv
636 && (inv_user & om->mask) == om->mask) {
637 new_opts = append_opt(new_opts, om->opt, NULL);
638 inv_user &= ~om->mask;
639 }
640 }
641 }
642
643 return new_opts;
644 }
645
646 static int
647 already (const char *spec0, const char *node0) {
648 struct mntentchn *mc;
649 int ret = 1;
650 char *spec = canonicalize_spec(spec0);
651 char *node = canonicalize(node0);
652
653 if ((mc = getmntfile(node)) != NULL)
654 error (_("mount: according to mtab, "
655 "%s is already mounted on %s"),
656 mc->m.mnt_fsname, node);
657 else if (spec && strcmp (spec, "none") &&
658 (mc = getmntfile(spec)) != NULL)
659 error (_("mount: according to mtab, %s is mounted on %s"),
660 spec, mc->m.mnt_dir);
661 else
662 ret = 0;
663
664 free(spec);
665 free(node);
666
667 return ret;
668 }
669
670 /* Create mtab with a root entry. */
671 static void
672 create_mtab (void) {
673 struct mntentchn *fstab;
674 struct my_mntent mnt;
675 int flags;
676 mntFILE *mfp;
677
678 lock_mtab();
679
680 mfp = my_setmntent (_PATH_MOUNTED, "a+");
681 if (mfp == NULL || mfp->mntent_fp == NULL) {
682 int errsv = errno;
683 die (EX_FILEIO, _("mount: can't open %s for writing: %s"),
684 _PATH_MOUNTED, strerror (errsv));
685 }
686
687 /* Find the root entry by looking it up in fstab */
688 if ((fstab = getfs_by_dir ("/")) || (fstab = getfs_by_dir ("root"))) {
689 char *extra_opts;
690 parse_opts (fstab->m.mnt_opts, &flags, &extra_opts);
691 mnt.mnt_dir = "/";
692 mnt.mnt_fsname = spec_to_devname(fstab->m.mnt_fsname);
693 mnt.mnt_type = fstab->m.mnt_type;
694 mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL, 0);
695 mnt.mnt_freq = mnt.mnt_passno = 0;
696 free(extra_opts);
697
698 if (my_addmntent (mfp, &mnt) == 1) {
699 int errsv = errno;
700 die (EX_FILEIO, _("mount: error writing %s: %s"),
701 _PATH_MOUNTED, strerror (errsv));
702 }
703 }
704 if (fchmod (fileno (mfp->mntent_fp), 0644) < 0)
705 if (errno != EROFS) {
706 int errsv = errno;
707 die (EX_FILEIO,
708 _("mount: error changing mode of %s: %s"),
709 _PATH_MOUNTED, strerror (errsv));
710 }
711 my_endmntent (mfp);
712
713 unlock_mtab();
714
715 reset_mtab_info();
716 }
717
718 /* count successful mount system calls */
719 static int mountcount = 0;
720
721 /*
722 * do_mount_syscall()
723 * Mount a single file system. Keep track of successes.
724 * returns: 0: OK, -1: error in errno
725 */
726 static int
727 do_mount_syscall (struct mountargs *args) {
728 int flags = args->flags;
729
730 if ((flags & MS_MGC_MSK) == 0)
731 flags |= MS_MGC_VAL;
732
733 if (verbose > 2)
734 printf("mount: mount(2) syscall: source: \"%s\", target: \"%s\", "
735 "filesystemtype: \"%s\", mountflags: %d, data: %s\n",
736 args->spec, args->node, args->type, flags, (char *) args->data);
737
738 return mount (args->spec, args->node, args->type, flags, args->data);
739 }
740
741 /*
742 * do_mount()
743 * Mount a single file system, possibly invoking an external handler to
744 * do so. Keep track of successes.
745 * returns: 0: OK, -1: error in errno
746 */
747 static int
748 do_mount (struct mountargs *args, int *special, int *status) {
749 int ret;
750 if (check_special_mountprog(args->spec, args->node, args->type,
751 args->flags, args->data, status)) {
752 *special = 1;
753 ret = 0;
754 } else {
755 ret = do_mount_syscall(args);
756 }
757 if (ret == 0)
758 mountcount++;
759 return ret;
760 }
761
762 /*
763 * check_special_mountprog()
764 * If there is a special mount program for this type, exec it.
765 * returns: 0: no exec was done, 1: exec was done, status has result
766 */
767 static int
768 check_special_mountprog(const char *spec, const char *node, const char *type, int flags,
769 char *extra_opts, int *status) {
770 char search_path[] = FS_SEARCH_PATH;
771 char *path, mountprog[150];
772 struct stat statbuf;
773 int res;
774
775 if (!external_allowed)
776 return 0;
777
778 if (type == NULL || strcmp(type, "none") == 0)
779 return 0;
780
781 path = strtok(search_path, ":");
782 while (path) {
783 int type_opt = 0;
784
785 res = snprintf(mountprog, sizeof(mountprog), "%s/mount.%s",
786 path, type);
787 path = strtok(NULL, ":");
788 if (res < 0 || (size_t) res >= sizeof(mountprog))
789 continue;
790
791 res = stat(mountprog, &statbuf);
792 if (res == -1 && errno == ENOENT && strchr(type, '.')) {
793 /* If type ends with ".subtype" try without it */
794 *strrchr(mountprog, '.') = '\0';
795 type_opt = 1;
796 res = stat(mountprog, &statbuf);
797 }
798 if (res)
799 continue;
800
801 if (verbose)
802 fflush(stdout);
803
804 switch (fork()) {
805 case 0: { /* child */
806 char *oo, *mountargs[12];
807 int i = 0;
808
809 if (setgid(getgid()) < 0)
810 die(EX_FAIL, _("mount: cannot set group id: %m"));
811
812 if (setuid(getuid()) < 0)
813 die(EX_FAIL, _("mount: cannot set user id: %m"));
814
815 oo = fix_opts_string(flags, extra_opts, NULL, invuser_flags);
816 mountargs[i++] = mountprog; /* 1 */
817 mountargs[i++] = (char *) spec; /* 2 */
818 mountargs[i++] = (char *) node; /* 3 */
819 if (sloppy && strncmp(type, "nfs", 3) == 0)
820 mountargs[i++] = "-s"; /* 4 */
821 if (fake)
822 mountargs[i++] = "-f"; /* 5 */
823 if (nomtab)
824 mountargs[i++] = "-n"; /* 6 */
825 if (verbose)
826 mountargs[i++] = "-v"; /* 7 */
827 if (oo && *oo) {
828 mountargs[i++] = "-o"; /* 8 */
829 mountargs[i++] = oo; /* 9 */
830 }
831 if (type_opt) {
832 mountargs[i++] = "-t"; /* 10 */
833 mountargs[i++] = (char *) type; /* 11 */
834 }
835 mountargs[i] = NULL; /* 12 */
836
837 if (verbose > 2) {
838 i = 0;
839 while (mountargs[i]) {
840 printf("mount: external mount: argv[%d] = \"%s\"\n",
841 i, mountargs[i]);
842 i++;
843 }
844 fflush(stdout);
845 }
846
847 execv(mountprog, mountargs);
848 exit(1); /* exec failed */
849 }
850
851 default: { /* parent */
852 int st;
853 wait(&st);
854 *status = (WIFEXITED(st) ? WEXITSTATUS(st) : EX_SYSERR);
855 return 1;
856 }
857
858 case -1: { /* error */
859 int errsv = errno;
860 error(_("mount: cannot fork: %s"), strerror(errsv));
861 }
862 }
863 }
864
865 return 0;
866 }
867
868
869 /* list of already tested filesystems by procfsloop_mount() */
870 static struct tried {
871 struct tried *next;
872 char *type;
873 } *tried = NULL;
874
875 static int
876 was_tested(const char *fstype) {
877 struct tried *t;
878
879 for (t = tried; t; t = t->next) {
880 if (!strcmp(t->type, fstype))
881 return 1;
882 }
883 return 0;
884 }
885
886 static void
887 set_tested(const char *fstype) {
888 struct tried *t = xmalloc(sizeof(struct tried));
889
890 t->next = tried;
891 t->type = xstrdup(fstype);
892 tried = t;
893 }
894
895 static void
896 free_tested(void) {
897 struct tried *t, *tt;
898
899 t = tried;
900 while(t) {
901 free(t->type);
902 tt = t->next;
903 free(t);
904 t = tt;
905 }
906 tried = NULL;
907 }
908
909 static char *
910 procfsnext(FILE *procfs) {
911 char line[100];
912 char fsname[100];
913
914 while (fgets(line, sizeof(line), procfs)) {
915 if (sscanf (line, "nodev %[^#\n]\n", fsname) == 1) continue;
916 if (sscanf (line, " %[^# \n]\n", fsname) != 1) continue;
917 return xstrdup(fsname);
918 }
919 return 0;
920 }
921
922 /* Only use /proc/filesystems here, this is meant to test what
923 the kernel knows about, so /etc/filesystems is irrelevant.
924 Return: 1: yes, 0: no, -1: cannot open procfs */
925 static int
926 known_fstype_in_procfs(const char *type)
927 {
928 FILE *procfs;
929 char *fsname;
930 int ret = -1;
931
932 procfs = fopen(_PATH_PROC_FILESYSTEMS, "r");
933 if (procfs) {
934 ret = 0;
935 while ((fsname = procfsnext(procfs)) != NULL)
936 if (!strcmp(fsname, type)) {
937 ret = 1;
938 break;
939 }
940 fclose(procfs);
941 procfs = NULL;
942 }
943 return ret;
944 }
945
946 /* Try all types in FILESYSTEMS, except those in *types,
947 in case *types starts with "no" */
948 /* return: 0: OK, -1: error in errno, 1: type not found */
949 /* when 0 or -1 is returned, *types contains the type used */
950 /* when 1 is returned, *types is NULL */
951 static int
952 procfsloop_mount(int (*mount_fn)(struct mountargs *, int *, int *),
953 struct mountargs *args,
954 const char **types,
955 int *special, int *status)
956 {
957 char *files[2] = { _PATH_FILESYSTEMS, _PATH_PROC_FILESYSTEMS };
958 FILE *procfs;
959 char *fsname;
960 const char *notypes = NULL;
961 int no = 0;
962 int ret = 1;
963 int errsv = 0;
964 int i;
965
966 if (*types && !strncmp(*types, "no", 2)) {
967 no = 1;
968 notypes = (*types) + 2;
969 }
970 *types = NULL;
971
972 /* Use _PATH_PROC_FILESYSTEMS only when _PATH_FILESYSTEMS
973 * (/etc/filesystems) does not exist. In some cases trying a
974 * filesystem that the kernel knows about on the wrong data will crash
975 * the kernel; in such cases _PATH_FILESYSTEMS can be used to list the
976 * filesystems that we are allowed to try, and in the order they should
977 * be tried. End _PATH_FILESYSTEMS with a line containing a single '*'
978 * only, if _PATH_PROC_FILESYSTEMS should be tried afterwards.
979 */
980 for (i=0; i<2; i++) {
981 procfs = fopen(files[i], "r");
982 if (!procfs)
983 continue;
984 while ((fsname = procfsnext(procfs)) != NULL) {
985 if (!strcmp(fsname, "*")) {
986 fclose(procfs);
987 goto nexti;
988 }
989 if (was_tested (fsname))
990 continue;
991 if (no && matching_type(fsname, notypes))
992 continue;
993 set_tested (fsname);
994 args->type = fsname;
995 if (verbose)
996 printf(_("Trying %s\n"), fsname);
997 if ((*mount_fn) (args, special, status) == 0) {
998 *types = fsname;
999 ret = 0;
1000 break;
1001 } else if (errno != EINVAL &&
1002 known_fstype_in_procfs(fsname) == 1) {
1003 *types = "guess";
1004 ret = -1;
1005 errsv = errno;
1006 break;
1007 }
1008 }
1009 free_tested();
1010 fclose(procfs);
1011 errno = errsv;
1012 return ret;
1013 nexti:;
1014 }
1015 return 1;
1016 }
1017
1018 static const char *
1019 guess_fstype_by_devname(const char *devname, int *ambivalent)
1020 {
1021 const char *type = fsprobe_get_fstype_by_devname_ambi(devname, ambivalent);
1022
1023 if (verbose) {
1024 printf (_("mount: you didn't specify a filesystem type for %s\n"), devname);
1025
1026 if (!type)
1027 printf (_(" I will try all types mentioned in %s or %s\n"),
1028 _PATH_FILESYSTEMS, _PATH_PROC_FILESYSTEMS);
1029 else if (!strcmp(type, MNTTYPE_SWAP))
1030 printf (_(" and it looks like this is swapspace\n"));
1031 else
1032 printf (_(" I will try type %s\n"), type);
1033 }
1034 return type;
1035 }
1036
1037 /*
1038 * guess_fstype_and_mount()
1039 * Mount a single file system. Guess the type when unknown.
1040 * returns: 0: OK, -1: error in errno, 1: other error
1041 * don't exit on non-fatal errors.
1042 * on return types is filled with the type used.
1043 */
1044 static int
1045 guess_fstype_and_mount(const char *spec, const char *node, const char **types,
1046 int flags, char *mount_opts, int *special, int *status) {
1047 struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts };
1048 int ambivalent = 0;
1049
1050 if (*types && strcasecmp (*types, "auto") == 0)
1051 *types = NULL;
1052
1053 if (!*types && !(flags & MS_REMOUNT)) {
1054 *types = guess_fstype_by_devname(spec, &ambivalent);
1055 if (*types) {
1056 if (!strcmp(*types, MNTTYPE_SWAP)) {
1057 error(_("%s looks like swapspace - not mounted"), spec);
1058 *types = NULL;
1059 return 1;
1060 } else {
1061 args.type = *types;
1062 return do_mount (&args, special, status);
1063 }
1064 } else if (ambivalent) {
1065 error(_("mount: %s: more filesystems detected. This should not happen,\n"
1066 " use -t <type> to explicitly specify the filesystem type or\n"
1067 " use wipefs(8) to clean up the device.\n"), spec);
1068 return 1;
1069 }
1070 }
1071
1072 /* Accept a comma-separated list of types, and try them one by one */
1073 /* A list like "nonfs,.." indicates types not to use */
1074 if (*types && strncmp(*types, "no", 2) && strchr(*types,',')) {
1075 char *t = strdup(*types);
1076 char *p;
1077
1078 while((p = strchr(t,',')) != NULL) {
1079 *p = 0;
1080 args.type = *types = t;
1081 if (do_mount (&args, special, status) == 0)
1082 return 0;
1083 t = p+1;
1084 }
1085 /* do last type below */
1086 *types = t;
1087 }
1088
1089 if (*types || (flags & MS_REMOUNT)) {
1090 args.type = *types;
1091 return do_mount (&args, special, status);
1092 }
1093
1094 return procfsloop_mount(do_mount, &args, types, special, status);
1095 }
1096
1097 /*
1098 * restricted_check()
1099 * Die if the user is not allowed to do this.
1100 */
1101 static void
1102 restricted_check(const char *spec, const char *node, int *flags, char **user) {
1103 if (restricted) {
1104 /*
1105 * MS_OWNER: Allow owners to mount when fstab contains
1106 * the owner option. Note that this should never be used
1107 * in a high security environment, but may be useful to give
1108 * people at the console the possibility of mounting a floppy.
1109 * MS_GROUP: Allow members of device group to mount. (Martin Dickopp)
1110 */
1111 if (*flags & (MS_OWNER | MS_GROUP)) {
1112 struct stat sb;
1113
1114 if (!strncmp(spec, "/dev/", 5) && stat(spec, &sb) == 0) {
1115
1116 if (*flags & MS_OWNER) {
1117 if (getuid() == sb.st_uid)
1118 *flags |= MS_USER;
1119 }
1120
1121 if (*flags & MS_GROUP) {
1122 if (getgid() == sb.st_gid)
1123 *flags |= MS_USER;
1124 else {
1125 int n = getgroups(0, NULL);
1126
1127 if (n > 0) {
1128 gid_t *groups = xmalloc(n * sizeof(*groups));
1129 if (getgroups(n, groups) == n) {
1130 int i;
1131 for (i = 0; i < n; i++) {
1132 if (groups[i] == sb.st_gid) {
1133 *flags |= MS_USER;
1134 break;
1135 }
1136 }
1137 }
1138 free(groups);
1139 }
1140 }
1141 }
1142 }
1143 }
1144
1145 /* James Kehl <mkehl@gil.com.au> came with a similar patch:
1146 allow an arbitrary user to mount when he is the owner of
1147 the mount-point and has write-access to the device.
1148 This is even less secure. Let me skip it for the time being;
1149 there should be an explicit fstab line allowing such things. */
1150
1151 if (!(*flags & (MS_USER | MS_USERS))) {
1152 if (already (spec, node))
1153 die (EX_USAGE, _("mount failed"));
1154 else
1155 die (EX_USAGE, _("mount: only root can mount %s on %s"), spec, node);
1156 }
1157 if (*flags & MS_USER)
1158 *user = getusername();
1159 }
1160
1161 *flags &= ~(MS_OWNER | MS_GROUP);
1162 }
1163
1164 /* Check, if there already exists a mounted loop device on the mountpoint node
1165 * with the same parameters.
1166 */
1167 static int
1168 is_mounted_same_loopfile(const char *node0, const char *loopfile, unsigned long long offset)
1169 {
1170 struct mntentchn *mnt = NULL;
1171 char *node;
1172 int res = 0;
1173
1174 node = canonicalize(node0);
1175
1176 /* Search for mountpoint node in mtab,
1177 * procceed if any of these has the loop option set or
1178 * the device is a loop device
1179 */
1180 mnt = getmntdirbackward(node, mnt);
1181 if (!mnt) {
1182 free(node);
1183 return 0;
1184 }
1185 for(; mnt && res == 0; mnt = getmntdirbackward(node, mnt)) {
1186 char *p;
1187
1188 if (strncmp(mnt->m.mnt_fsname, "/dev/loop", 9) == 0)
1189 res = loopdev_is_used((char *) mnt->m.mnt_fsname,
1190 loopfile, offset, LOOPDEV_FL_OFFSET);
1191
1192 else if (mnt->m.mnt_opts &&
1193 (p = strstr(mnt->m.mnt_opts, "loop=")))
1194 {
1195 char *dev = xstrdup(p+5);
1196 if ((p = strchr(dev, ',')))
1197 *p = '\0';
1198 res = loopdev_is_used(dev,
1199 loopfile, offset, LOOPDEV_FL_OFFSET);
1200 free(dev);
1201 }
1202 }
1203
1204 free(node);
1205 return res;
1206 }
1207
1208 static int
1209 parse_offset(const char **opt, uintmax_t *val)
1210 {
1211 char *tmp;
1212
1213 if (strtosize(*opt, val))
1214 return -1;
1215
1216 tmp = xmalloc(32);
1217 snprintf(tmp, 32, "%jd", *val);
1218 my_free(*opt);
1219 *opt = tmp;
1220 return 0;
1221 }
1222
1223 static int
1224 loop_check(const char **spec, const char **type, int *flags,
1225 int *loop, const char **loopdev, const char **loopfile,
1226 const char *node) {
1227 int looptype;
1228 uintmax_t offset = 0, sizelimit = 0;
1229 struct loopdev_cxt lc;
1230 char *pwd = NULL;
1231 int ret = EX_FAIL;
1232
1233 /*
1234 * In the case of a loop mount, either type is of the form lo@/dev/loop5
1235 * or the option "-o loop=/dev/loop5" or just "-o loop" is given, or
1236 * mount just has to figure things out for itself from the fact that
1237 * spec is not a block device. We do not test for a block device
1238 * immediately: maybe later other types of mountable objects will occur.
1239 */
1240
1241 *loopdev = opt_loopdev;
1242
1243 looptype = (*type && strncmp("lo@", *type, 3) == 0);
1244 if (looptype) {
1245 if (*loopdev)
1246 error(_("mount: loop device specified twice"));
1247 *loopdev = *type + 3;
1248 *type = opt_vfstype;
1249 } else if (opt_vfstype) {
1250 if (*type)
1251 error(_("mount: type specified twice"));
1252 else
1253 *type = opt_vfstype;
1254 }
1255
1256 *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_sizelimit || opt_encryption);
1257 *loopfile = *spec;
1258
1259 /* Automatically create a loop device from a regular file if a filesystem
1260 * is not specified or the filesystem is known for libblkid (these
1261 * filesystems work with block devices only).
1262 *
1263 * Note that there is not a restriction (on kernel side) that prevents regular
1264 * file as a mount(2) source argument. A filesystem that is able to mount
1265 * regular files could be implemented.
1266 */
1267 if (!*loop && !(*flags & (MS_BIND | MS_MOVE | MS_PROPAGATION)) &&
1268 (!*type || strcmp(*type, "auto") == 0 || fsprobe_known_fstype(*type))) {
1269
1270 struct stat st;
1271 if (stat(*loopfile, &st) == 0)
1272 *loop = S_ISREG(st.st_mode);
1273 }
1274
1275 if (*loop) {
1276 *flags |= MS_LOOP;
1277 if (fake) {
1278 if (verbose)
1279 printf(_("mount: skipping the setup of a loop device\n"));
1280 } else {
1281 int loop_opts = 0;
1282
1283 /* since 2.6.37 we don't have to store backing filename to mtab
1284 * because kernel provides the name in /sys
1285 */
1286 if (get_linux_version() >= KERNEL_VERSION(2, 6, 37) ||
1287 mtab_is_writable() == 0) {
1288
1289 if (verbose)
1290 printf(_("mount: enabling autoclear loopdev flag\n"));
1291 loop_opts = LO_FLAGS_AUTOCLEAR;
1292 }
1293
1294 if (*flags & MS_RDONLY)
1295 loop_opts |= LO_FLAGS_READ_ONLY;
1296
1297 if (opt_offset && parse_offset(&opt_offset, &offset)) {
1298 error(_("mount: invalid offset '%s' specified"), opt_offset);
1299 return EX_FAIL;
1300 }
1301 if (opt_sizelimit && parse_offset(&opt_sizelimit, &sizelimit)) {
1302 error(_("mount: invalid sizelimit '%s' specified"), opt_sizelimit);
1303 return EX_FAIL;
1304 }
1305
1306 if (is_mounted_same_loopfile(node, *loopfile, offset)) {
1307 error(_("mount: according to mtab %s is already mounted on %s as loop"), *loopfile, node);
1308 return EX_FAIL;
1309 }
1310
1311 if (opt_encryption) {
1312 #ifdef MCL_FUTURE
1313 if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
1314 error(_("mount: couldn't lock into memory"));
1315 return EX_FAIL;
1316 }
1317 #endif
1318 pwd = xgetpass(pfd, _("Password: "));
1319 }
1320
1321 loopcxt_init(&lc, 0);
1322 /*loopcxt_enable_debug(&lc, 1);*/
1323
1324 if (*loopdev && **loopdev)
1325 loopcxt_set_device(&lc, *loopdev); /* use loop=<devname> */
1326
1327 do {
1328 int rc;
1329
1330 if ((!*loopdev || !**loopdev) && loopcxt_find_unused(&lc) == 0)
1331 *loopdev = loopcxt_strdup_device(&lc);
1332
1333 if (!*loopdev) {
1334 error(_("mount: failed to found free loop device"));
1335 loopcxt_deinit(&lc);
1336 goto err; /* no more loop devices */
1337 }
1338 if (verbose)
1339 printf(_("mount: going to use the loop device %s\n"), *loopdev);
1340
1341 rc = loopcxt_set_backing_file(&lc, *loopfile);
1342
1343 if (!rc && offset)
1344 rc = loopcxt_set_offset(&lc, offset);
1345 if (!rc && sizelimit)
1346 rc = loopcxt_set_sizelimit(&lc, sizelimit);
1347 if (!rc && opt_encryption && pwd)
1348 loopcxt_set_encryption(&lc, opt_encryption, pwd);
1349 if (!rc)
1350 loopcxt_set_flags(&lc, loop_opts);
1351
1352 if (rc) {
1353 error(_("mount: %s: failed to set loopdev attributes"), *loopdev);
1354 loopcxt_deinit(&lc);
1355 goto err;
1356 }
1357
1358 /* setup the device */
1359 rc = loopcxt_setup_device(&lc);
1360 if (!rc)
1361 break; /* success */
1362
1363 if (rc != -EBUSY) {
1364 error(_("mount: %s: failed setting up loop device: %m"), *loopfile);
1365 if (!opt_loopdev) {
1366 my_free(*loopdev);
1367 *loopdev = NULL;
1368 }
1369 loopcxt_deinit(&lc);
1370 goto err;
1371 }
1372
1373 if (!opt_loopdev) {
1374 if (verbose)
1375 printf(_("mount: stolen loop=%s ...trying again\n"), *loopdev);
1376 my_free(*loopdev);
1377 *loopdev = NULL;
1378 continue;
1379 }
1380 error(_("mount: stolen loop=%s"), *loopdev);
1381 loopcxt_deinit(&lc);
1382 goto err;
1383
1384 } while (!*loopdev);
1385
1386 if (verbose > 1)
1387 printf(_("mount: setup loop device successfully\n"));
1388 *spec = *loopdev;
1389
1390 if (loopcxt_is_readonly(&lc))
1391 *flags |= MS_RDONLY;
1392
1393 if (loopcxt_is_autoclear(&lc))
1394 /* Prevent recording loop dev in mtab for cleanup on umount */
1395 *loop = 0;
1396
1397 /* We have to keep the device open until mount(2), otherwise it will
1398 * be auto-cleared by kernel (because LO_FLAGS_AUTOCLEAR) */
1399 loopcxt_set_fd(&lc, -1, 0);
1400 loopcxt_deinit(&lc);
1401 }
1402 }
1403
1404 ret = 0;
1405 err:
1406 if (pwd) {
1407 char *p = pwd;
1408 while (*p)
1409 *p++ = '\0';
1410 free(pwd);
1411 }
1412 return ret;
1413 }
1414
1415
1416 static void
1417 update_mtab_entry(const char *spec, const char *node, const char *type,
1418 const char *opts, int flags, int freq, int pass) {
1419 struct my_mntent mnt;
1420
1421 mnt.mnt_fsname = is_pseudo_fs(type) ? xstrdup(spec) : canonicalize(spec);
1422 mnt.mnt_dir = canonicalize (node);
1423 mnt.mnt_type = type;
1424 mnt.mnt_opts = opts;
1425 mnt.mnt_freq = freq;
1426 mnt.mnt_passno = pass;
1427
1428 /* We get chatty now rather than after the update to mtab since the
1429 mount succeeded, even if the write to /etc/mtab should fail. */
1430 if (verbose)
1431 print_one (&mnt);
1432
1433 if (!nomtab && mtab_does_not_exist()) {
1434 if (verbose > 1)
1435 printf(_("mount: no %s found - creating it..\n"),
1436 _PATH_MOUNTED);
1437 create_mtab ();
1438
1439 }
1440
1441 if (!nomtab && mtab_is_writable()) {
1442 if (flags & MS_REMOUNT)
1443 update_mtab (mnt.mnt_dir, &mnt);
1444 else if (flags & MS_MOVE)
1445 update_mtab(mnt.mnt_fsname, &mnt);
1446 else
1447 update_mtab(NULL, &mnt);
1448 }
1449 my_free(mnt.mnt_fsname);
1450 my_free(mnt.mnt_dir);
1451 }
1452
1453 static void
1454 set_pfd(char *s) {
1455 if (!isdigit(*s))
1456 die(EX_USAGE,
1457 _("mount: argument to -p or --pass-fd must be a number"));
1458 pfd = atoi(optarg);
1459 }
1460
1461 static void
1462 cdrom_setspeed(const char *spec) {
1463 #define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */
1464 if (opt_speed) {
1465 int cdrom;
1466 int speed = atoi(opt_speed);
1467
1468 if ((cdrom = open(spec, O_RDONLY | O_NONBLOCK)) < 0)
1469 die(EX_FAIL,
1470 _("mount: cannot open %s for setting speed"),
1471 spec);
1472 if (ioctl(cdrom, CDROM_SELECT_SPEED, speed) < 0)
1473 die(EX_FAIL, _("mount: cannot set speed: %m"));
1474 close(cdrom);
1475 }
1476 }
1477
1478 /*
1479 * Check if @path is on read-only filesystem independently on file permissions.
1480 */
1481 static int
1482 is_readonly(const char *path)
1483 {
1484 if (access(path, W_OK) == 0)
1485 return 0;
1486 if (errno == EROFS)
1487 return 1;
1488 if (errno != EACCES)
1489 return 0;
1490
1491 #ifdef HAVE_FUTIMENS
1492 /*
1493 * access(2) returns EACCES on read-only FS:
1494 *
1495 * - for set-uid application if one component of the path is not
1496 * accessible for the current rUID. (Note that euidaccess(2) does not
1497 * check for EROFS at all).
1498 *
1499 * - for read-write filesystem with read-only VFS node (aka -o remount,ro,bind)
1500 */
1501 {
1502 struct timespec times[2];
1503
1504 times[0].tv_nsec = UTIME_NOW; /* atime */
1505 times[1].tv_nsec = UTIME_OMIT; /* mtime */
1506
1507 if (utimensat(AT_FDCWD, path, times, 0) == -1)
1508 return errno == EROFS;
1509 }
1510 #endif
1511 return 0;
1512 }
1513
1514 /*
1515 * try_mount_one()
1516 * Try to mount one file system.
1517 *
1518 * returns: 0: OK, EX_SYSERR, EX_FAIL, return code from nfsmount,
1519 * return status from wait
1520 */
1521 static int
1522 try_mount_one (const char *spec0, const char *node0, const char *types0,
1523 const char *opts0, int freq, int pass, int ro) {
1524 int res = 0, status = 0, special = 0;
1525 int mnt5_res = 0; /* only for gcc */
1526 int mnt_err;
1527 int flags;
1528 char *extra_opts; /* written in mtab */
1529 char *mount_opts; /* actually used on system call */
1530 const char *opts, *spec, *node, *types;
1531 char *user = 0;
1532 int loop = 0;
1533 const char *loopdev = 0, *loopfile = 0;
1534 struct stat statbuf;
1535
1536 /* copies for freeing on exit */
1537 const char *opts1, *spec1, *node1, *types1;
1538
1539 if (verbose > 2) {
1540 printf("mount: spec: \"%s\"\n", spec0);
1541 printf("mount: node: \"%s\"\n", node0);
1542 printf("mount: types: \"%s\"\n", types0);
1543 printf("mount: opts: \"%s\"\n", opts0);
1544 }
1545
1546 spec = spec1 = xstrdup(spec0);
1547 node = node1 = xstrdup(node0);
1548 types = types1 = xstrdup(types0);
1549 opts = opts1 = xstrdup(opts0);
1550
1551 parse_opts (opts, &flags, &extra_opts);
1552 mount_opts = xstrdup(extra_opts);
1553
1554 /* quietly succeed for fstab entries that don't get mounted automatically */
1555 if (mount_all && (flags & MS_NOAUTO))
1556 goto out;
1557
1558 restricted_check(spec, node, &flags, &user);
1559
1560 /* The "mount -f" checks for for existing record in /etc/mtab (with
1561 * regular non-fake mount this is usually done by kernel)
1562 */
1563 if (!(flags & MS_REMOUNT) && fake && mounted (spec, node, NULL))
1564 die(EX_USAGE, _("mount: according to mtab, "
1565 "%s is already mounted on %s\n"),
1566 spec, node);
1567
1568 if (opt_speed)
1569 cdrom_setspeed(spec);
1570
1571 if (!(flags & MS_REMOUNT)) {
1572 /*
1573 * Don't set up a (new) loop device if we only remount - this left
1574 * stale assignments of files to loop devices. Nasty when used for
1575 * encryption.
1576 */
1577 res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile, node);
1578 if (res)
1579 goto out;
1580 }
1581
1582 if (loop)
1583 opt_loopdev = loopdev;
1584
1585 if (flags & (MS_BIND | MS_MOVE | MS_PROPAGATION))
1586 types = "none";
1587
1588 #ifdef HAVE_LIBSELINUX
1589 if (flags & MS_REMOUNT) {
1590 /*
1591 * Linux kernel does not accept any selinux context option on remount
1592 */
1593 if (mount_opts) {
1594 char *tmp = mount_opts;
1595 mount_opts = remove_context_options(mount_opts);
1596 my_free(tmp);
1597 }
1598
1599 } else if (types && strcmp(types, "tmpfs") == 0 && is_selinux_enabled() > 0 &&
1600 !has_context_option(mount_opts)) {
1601 /*
1602 * Add rootcontext= mount option for tmpfs
1603 * https://bugzilla.redhat.com/show_bug.cgi?id=476964
1604 */
1605 security_context_t sc = NULL;
1606
1607 if (getfilecon(node, &sc) > 0 && strcmp("unlabeled", sc))
1608 append_context("rootcontext=", (char *) sc, &mount_opts);
1609 freecon(sc);
1610 }
1611 #endif
1612
1613 /*
1614 * Call mount.TYPE for types that require a separate mount program.
1615 * For the moment these types are ncpfs and smbfs. Maybe also vxfs.
1616 * All such special things must occur isolated in the types string.
1617 */
1618 if (check_special_mountprog(spec, node, types, flags, mount_opts, &status)) {
1619 res = status;
1620 goto out;
1621 }
1622
1623 block_signals (SIG_BLOCK);
1624
1625 if (!fake) {
1626 mnt5_res = guess_fstype_and_mount (spec, node, &types, flags & ~MS_NOSYS,
1627 mount_opts, &special, &status);
1628
1629 if (special) {
1630 block_signals (SIG_UNBLOCK);
1631 res = status;
1632 goto out;
1633 }
1634 }
1635
1636 /* Kernel allows to use MS_RDONLY for bind mounts, but the read-only request
1637 * could be silently ignored. Check it to avoid 'ro' in mtab and 'rw' in
1638 * /proc/mounts.
1639 */
1640 if (!fake && mnt5_res == 0 &&
1641 (flags & MS_BIND) && (flags & MS_RDONLY) && !is_readonly(node)) {
1642
1643 printf(_("mount: warning: %s seems to be mounted read-write.\n"), node);
1644 flags &= ~MS_RDONLY;
1645 }
1646
1647 /* Kernel can silently add MS_RDONLY flag when mounting file system that
1648 * does not have write support. Check this to avoid 'ro' in /proc/mounts
1649 * and 'rw' in mtab.
1650 */
1651 if (!fake && mnt5_res == 0 &&
1652 !(flags & (MS_RDONLY | MS_PROPAGATION | MS_MOVE)) &&
1653 is_readonly(node)) {
1654
1655 printf(_("mount: warning: %s seems to be mounted read-only.\n"), node);
1656 flags |= MS_RDONLY;
1657 }
1658
1659 if (fake || mnt5_res == 0) {
1660 char *mo = fix_opts_string (flags & ~MS_NOMTAB, extra_opts, user, 0);
1661 const char *tp = types ? types : "unknown";
1662
1663 /* Mount succeeded, report this (if verbose) and write mtab entry. */
1664 if (!(mounttype & MS_PROPAGATION))
1665 update_mtab_entry(loop ? loopfile : spec,
1666 node,
1667 tp,
1668 mo,
1669 flags,
1670 freq,
1671 pass);
1672
1673 block_signals (SIG_UNBLOCK);
1674 free(mo);
1675
1676 res = 0;
1677 goto out;
1678 }
1679
1680 mnt_err = errno;
1681
1682 if (loop)
1683 loopdev_delete(spec);
1684
1685 block_signals (SIG_UNBLOCK);
1686
1687 /* Mount failed, complain, but don't die. */
1688
1689 if (types == 0) {
1690 if (restricted)
1691 error (_("mount: I could not determine the filesystem type, "
1692 "and none was specified"));
1693 else
1694 error (_("mount: you must specify the filesystem type"));
1695 } else if (mnt5_res != -1) {
1696 /* should not happen */
1697 error (_("mount: mount failed"));
1698 } else {
1699 switch (mnt_err) {
1700 case EPERM:
1701 if (geteuid() == 0) {
1702 if (stat (node, &statbuf) || !S_ISDIR(statbuf.st_mode))
1703 error (_("mount: mount point %s is not a directory"), node);
1704 else
1705 error (_("mount: permission denied"));
1706 } else
1707 error (_("mount: must be superuser to use mount"));
1708 break;
1709 case EBUSY:
1710 if (flags & MS_REMOUNT) {
1711 error (_("mount: %s is busy"), node);
1712 } else if (!strcmp(types, "proc") && !strcmp(node, "/proc")) {
1713 /* heuristic: if /proc/version exists, then probably proc is mounted */
1714 if (stat ("/proc/version", &statbuf)) /* proc mounted? */
1715 error (_("mount: %s is busy"), node); /* no */
1716 else if (!mount_all || verbose) /* yes, don't mention it */
1717 error (_("mount: proc already mounted"));
1718 } else {
1719 error (_("mount: %s already mounted or %s busy"), spec, node);
1720 already (spec, node);
1721 }
1722 break;
1723 case ENOENT:
1724 if (lstat (node, &statbuf))
1725 error (_("mount: mount point %s does not exist"), node);
1726 else if (stat (node, &statbuf))
1727 error (_("mount: mount point %s is a symbolic link to nowhere"),
1728 node);
1729 else if (stat (spec, &statbuf)) {
1730 if (opt_nofail)
1731 goto out;
1732 error (_("mount: special device %s does not exist"), spec);
1733 } else {
1734 errno = mnt_err;
1735 perror("mount");
1736 }
1737 break;
1738 case ENOTDIR:
1739 if (stat (node, &statbuf) || ! S_ISDIR(statbuf.st_mode))
1740 error (_("mount: mount point %s is not a directory"), node);
1741 else if (stat (spec, &statbuf) && errno == ENOTDIR) {
1742 if (opt_nofail)
1743 goto out;
1744 error (_("mount: special device %s does not exist\n"
1745 " (a path prefix is not a directory)\n"), spec);
1746 } else {
1747 errno = mnt_err;
1748 perror("mount");
1749 }
1750 break;
1751 case EINVAL:
1752 { int fd;
1753 unsigned long long size = 0;
1754
1755 if (flags & MS_REMOUNT) {
1756 error (_("mount: %s not mounted or bad option"), node);
1757 } else {
1758 error (_("mount: wrong fs type, bad option, bad superblock on %s,\n"
1759 " missing codepage or helper program, or other error"),
1760 spec);
1761
1762 if (stat(spec, &statbuf) < 0) {
1763 if (errno == ENOENT) /* network FS? */
1764 error(_(
1765 " (for several filesystems (e.g. nfs, cifs) you might\n"
1766 " need a /sbin/mount.<type> helper program)"));
1767
1768 } else if (S_ISBLK(statbuf.st_mode)
1769 && (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) {
1770
1771 if (blkdev_get_size(fd, &size) == 0) {
1772 if (size == 0 && !loop)
1773 error(_(
1774 " (could this be the IDE device where you in fact use\n"
1775 " ide-scsi so that sr0 or sda or so is needed?)"));
1776
1777 if (size && size <= 2)
1778 error(_(
1779 " (aren't you trying to mount an extended partition,\n"
1780 " instead of some logical partition inside?)"));
1781
1782 close(fd);
1783 }
1784 }
1785 error(_(
1786 " In some cases useful info is found in syslog - try\n"
1787 " dmesg | tail or so\n"));
1788 }
1789 break;
1790 }
1791 case EMFILE:
1792 error (_("mount table full")); break;
1793 case EIO:
1794 error (_("mount: %s: can't read superblock"), spec); break;
1795 case ENODEV:
1796 {
1797 int pfs = known_fstype_in_procfs(types);
1798
1799 if (pfs == 1 || !strcmp(types, "guess"))
1800 error(_("mount: %s: unknown device"), spec);
1801 else if (pfs == 0) {
1802 char *lowtype, *p;
1803 int u;
1804
1805 error (_("mount: unknown filesystem type '%s'"), types);
1806
1807 /* maybe this loser asked for FAT or ISO9660 or isofs */
1808 lowtype = xstrdup(types);
1809 u = 0;
1810 for(p=lowtype; *p; p++) {
1811 if(tolower(*p) != *p) {
1812 *p = tolower(*p);
1813 u++;
1814 }
1815 }
1816 if (u && known_fstype_in_procfs(lowtype) == 1)
1817 error (_("mount: probably you meant %s"), lowtype);
1818 else if (!strncmp(lowtype, "iso", 3) &&
1819 known_fstype_in_procfs("iso9660") == 1)
1820 error (_("mount: maybe you meant 'iso9660'?"));
1821 else if (!strncmp(lowtype, "fat", 3) &&
1822 known_fstype_in_procfs("vfat") == 1)
1823 error (_("mount: maybe you meant 'vfat'?"));
1824 free(lowtype);
1825 } else
1826 error (_("mount: %s has wrong device number or fs type %s not supported"),
1827 spec, types);
1828 break;
1829 }
1830 case ENOTBLK:
1831 if (opt_nofail)
1832 goto out;
1833 if (stat (spec, &statbuf)) /* strange ... */
1834 error (_("mount: %s is not a block device, and stat fails?"), spec);
1835 else if (S_ISBLK(statbuf.st_mode))
1836 error (_("mount: the kernel does not recognize %s as a block device\n"
1837 " (maybe `modprobe driver'?)"), spec);
1838 else if (S_ISREG(statbuf.st_mode))
1839 error (_("mount: %s is not a block device (maybe try `-o loop'?)"),
1840 spec);
1841 else
1842 error (_("mount: %s is not a block device"), spec);
1843 break;
1844 case ENXIO:
1845 if (opt_nofail)
1846 goto out;
1847 error (_("mount: %s is not a valid block device"), spec); break;
1848 case EACCES: /* pre-linux 1.1.38, 1.1.41 and later */
1849 case EROFS: /* linux 1.1.38 and later */
1850 { char *bd = (loop ? "" : _("block device "));
1851 if (ro || (flags & MS_RDONLY)) {
1852 error (_("mount: cannot mount %s%s read-only"),
1853 bd, spec);
1854 break;
1855 } else if (readwrite) {
1856 error (_("mount: %s%s is write-protected but explicit `-w' flag given"),
1857 bd, spec);
1858 break;
1859 } else if (flags & MS_REMOUNT) {
1860 error (_("mount: cannot remount %s%s read-write, is write-protected"),
1861 bd, spec);
1862 break;
1863 } else {
1864 opts = opts0;
1865 types = types0;
1866
1867 if (opts) {
1868 char *opts2 = append_opt(xstrdup(opts), "ro", NULL);
1869 my_free(opts1);
1870 opts = opts1 = opts2;
1871 } else
1872 opts = "ro";
1873 if (types && !strcmp(types, "guess"))
1874 types = 0;
1875 error (_("mount: %s%s is write-protected, mounting read-only"),
1876 bd, spec0);
1877 res = try_mount_one (spec0, node0, types, opts, freq, pass, 1);
1878 goto out;
1879 }
1880 break;
1881 }
1882 case ENOMEDIUM:
1883 error(_("mount: no medium found on %s"), spec);
1884 break;
1885 default:
1886 error ("mount: %s", strerror (mnt_err)); break;
1887 }
1888 }
1889 res = EX_FAIL;
1890
1891 out:
1892
1893 #if defined(HAVE_LIBSELINUX) && defined(HAVE_SECURITY_GET_INITIAL_CONTEXT)
1894 if (res != EX_FAIL && verbose && is_selinux_enabled() > 0) {
1895 security_context_t raw = NULL, def = NULL;
1896
1897 if (getfilecon(node, &raw) > 0 &&
1898 security_get_initial_context("file", &def) == 0) {
1899
1900 if (!selinux_file_context_cmp(raw, def))
1901 printf(_("mount: %s does not contain SELinux labels.\n"
1902 " You just mounted an file system that supports labels which does not\n"
1903 " contain labels, onto an SELinux box. It is likely that confined\n"
1904 " applications will generate AVC messages and not be allowed access to\n"
1905 " this file system. For more details see restorecon(8) and mount(8).\n"),
1906 node);
1907 }
1908 freecon(raw);
1909 freecon(def);
1910 }
1911 #endif
1912
1913 my_free(mount_opts);
1914 my_free(extra_opts);
1915 my_free(spec1);
1916 my_free(node1);
1917 my_free(opts1);
1918 my_free(types1);
1919
1920 return res;
1921 }
1922
1923 static char *
1924 subst_string(const char *s, const char *sub, int sublen, const char *repl) {
1925 char *n;
1926
1927 n = (char *) xmalloc(strlen(s)-sublen+strlen(repl)+1);
1928 strncpy (n, s, sub-s);
1929 strcpy (n + (sub-s), repl);
1930 strcat (n, sub+sublen);
1931 return n;
1932 }
1933
1934 static char *
1935 usersubst(const char *opts) {
1936 char *s, *w;
1937 char id[40];
1938
1939 if (!opts)
1940 return NULL;
1941
1942 s = "uid=useruid";
1943 if (opts && (w = strstr(opts, s)) != NULL) {
1944 sprintf(id, "uid=%u", getuid());
1945 opts = subst_string(opts, w, strlen(s), id);
1946 }
1947 s = "gid=usergid";
1948 if (opts && (w = strstr(opts, s)) != NULL) {
1949 sprintf(id, "gid=%u", getgid());
1950 opts = subst_string(opts, w, strlen(s), id);
1951 }
1952 return xstrdup(opts);
1953 }
1954
1955 static int
1956 is_existing_file (const char *s) {
1957 struct stat statbuf;
1958
1959 return (stat(s, &statbuf) == 0);
1960 }
1961
1962 /*
1963 * Return 0 for success (either mounted sth or -a and NOAUTO was given)
1964 */
1965 static int
1966 mount_one (const char *spec, const char *node, const char *types,
1967 const char *fstabopts, char *cmdlineopts, int freq, int pass) {
1968 const char *nspec = NULL;
1969 char *opts;
1970
1971 /* Substitute values in opts, if required */
1972 opts = usersubst(fstabopts);
1973
1974 /* Merge the fstab and command line options. */
1975 opts = append_opt(opts, cmdlineopts, NULL);
1976
1977 if (types == NULL && !mounttype && !is_existing_file(spec)) {
1978 if (strchr (spec, ':') != NULL) {
1979 types = "nfs";
1980 if (verbose)
1981 printf(_("mount: no type was given - "
1982 "I'll assume nfs because of "
1983 "the colon\n"));
1984 } else if(!strncmp(spec, "//", 2)) {
1985 types = "cifs";
1986 if (verbose)
1987 printf(_("mount: no type was given - "
1988 "I'll assume cifs because of "
1989 "the // prefix\n"));
1990 }
1991 }
1992
1993 /* Handle possible LABEL= and UUID= forms of spec */
1994 if (types == NULL || (strncmp(types, "9p", 2) &&
1995 strncmp(types, "nfs", 3) &&
1996 strncmp(types, "cifs", 4) &&
1997 strncmp(types, "smbfs", 5))) {
1998 if (!is_pseudo_fs(types))
1999 nspec = spec_to_devname(spec);
2000 if (nspec)
2001 spec = nspec;
2002 }
2003
2004 return try_mount_one (spec, node, types, opts, freq, pass, 0);
2005 }
2006
2007 static int
2008 mounted (const char *spec0, const char *node0,
2009 struct mntentchn *fstab_mc __attribute__((__unused__))) {
2010
2011 struct mntentchn *mc, *mc0;
2012 const char *spec, *node;
2013 int ret = 0;
2014
2015 /* Handle possible UUID= and LABEL= in spec */
2016 spec = spec_to_devname(spec0);
2017 if (!spec)
2018 return ret;
2019
2020 node = canonicalize(node0);
2021
2022
2023 mc0 = mtab_head();
2024 for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
2025 if (streq (spec, mc->m.mnt_fsname) &&
2026 streq (node, mc->m.mnt_dir)) {
2027 ret = 1;
2028 break;
2029 }
2030
2031 my_free(spec);
2032 my_free(node);
2033
2034 return ret;
2035 }
2036
2037 /* returns 0 if not mounted, 1 if mounted and -1 in case of error */
2038 static int
2039 is_fstab_entry_mounted(struct mntentchn *mc, int verbose)
2040 {
2041 struct stat st;
2042
2043 if (mounted(mc->m.mnt_fsname, mc->m.mnt_dir, mc))
2044 goto yes;
2045
2046 /* extra care for loop devices */
2047 if ((mc->m.mnt_opts && strstr(mc->m.mnt_opts, "loop=")) ||
2048 (stat(mc->m.mnt_fsname, &st) == 0 && S_ISREG(st.st_mode))) {
2049
2050 char *p = get_option_value(mc->m.mnt_opts, "offset=");
2051 uintmax_t offset = 0;
2052
2053 if (p && strtosize(p, &offset) != 0) {
2054 if (verbose)
2055 printf(_("mount: ignore %s "
2056 "(unparsable offset= option)\n"),
2057 mc->m.mnt_fsname);
2058 return -1;
2059 }
2060 free(p);
2061 if (is_mounted_same_loopfile(mc->m.mnt_dir, mc->m.mnt_fsname, offset))
2062 goto yes;
2063 }
2064
2065 return 0;
2066 yes:
2067 if (verbose)
2068 printf(_("mount: %s already mounted on %s\n"),
2069 mc->m.mnt_fsname, mc->m.mnt_dir);
2070 return 1;
2071 }
2072
2073 /* avoid using stat() on things we are not going to mount anyway.. */
2074 static int
2075 has_noauto (const char *opts) {
2076 char *s;
2077
2078 if (!opts)
2079 return 0;
2080 s = strstr(opts, "noauto");
2081 if (!s)
2082 return 0;
2083 return (s == opts || s[-1] == ',') && (s[6] == 0 || s[6] == ',');
2084 }
2085
2086 /* Mount all filesystems of the specified types except swap and root. */
2087 /* With the --fork option: fork and let different incarnations of
2088 mount handle different filesystems. However, try to avoid several
2089 simultaneous mounts on the same physical disk, since that is very slow. */
2090 #define DISKMAJOR(m) (((int) m) & ~0xf)
2091
2092 static int
2093 do_mount_all (char *types, char *options, char *test_opts) {
2094 struct mntentchn *mc, *mc0, *mtmp;
2095 int status = 0;
2096 struct stat statbuf;
2097 struct child {
2098 pid_t pid;
2099 char *group;
2100 struct mntentchn *mec;
2101 struct mntentchn *meclast;
2102 struct child *nxt;
2103 } childhead, *childtail, *cp;
2104 char major[22];
2105 char *g, *colon;
2106
2107 /* build a chain of what we have to do, or maybe
2108 several chains, one for each major or NFS host */
2109 childhead.nxt = 0;
2110 childtail = &childhead;
2111 mc0 = fstab_head();
2112 for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
2113 if (has_noauto (mc->m.mnt_opts))
2114 continue;
2115 if (matching_type (mc->m.mnt_type, types)
2116 && matching_opts (mc->m.mnt_opts, test_opts)
2117 && !streq (mc->m.mnt_dir, "/")
2118 && !streq (mc->m.mnt_dir, "root")
2119 && !is_fstab_entry_mounted(mc, verbose)) {
2120
2121 mtmp = (struct mntentchn *) xmalloc(sizeof(*mtmp));
2122 *mtmp = *mc;
2123 mtmp->nxt = 0;
2124 g = NULL;
2125 if (optfork) {
2126 if (stat(mc->m.mnt_fsname, &statbuf) == 0 &&
2127 S_ISBLK(statbuf.st_mode)) {
2128 sprintf(major, "#%x",
2129 DISKMAJOR(statbuf.st_rdev));
2130 g = major;
2131 }
2132 if (strcmp(mc->m.mnt_type, "nfs") == 0) {
2133 g = xstrdup(mc->m.mnt_fsname);
2134 colon = strchr(g, ':');
2135 if (colon)
2136 *colon = '\0';
2137 }
2138 }
2139 if (g) {
2140 for (cp = childhead.nxt; cp; cp = cp->nxt)
2141 if (cp->group &&
2142 strcmp(cp->group, g) == 0) {
2143 cp->meclast->nxt = mtmp;
2144 cp->meclast = mtmp;
2145 goto fnd;
2146 }
2147 }
2148 cp = (struct child *) xmalloc(sizeof *cp);
2149 cp->nxt = 0;
2150 cp->mec = cp->meclast = mtmp;
2151 cp->group = xstrdup(g);
2152 cp->pid = 0;
2153 childtail->nxt = cp;
2154 childtail = cp;
2155 fnd:;
2156
2157 }
2158 }
2159
2160 /* now do everything */
2161 for (cp = childhead.nxt; cp; cp = cp->nxt) {
2162 pid_t p = -1;
2163 if (optfork) {
2164 p = fork();
2165 if (p == -1) {
2166 int errsv = errno;
2167 error(_("mount: cannot fork: %s"),
2168 strerror (errsv));
2169 }
2170 else if (p != 0)
2171 cp->pid = p;
2172 }
2173
2174 /* if child, or not forked, do the mounting */
2175 if (p == 0 || p == -1) {
2176 for (mc = cp->mec; mc; mc = mc->nxt) {
2177 status |= mount_one (mc->m.mnt_fsname,
2178 mc->m.mnt_dir,
2179 mc->m.mnt_type,
2180 mc->m.mnt_opts,
2181 options, 0, 0);
2182 }
2183 if (mountcount)
2184 status |= EX_SOMEOK;
2185 if (p == 0)
2186 exit(status);
2187 }
2188 }
2189
2190 /* wait for children, if any */
2191 while ((cp = childhead.nxt) != NULL) {
2192 childhead.nxt = cp->nxt;
2193 if (cp->pid) {
2194 int ret;
2195 keep_waiting:
2196 if(waitpid(cp->pid, &ret, 0) == -1) {
2197 if (errno == EINTR)
2198 goto keep_waiting;
2199 perror("waitpid");
2200 } else if (WIFEXITED(ret))
2201 status |= WEXITSTATUS(ret);
2202 else
2203 status |= EX_SYSERR;
2204 }
2205 }
2206 if (mountcount)
2207 status |= EX_SOMEOK;
2208 return status;
2209 }
2210
2211 static struct option longopts[] = {
2212 { "all", 0, 0, 'a' },
2213 { "fake", 0, 0, 'f' },
2214 { "fork", 0, 0, 'F' },
2215 { "help", 0, 0, 'h' },
2216 { "no-mtab", 0, 0, 'n' },
2217 { "read-only", 0, 0, 'r' },
2218 { "ro", 0, 0, 'r' },
2219 { "verbose", 0, 0, 'v' },
2220 { "version", 0, 0, 'V' },
2221 { "read-write", 0, 0, 'w' },
2222 { "rw", 0, 0, 'w' },
2223 { "options", 1, 0, 'o' },
2224 { "test-opts", 1, 0, 'O' },
2225 { "pass-fd", 1, 0, 'p' },
2226 { "types", 1, 0, 't' },
2227 { "bind", 0, 0, 'B' },
2228 { "move", 0, 0, 'M' },
2229 { "guess-fstype", 1, 0, 134 },
2230 { "rbind", 0, 0, 'R' },
2231 { "make-shared", 0, 0, 136 },
2232 { "make-slave", 0, 0, 137 },
2233 { "make-private", 0, 0, 138 },
2234 { "make-unbindable", 0, 0, 139 },
2235 { "make-rshared", 0, 0, 140 },
2236 { "make-rslave", 0, 0, 141 },
2237 { "make-rprivate", 0, 0, 142 },
2238 { "make-runbindable", 0, 0, 143 },
2239 { "no-canonicalize", 0, 0, 144 },
2240 { "internal-only", 0, 0, 'i' },
2241 { NULL, 0, 0, 0 }
2242 };
2243
2244 /* Keep the usage message at max 22 lines, each at most 70 chars long.
2245 The user should not need a pager to read it. */
2246 static void
2247 usage (FILE *fp, int n) {
2248 fprintf(fp, _(
2249 "Usage: mount -V : print version\n"
2250 " mount -h : print this help\n"
2251 " mount : list mounted filesystems\n"
2252 " mount -l : idem, including volume labels\n"
2253 "So far the informational part. Next the mounting.\n"
2254 "The command is `mount [-t fstype] something somewhere'.\n"
2255 "Details found in /etc/fstab may be omitted.\n"
2256 " mount -a [-t|-O] ... : mount all stuff from /etc/fstab\n"
2257 " mount device : mount device at the known place\n"
2258 " mount directory : mount known device here\n"
2259 " mount -t type dev dir : ordinary mount command\n"
2260 "Note that one does not really mount a device, one mounts\n"
2261 "a filesystem (of the given type) found on the device.\n"
2262 "One can also mount an already visible directory tree elsewhere:\n"
2263 " mount --bind olddir newdir\n"
2264 "or move a subtree:\n"
2265 " mount --move olddir newdir\n"
2266 "One can change the type of mount containing the directory dir:\n"
2267 " mount --make-shared dir\n"
2268 " mount --make-slave dir\n"
2269 " mount --make-private dir\n"
2270 " mount --make-unbindable dir\n"
2271 "One can change the type of all the mounts in a mount subtree\n"
2272 "containing the directory dir:\n"
2273 " mount --make-rshared dir\n"
2274 " mount --make-rslave dir\n"
2275 " mount --make-rprivate dir\n"
2276 " mount --make-runbindable dir\n"
2277 "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n"
2278 "or by label, using -L label or by uuid, using -U uuid .\n"
2279 "Other options: [-nfFrsvw] [-o options] [-p passwdfd].\n"
2280 "For many more details, say man 8 mount .\n"
2281 ));
2282
2283 unlock_mtab();
2284 exit (n);
2285 }
2286
2287 /* returns mount entry from fstab */
2288 static struct mntentchn *
2289 getfs(const char *spec, const char *uuid, const char *label)
2290 {
2291 struct mntentchn *mc = NULL;
2292 const char *devname = NULL;
2293
2294 if (!spec && !uuid && !label)
2295 return NULL;
2296
2297 /*
2298 * A) 99% of all cases, the spec on cmdline matches
2299 * with spec in fstab
2300 */
2301 if (uuid)
2302 mc = getfs_by_uuid(uuid);
2303 else if (label)
2304 mc = getfs_by_label(label);
2305 else {
2306 mc = getfs_by_dir(spec);
2307
2308 if (!mc)
2309 mc = getfs_by_spec(spec);
2310 }
2311 if (mc)
2312 return mc;
2313
2314 /*
2315 * B) UUID or LABEL on cmdline, but devname in fstab
2316 */
2317 if (uuid)
2318 devname = fsprobe_get_devname_by_uuid(uuid);
2319 else if (label)
2320 devname = fsprobe_get_devname_by_label(label);
2321 else
2322 devname = spec_to_devname(spec);
2323
2324 if (devname)
2325 mc = getfs_by_devname(devname);
2326
2327 /*
2328 * C) mixed
2329 */
2330 if (!mc && devname) {
2331 const char *id = NULL;
2332
2333 if (!label && (!spec || strncmp(spec, "LABEL=", 6))) {
2334 id = fsprobe_get_label_by_devname(devname);
2335 if (id)
2336 mc = getfs_by_label(id);
2337 }
2338 if (!mc && !uuid && (!spec || strncmp(spec, "UUID=", 5))) {
2339 id = fsprobe_get_uuid_by_devname(devname);
2340 if (id)
2341 mc = getfs_by_uuid(id);
2342 }
2343 my_free(id);
2344
2345 if (mc) {
2346 /* use real device name to avoid repetitional
2347 * conversion from LABEL/UUID to devname
2348 */
2349 my_free(mc->m.mnt_fsname);
2350 mc->m.mnt_fsname = xstrdup(devname);
2351 }
2352 }
2353
2354 /*
2355 * D) remount -- try /etc/mtab
2356 * Earlier mtab was tried first, but this would sometimes try the
2357 * wrong mount in case mtab had the root device entry wrong. Try
2358 * the last occurrence first, since that is the visible mount.
2359 */
2360 if (!mc && (devname || spec))
2361 mc = getmntfilebackward (devname ? devname : spec, NULL);
2362
2363 my_free(devname);
2364 return mc;
2365 }
2366
2367
2368 static void
2369 print_version(int rc) {
2370 printf( "mount from %s (with "
2371 #ifdef HAVE_LIBBLKID
2372 "libblkid"
2373 #else
2374 "libvolume_id"
2375 #endif
2376 #ifdef HAVE_LIBSELINUX
2377 " and selinux"
2378 #endif
2379 " support)\n", PACKAGE_STRING);
2380 exit(rc);
2381 }
2382
2383 int
2384 main(int argc, char *argv[]) {
2385 int c, result = 0, specseen;
2386 char *options = NULL, *test_opts = NULL, *node;
2387 const char *spec = NULL;
2388 char *label = NULL;
2389 char *uuid = NULL;
2390 char *types = NULL;
2391 char *p;
2392 struct mntentchn *mc;
2393 int fd;
2394
2395 sanitize_env();
2396 setlocale(LC_ALL, "");
2397 bindtextdomain(PACKAGE, LOCALEDIR);
2398 textdomain(PACKAGE);
2399 atexit(close_stdout);
2400
2401 progname = argv[0];
2402 if ((p = strrchr(progname, '/')) != NULL)
2403 progname = p+1;
2404
2405 umask(022);
2406
2407 /* People report that a mount called from init without console
2408 writes error messages to /etc/mtab
2409 Let us try to avoid getting fd's 0,1,2 */
2410 while((fd = open("/dev/null", O_RDWR)) == 0 || fd == 1 || fd == 2) ;
2411 if (fd > 2)
2412 close(fd);
2413
2414 fsprobe_init();
2415
2416 #ifdef DO_PS_FIDDLING
2417 initproctitle(argc, argv);
2418 #endif
2419
2420 while ((c = getopt_long (argc, argv, "aBfFhilL:Mno:O:p:rRsU:vVwt:",
2421 longopts, NULL)) != -1) {
2422 switch (c) {
2423 case 'a': /* mount everything in fstab */
2424 ++mount_all;
2425 break;
2426 case 'B': /* bind */
2427 mounttype = MS_BIND;
2428 break;
2429 case 'f': /* fake: don't actually call mount(2) */
2430 ++fake;
2431 break;
2432 case 'F':
2433 ++optfork;
2434 break;
2435 case 'h': /* help */
2436 usage (stdout, 0);
2437 break;
2438 case 'i':
2439 external_allowed = 0;
2440 break;
2441 case 'l':
2442 list_with_volumelabel = 1;
2443 break;
2444 case 'L':
2445 label = optarg;
2446 break;
2447 case 'M': /* move */
2448 mounttype = MS_MOVE;
2449 break;
2450 case 'n': /* do not write /etc/mtab */
2451 ++nomtab;
2452 break;
2453 case 'o': /* specify mount options */
2454 options = append_opt(options, optarg, NULL);
2455 break;
2456 case 'O': /* with -t: mount only if (not) opt */
2457 test_opts = append_opt(test_opts, optarg, NULL);
2458 break;
2459 case 'p': /* fd on which to read passwd */
2460 set_pfd(optarg);
2461 break;
2462 case 'r': /* mount readonly */
2463 readonly = 1;
2464 readwrite = 0;
2465 break;
2466 case 'R': /* rbind */
2467 mounttype = (MS_BIND | MS_REC);
2468 break;
2469 case 's': /* allow sloppy mount options */
2470 sloppy = 1;
2471 break;
2472 case 't': /* specify file system types */
2473 types = optarg;
2474 break;
2475 case 'U':
2476 uuid = optarg;
2477 break;
2478 case 'v': /* be chatty - more so if repeated */
2479 ++verbose;
2480 break;
2481 case 'V': /* version */
2482 print_version(EXIT_SUCCESS);
2483 break;
2484 case 'w': /* mount read/write */
2485 readwrite = 1;
2486 readonly = 0;
2487 break;
2488 case 0:
2489 break;
2490
2491 case 134:
2492 /* undocumented, may go away again:
2493 call: mount --guess-fstype device
2494 use only for testing purposes -
2495 the guessing is not reliable at all */
2496 {
2497 const char *fstype;
2498 fstype = fsprobe_get_fstype_by_devname(optarg);
2499 printf("%s\n", fstype ? fstype : "unknown");
2500 exit(fstype ? 0 : EX_FAIL);
2501 }
2502
2503 case 136:
2504 mounttype = MS_SHARED;
2505 break;
2506
2507 case 137:
2508 mounttype = MS_SLAVE;
2509 break;
2510
2511 case 138:
2512 mounttype = MS_PRIVATE;
2513 break;
2514
2515 case 139:
2516 mounttype = MS_UNBINDABLE;
2517 break;
2518
2519 case 140:
2520 mounttype = (MS_SHARED | MS_REC);
2521 break;
2522
2523 case 141:
2524 mounttype = (MS_SLAVE | MS_REC);
2525 break;
2526
2527 case 142:
2528 mounttype = (MS_PRIVATE | MS_REC);
2529 break;
2530
2531 case 143:
2532 mounttype = (MS_UNBINDABLE | MS_REC);
2533 break;
2534 case 144:
2535 nocanonicalize = 1;
2536 break;
2537 case '?':
2538 default:
2539 usage (stderr, EX_USAGE);
2540 }
2541 }
2542
2543 if (verbose > 2) {
2544 printf("mount: fstab path: \"%s\"\n", _PATH_MNTTAB);
2545 printf("mount: mtab path: \"%s\"\n", _PATH_MOUNTED);
2546 printf("mount: lock path: \"%s\"\n", _PATH_MOUNTED_LOCK);
2547 printf("mount: temp path: \"%s\"\n", _PATH_MOUNTED_TMP);
2548 printf("mount: UID: %u\n", getuid());
2549 printf("mount: eUID: %u\n", geteuid());
2550 }
2551
2552 argc -= optind;
2553 argv += optind;
2554
2555 specseen = (uuid || label) ? 1 : 0; /* yes, .. i know */
2556
2557 if (argc+specseen == 0 && !mount_all) {
2558 if (options || mounttype)
2559 usage (stderr, EX_USAGE);
2560 return print_all (types);
2561 }
2562
2563 {
2564 const uid_t ruid = getuid();
2565 const uid_t euid = geteuid();
2566
2567 /* if we're really root and aren't running setuid */
2568 if (((uid_t)0 == ruid) && (ruid == euid)) {
2569 restricted = 0;
2570 }
2571
2572 if (restricted &&
2573 (types || options || readwrite || nomtab || mount_all ||
2574 nocanonicalize || fake || mounttype ||
2575 (argc + specseen) != 1)) {
2576
2577 if (ruid == 0 && euid != 0)
2578 /* user is root, but setuid to non-root */
2579 die (EX_USAGE, _("mount: only root can do that "
2580 "(effective UID is %u)"), euid);
2581
2582 die (EX_USAGE, _("mount: only root can do that"));
2583 }
2584 }
2585
2586 atexit(unlock_mtab);
2587
2588 switch (argc+specseen) {
2589 case 0:
2590 /* mount -a */
2591 result = do_mount_all (types, options, test_opts);
2592 if (result == 0 && verbose && !fake)
2593 error(_("nothing was mounted"));
2594 break;
2595
2596 case 1:
2597 /* mount [-nfrvw] [-o options] special | node
2598 * mount -L label (or -U uuid)
2599 * (/etc/fstab is necessary)
2600 */
2601 if (types != NULL)
2602 usage (stderr, EX_USAGE);
2603
2604 if (uuid || label)
2605 mc = getfs(NULL, uuid, label);
2606 else
2607 mc = getfs(*argv, NULL, NULL);
2608
2609 if (!mc) {
2610 if (uuid || label)
2611 die (EX_USAGE, _("mount: no such partition found"));
2612
2613 die (EX_USAGE,
2614 _("mount: can't find %s in %s or %s"),
2615 *argv, _PATH_MNTTAB, _PATH_MOUNTED);
2616 }
2617
2618 result = mount_one (xstrdup (mc->m.mnt_fsname),
2619 xstrdup (mc->m.mnt_dir),
2620 xstrdup (mc->m.mnt_type),
2621 mc->m.mnt_opts, options, 0, 0);
2622 break;
2623
2624 case 2:
2625 /* mount special node (/etc/fstab is not necessary) */
2626 if (specseen) {
2627 /* mount -L label node (or -U uuid) */
2628 spec = uuid ? fsprobe_get_devname_by_uuid(uuid) :
2629 fsprobe_get_devname_by_label(label);
2630 node = argv[0];
2631 } else {
2632 /* mount special node */
2633 spec = argv[0];
2634 node = argv[1];
2635 }
2636 if (!spec)
2637 die (EX_USAGE, _("mount: no such partition found"));
2638
2639 result = mount_one (spec, node, types, NULL, options, 0, 0);
2640 break;
2641
2642 default:
2643 usage (stderr, EX_USAGE);
2644 }
2645
2646 if (result == EX_SOMEOK)
2647 result = 0;
2648
2649 fsprobe_exit();
2650
2651 exit (result);
2652 }