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