blob: b059d7094cca787dbebec6701cd942a229b5352d [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersencc8ed391999-10-05 16:24:54 +00002/*
Eric Andersen596e5461999-10-07 08:30:23 +00003 * Mini mount implementation for busybox
4 *
Eric Andersenc4996011999-10-20 22:08:37 +00005 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00006 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersen596e5461999-10-07 08:30:23 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * 3/21/1999 Charles P. Wright <cpwright@cpwright.com>
23 * searches through fstab when -a is passed
24 * will try mounting stuff with all fses when passed -t auto
25 *
26 * 1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab.
Eric Andersenc4996011999-10-20 22:08:37 +000027 *
Eric Andersencb81e642003-07-14 21:21:08 +000028 * 1999-10-07 Erik Andersen <andersen@codepoet.org>.
Erik Andersen31638212000-01-15 22:28:50 +000029 * Rewrite of a lot of code. Removed mtab usage (I plan on
Eric Andersenc7bda1c2004-03-15 08:29:22 +000030 * putting it back as a compile-time option some time),
31 * major adjustments to option parsing, and some serious
Eric Andersenc4996011999-10-20 22:08:37 +000032 * dieting all around.
Erik Andersenb7cc49d2000-01-13 06:38:14 +000033 *
Eric Andersenaff114c2004-04-14 17:51:38 +000034 * 1999-11-06 mtab support is back - andersee
Erik Andersen31638212000-01-15 22:28:50 +000035 *
Erik Andersenb7cc49d2000-01-13 06:38:14 +000036 * 2000-01-12 Ben Collins <bcollins@debian.org>, Borrowed utils-linux's
37 * mount to add loop support.
Eric Andersenfdd51032000-08-02 18:48:26 +000038 *
39 * 2000-04-30 Dave Cinege <dcinege@psychosis.com>
40 * Rewrote fstab while loop and lower mount section. Can now do
41 * single mounts from fstab. Can override fstab options for single
42 * mount. Common mount_one call for single mounts and 'all'. Fixed
Eric Andersenc7bda1c2004-03-15 08:29:22 +000043 * mtab updating and stale entries. Removed 'remount' default.
44 *
Erik Andersenb7cc49d2000-01-13 06:38:14 +000045 */
Eric Andersencc8ed391999-10-05 16:24:54 +000046
Matt Kraai34251112001-05-02 21:17:38 +000047#include <limits.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000048#include <stdlib.h>
49#include <unistd.h>
50#include <errno.h>
51#include <string.h>
52#include <stdio.h>
53#include <mntent.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000054#include <ctype.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000055#include "busybox.h"
Eric Andersenbd22ed82000-07-08 18:55:24 +000056
Eric Andersend9fe9582003-07-22 08:25:37 +000057#ifdef CONFIG_NFSMOUNT
58#if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
59#error "You need to build uClibc with UCLIBC_HAS_RPC for busybox mount with NFS support to compile."
60#endif
61#endif
62
Mark Whitley59ab0252001-01-23 22:30:04 +000063enum {
Glenn L McGrath9fef17d2002-08-22 18:41:20 +000064 MS_MGC_VAL = 0xc0ed0000, /* Magic number indicatng "new" flags */
65 MS_RDONLY = 1, /* Mount read-only */
66 MS_NOSUID = 2, /* Ignore suid and sgid bits */
67 MS_NODEV = 4, /* Disallow access to device special files */
68 MS_NOEXEC = 8, /* Disallow program execution */
69 MS_SYNCHRONOUS = 16, /* Writes are synced at once */
70 MS_REMOUNT = 32, /* Alter flags of a mounted FS */
71 MS_MANDLOCK = 64, /* Allow mandatory locks on an FS */
72 S_QUOTA = 128, /* Quota initialized for file/directory/symlink */
73 S_APPEND = 256, /* Append-only file */
74 S_IMMUTABLE = 512, /* Immutable file */
75 MS_NOATIME = 1024, /* Do not update access times. */
76 MS_NODIRATIME = 2048, /* Do not update directory access times */
77 MS_BIND = 4096, /* Use the new linux 2.4.x "mount --bind" feature */
Eric Andersen86af0522004-05-26 21:26:07 +000078 MS_MOVE = 8192, /* Use the new linux 2.4.x "mount --move" feature */
Mark Whitley59ab0252001-01-23 22:30:04 +000079};
Eric Andersencc8ed391999-10-05 16:24:54 +000080
Eric Andersenbd22ed82000-07-08 18:55:24 +000081
Eric Andersenbdfd0d72001-10-24 05:00:29 +000082#if defined CONFIG_FEATURE_MOUNT_LOOP
Erik Andersenb7cc49d2000-01-13 06:38:14 +000083#include <fcntl.h>
84#include <sys/ioctl.h>
Erik Andersene132f4b2000-02-09 04:16:43 +000085static int use_loop = FALSE;
Erik Andersenb7cc49d2000-01-13 06:38:14 +000086#endif
87
Glenn L McGrath9fef17d2002-08-22 18:41:20 +000088extern int mount(__const char *__special_file, __const char *__dir,
89 __const char *__fstype, unsigned long int __rwflag,
90 __const void *__data);
91extern int umount(__const char *__special_file);
92extern int umount2(__const char *__special_file, int __flags);
Eric Andersende440672001-03-01 07:55:49 +000093
Glenn L McGrath9fef17d2002-08-22 18:41:20 +000094extern int sysfs(int option, unsigned int fs_index, char *buf);
Eric Andersena57ba4d2000-07-08 19:20:49 +000095
Eric Andersencc8ed391999-10-05 16:24:54 +000096struct mount_options {
Erik Andersene49d5ec2000-02-08 19:58:47 +000097 const char *name;
98 unsigned long and;
99 unsigned long or;
Eric Andersencc8ed391999-10-05 16:24:54 +0000100};
101
Eric Andersen596e5461999-10-07 08:30:23 +0000102static const struct mount_options mount_options[] = {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000103 {"async", ~MS_SYNCHRONOUS, 0},
Erik Andersen6c5f2c62000-05-05 19:49:33 +0000104 {"atime", ~0, ~MS_NOATIME},
Erik Andersene49d5ec2000-02-08 19:58:47 +0000105 {"defaults", ~0, 0},
Robert Grieblaa385d42002-05-14 22:56:29 +0000106 {"noauto", ~0, 0},
Erik Andersene49d5ec2000-02-08 19:58:47 +0000107 {"dev", ~MS_NODEV, 0},
Erik Andersen6c5f2c62000-05-05 19:49:33 +0000108 {"diratime", ~0, ~MS_NODIRATIME},
Erik Andersene49d5ec2000-02-08 19:58:47 +0000109 {"exec", ~MS_NOEXEC, 0},
Erik Andersen6c5f2c62000-05-05 19:49:33 +0000110 {"noatime", ~0, MS_NOATIME},
Erik Andersene49d5ec2000-02-08 19:58:47 +0000111 {"nodev", ~0, MS_NODEV},
Erik Andersen6c5f2c62000-05-05 19:49:33 +0000112 {"nodiratime", ~0, MS_NODIRATIME},
Erik Andersene49d5ec2000-02-08 19:58:47 +0000113 {"noexec", ~0, MS_NOEXEC},
114 {"nosuid", ~0, MS_NOSUID},
115 {"remount", ~0, MS_REMOUNT},
116 {"ro", ~0, MS_RDONLY},
117 {"rw", ~MS_RDONLY, 0},
118 {"suid", ~MS_NOSUID, 0},
119 {"sync", ~0, MS_SYNCHRONOUS},
Eric Andersen2f6e1f82001-05-21 15:59:34 +0000120 {"bind", ~0, MS_BIND},
Eric Andersen86af0522004-05-26 21:26:07 +0000121 {"move", ~0, MS_MOVE},
Erik Andersene49d5ec2000-02-08 19:58:47 +0000122 {0, 0, 0}
Eric Andersencc8ed391999-10-05 16:24:54 +0000123};
124
Eric Andersend0246fb1999-11-04 21:18:07 +0000125static int
Glenn L McGrath8042f652002-08-23 06:17:46 +0000126do_mount(char *specialfile, char *dir, char *filesystemtype, long flags,
127 void *string_flags, int useMtab, int fakeIt, char *mtab_opts,
128 int mount_all)
Eric Andersend0246fb1999-11-04 21:18:07 +0000129{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000130 int status = 0;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000131
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000132#if defined CONFIG_FEATURE_MOUNT_LOOP
Erik Andersene132f4b2000-02-09 04:16:43 +0000133 char *lofile = NULL;
Eric Andersen8847b9a2000-09-21 01:33:05 +0000134#endif
Eric Andersend0246fb1999-11-04 21:18:07 +0000135
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000136 if (!fakeIt) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000137#if defined CONFIG_FEATURE_MOUNT_LOOP
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000138 if (use_loop == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000139 int loro = flags & MS_RDONLY;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000140
Mark Whitleye677dfe2001-02-26 17:45:58 +0000141 lofile = specialfile;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000142
143 specialfile = find_unused_loop_device();
144 if (specialfile == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000145 bb_error_msg_and_die("Could not find a spare loop device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000146 }
147 if (set_loop(specialfile, lofile, 0, &loro)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000148 bb_error_msg_and_die("Could not setup loop device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000149 }
150 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000151 bb_error_msg("WARNING: loop device is read-only");
Matt Kraai94f3a572001-07-05 14:46:07 +0000152 flags |= MS_RDONLY;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000153 }
154 }
Erik Andersenb7cc49d2000-01-13 06:38:14 +0000155#endif
Eric Andersena42982e2000-06-07 17:28:53 +0000156 status = mount(specialfile, dir, filesystemtype, flags, string_flags);
Matt Kraai9344f752001-06-03 02:21:38 +0000157 if (status < 0 && errno == EROFS) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000158 bb_error_msg("%s is write-protected, mounting read-only",
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000159 specialfile);
160 status = mount(specialfile, dir, filesystemtype, flags |=
161 MS_RDONLY, string_flags);
Eric Andersen0cccdfa2000-09-20 06:23:36 +0000162 }
Matt Kraai9344f752001-06-03 02:21:38 +0000163 /* Don't whine about already mounted filesystems when mounting all. */
Glenn L McGrath8042f652002-08-23 06:17:46 +0000164 if (status < 0 && errno == EBUSY && mount_all) {
Matt Kraai9344f752001-06-03 02:21:38 +0000165 return TRUE;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000166 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000167 }
Erik Andersen5cbdd712000-01-26 20:06:48 +0000168
169
Erik Andersene49d5ec2000-02-08 19:58:47 +0000170 /* If the mount was sucessful, do anything needed, then return TRUE */
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000171 if (status == 0 || fakeIt == TRUE) {
Erik Andersen5cbdd712000-01-26 20:06:48 +0000172
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000173#if defined CONFIG_FEATURE_MTAB_SUPPORT
Matt Kraai1f0c4362001-12-20 23:13:26 +0000174 if (useMtab) {
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000175 erase_mtab(specialfile); /* Clean any stale entries */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000176 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
177 }
178#endif
179 return (TRUE);
180 }
181
182 /* Bummer. mount failed. Clean up */
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000183#if defined CONFIG_FEATURE_MOUNT_LOOP
Erik Andersene132f4b2000-02-09 04:16:43 +0000184 if (lofile != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000185 del_loop(specialfile);
Erik Andersen5cbdd712000-01-26 20:06:48 +0000186 }
Eric Andersend0246fb1999-11-04 21:18:07 +0000187#endif
Eric Andersena42982e2000-06-07 17:28:53 +0000188
189 if (errno == EPERM) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000190 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
Eric Andersena42982e2000-06-07 17:28:53 +0000191 }
192
Erik Andersene49d5ec2000-02-08 19:58:47 +0000193 return (FALSE);
Erik Andersenb7cc49d2000-01-13 06:38:14 +0000194}
195
Eric Andersend0246fb1999-11-04 21:18:07 +0000196
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000197static void paste_str(char **s1, const char *s2)
198{
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000199 *s1 = xrealloc(*s1, strlen(*s1) + strlen(s2) + 1);
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000200 strcat(*s1, s2);
201}
Eric Andersencc8ed391999-10-05 16:24:54 +0000202
Eric Andersen8341a151999-10-08 17:14:14 +0000203/* Seperate standard mount options from the nonstandard string options */
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000204static void parse_mount_options(char *options, int *flags, char **strflags)
Eric Andersencc8ed391999-10-05 16:24:54 +0000205{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000206 while (options) {
207 int gotone = FALSE;
208 char *comma = strchr(options, ',');
209 const struct mount_options *f = mount_options;
Eric Andersencc8ed391999-10-05 16:24:54 +0000210
Glenn L McGrath8042f652002-08-23 06:17:46 +0000211 if (comma) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000212 *comma = '\0';
Glenn L McGrath8042f652002-08-23 06:17:46 +0000213 }
Eric Andersen3ae0c781999-11-04 01:13:21 +0000214
Erik Andersene49d5ec2000-02-08 19:58:47 +0000215 while (f->name != 0) {
216 if (strcasecmp(f->name, options) == 0) {
217
218 *flags &= f->and;
219 *flags |= f->or;
220 gotone = TRUE;
221 break;
222 }
223 f++;
224 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000225#if defined CONFIG_FEATURE_MOUNT_LOOP
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000226 if (!strcasecmp("loop", options)) { /* loop device support */
Erik Andersene132f4b2000-02-09 04:16:43 +0000227 use_loop = TRUE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000228 gotone = TRUE;
229 }
Erik Andersenb7cc49d2000-01-13 06:38:14 +0000230#endif
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000231 if (!gotone) {
Glenn L McGrath8042f652002-08-23 06:17:46 +0000232 if (**strflags) {
233 /* have previous parsed options */
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000234 paste_str(strflags, ",");
Glenn L McGrath8042f652002-08-23 06:17:46 +0000235 }
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000236 paste_str(strflags, options);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000237 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000238 if (comma) {
239 *comma = ',';
240 options = ++comma;
241 } else {
242 break;
243 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000244 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000245}
246
Glenn L McGrath8042f652002-08-23 06:17:46 +0000247static int mount_one(char *blockDevice, char *directory, char *filesystemType,
248 unsigned long flags, char *string_flags, int useMtab,
249 int fakeIt, char *mtab_opts, int whineOnErrors,
250 int mount_all)
Eric Andersencc8ed391999-10-05 16:24:54 +0000251{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000252 int status = 0;
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000253 if (strcmp(filesystemType, "auto") == 0) {
254 char buf[255];
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000255 FILE *f;
256 int read_proc = 0;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000257
258 f = fopen("/etc/filesystems", "r");
259
260 if (f) {
261 while (fgets(buf, sizeof(buf), f)) {
Glenn L McGrath8042f652002-08-23 06:17:46 +0000262 if (*buf == '*') {
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000263 read_proc = 1;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000264 } else if (*buf == '#') {
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000265 continue;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000266 } else {
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000267 filesystemType = buf;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000268
269 /* Add NULL termination to each line */
Glenn L McGrath8042f652002-08-23 06:17:46 +0000270 while (*filesystemType && !isspace(*filesystemType)) {
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000271 filesystemType++;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000272 }
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000273 *filesystemType = '\0';
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000274
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000275 filesystemType = buf;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000276
Manuel Novoa III cad53642003-03-19 09:13:01 +0000277 if (bb_strlen(filesystemType)) {
Eric Andersend5c746f2003-12-09 23:50:24 +0000278 status = do_mount(blockDevice, directory, filesystemType,
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000279 flags | MS_MGC_VAL, string_flags,
280 useMtab, fakeIt, mtab_opts, mount_all);
Glenn L McGrath8042f652002-08-23 06:17:46 +0000281 if (status) {
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000282 break;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000283 }
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000284 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000285
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000286 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000287 }
288 fclose(f);
Eric Andersenc1893c52003-12-12 07:01:14 +0000289 } else {
290 read_proc = 1;
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000291 }
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000292
Eric Andersend5c746f2003-12-09 23:50:24 +0000293 if (read_proc && !status) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000294
Manuel Novoa III cad53642003-03-19 09:13:01 +0000295 f = bb_xfopen("/proc/filesystems", "r");
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000296
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000297 while (fgets(buf, sizeof(buf), f) != NULL) {
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000298 filesystemType = buf;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000299 if (*filesystemType == '\t') { /* Not a nodev filesystem */
300
301 /* Add NULL termination to each line */
Glenn L McGrath8042f652002-08-23 06:17:46 +0000302 while (*filesystemType && *filesystemType != '\n') {
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000303 filesystemType++;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000304 }
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000305 *filesystemType = '\0';
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000306
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000307 filesystemType = buf;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000308 filesystemType++; /* hop past tab */
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000309
Eric Andersend5c746f2003-12-09 23:50:24 +0000310 status = do_mount(blockDevice, directory, filesystemType,
Glenn L McGrath8042f652002-08-23 06:17:46 +0000311 flags | MS_MGC_VAL, string_flags, useMtab,
312 fakeIt, mtab_opts, mount_all);
313 if (status) {
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000314 break;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000315 }
Robert Griebl2a4a8d82002-07-24 01:41:30 +0000316 }
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000317 }
Eric Andersend5c746f2003-12-09 23:50:24 +0000318 fclose(f);
Eric Andersen8acbf1d2001-10-18 04:10:22 +0000319 }
Eric Andersendeca1062002-12-05 07:24:08 +0000320 } else {
Eric Andersenc1893c52003-12-12 07:01:14 +0000321 status = do_mount(blockDevice, directory, filesystemType,
Glenn L McGrath8042f652002-08-23 06:17:46 +0000322 flags | MS_MGC_VAL, string_flags, useMtab, fakeIt,
323 mtab_opts, mount_all);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000324 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000325
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000326 if (!status) {
Matt Kraai1f0c4362001-12-20 23:13:26 +0000327 if (whineOnErrors) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000328 bb_perror_msg("Mounting %s on %s failed", blockDevice, directory);
Erik Andersene132f4b2000-02-09 04:16:43 +0000329 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000330 return (FALSE);
331 }
332 return (TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000333}
334
Robert Griebld0dd3d32002-07-25 14:17:19 +0000335static void show_mounts(char *onlytype)
Matt Kraai12400822001-04-17 04:32:50 +0000336{
Manuel Novoa III cad53642003-03-19 09:13:01 +0000337 FILE *mountTable = setmntent(bb_path_mtab_file, "r");
Matt Kraai12400822001-04-17 04:32:50 +0000338
339 if (mountTable) {
340 struct mntent *m;
341
342 while ((m = getmntent(mountTable)) != 0) {
343 char *blockDevice = m->mnt_fsname;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000344
Eric Andersen9d7f0f02003-06-20 09:36:49 +0000345 if (strcmp(blockDevice, "rootfs") == 0) {
346 continue;
347 } else if (strcmp(blockDevice, "/dev/root") == 0) {
Eric Andersen93d7fba2004-08-03 00:14:02 +0000348 blockDevice = find_real_root_device_name();
Matt Kraai12400822001-04-17 04:32:50 +0000349 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000350 if (!onlytype || (strcmp(m->mnt_type, onlytype) == 0)) {
Robert Griebld0dd3d32002-07-25 14:17:19 +0000351 printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
352 m->mnt_type, m->mnt_opts);
353 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000354#ifdef CONFIG_FEATURE_CLEAN_UP
Glenn L McGrath8042f652002-08-23 06:17:46 +0000355 if (blockDevice != m->mnt_fsname) {
Eric Andersenc911a432001-05-15 17:42:16 +0000356 free(blockDevice);
Glenn L McGrath8042f652002-08-23 06:17:46 +0000357 }
Eric Andersenc911a432001-05-15 17:42:16 +0000358#endif
Matt Kraai12400822001-04-17 04:32:50 +0000359 }
360 endmntent(mountTable);
361 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000362 bb_perror_msg_and_die(bb_path_mtab_file);
Matt Kraai12400822001-04-17 04:32:50 +0000363 }
364 exit(EXIT_SUCCESS);
Matt Kraai12400822001-04-17 04:32:50 +0000365}
366
Erik Andersene49d5ec2000-02-08 19:58:47 +0000367extern int mount_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000368{
Glenn L McGrath3aae1002001-05-07 01:38:03 +0000369 struct stat statbuf;
Manuel Novoa III cad53642003-03-19 09:13:01 +0000370 char *string_flags = bb_xstrdup("");
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000371 char *extra_opts;
Eric Andersene7413a92000-07-14 06:19:41 +0000372 int flags = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000373 char *filesystemType = "auto";
Robert Griebld0dd3d32002-07-25 14:17:19 +0000374 int got_filesystemType = 0;
Glenn L McGrath3aae1002001-05-07 01:38:03 +0000375 char *device = xmalloc(PATH_MAX);
376 char *directory = xmalloc(PATH_MAX);
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000377 struct mntent *m = NULL;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000378 int all = FALSE;
379 int fakeIt = FALSE;
380 int useMtab = TRUE;
Matt Kraai3e856ce2000-12-01 02:55:13 +0000381 int rc = EXIT_FAILURE;
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000382 FILE *f = 0;
Matt Kraaia3045df2001-04-17 04:48:51 +0000383 int opt;
Eric Andersencc8ed391999-10-05 16:24:54 +0000384
Erik Andersene49d5ec2000-02-08 19:58:47 +0000385 /* Parse options */
Matt Kraaia3045df2001-04-17 04:48:51 +0000386 while ((opt = getopt(argc, argv, "o:rt:wafnv")) > 0) {
387 switch (opt) {
388 case 'o':
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000389 parse_mount_options(optarg, &flags, &string_flags);
Matt Kraaia3045df2001-04-17 04:48:51 +0000390 break;
391 case 'r':
392 flags |= MS_RDONLY;
393 break;
394 case 't':
395 filesystemType = optarg;
Robert Griebld0dd3d32002-07-25 14:17:19 +0000396 got_filesystemType = 1;
Matt Kraaia3045df2001-04-17 04:48:51 +0000397 break;
398 case 'w':
399 flags &= ~MS_RDONLY;
400 break;
401 case 'a':
402 all = TRUE;
403 break;
404 case 'f':
405 fakeIt = TRUE;
406 break;
Matt Kraaia3045df2001-04-17 04:48:51 +0000407 case 'n':
Eric Andersenee4b7d42004-04-12 15:02:53 +0000408#ifdef CONFIG_FEATURE_MTAB_SUPPORT
Matt Kraaia3045df2001-04-17 04:48:51 +0000409 useMtab = FALSE;
Eric Andersena9c95ea1999-11-15 17:33:30 +0000410#endif
Eric Andersenee4b7d42004-04-12 15:02:53 +0000411 break;
Matt Kraaia3045df2001-04-17 04:48:51 +0000412 case 'v':
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000413 break; /* ignore -v */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000414 }
Matt Kraaia3045df2001-04-17 04:48:51 +0000415 }
416
Glenn L McGrath8042f652002-08-23 06:17:46 +0000417 if (!all && (optind == argc)) {
418 show_mounts(got_filesystemType ? filesystemType : NULL);
419 }
Matt Kraai12400822001-04-17 04:32:50 +0000420
Matt Kraaie6bf66e2001-05-04 14:49:58 +0000421 if (optind < argc) {
Glenn L McGrath3aae1002001-05-07 01:38:03 +0000422 /* if device is a filename get its real path */
Glenn L McGrathcc0aa0f2001-05-07 01:51:24 +0000423 if (stat(argv[optind], &statbuf) == 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000424 char *tmp = bb_simplify_path(argv[optind]);
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000425
Eric Andersendefd9982002-04-13 13:47:39 +0000426 safe_strncpy(device, tmp, PATH_MAX);
Glenn L McGrath3aae1002001-05-07 01:38:03 +0000427 } else {
Matt Kraaie6bf66e2001-05-04 14:49:58 +0000428 safe_strncpy(device, argv[optind], PATH_MAX);
Glenn L McGrath3aae1002001-05-07 01:38:03 +0000429 }
Matt Kraaie6bf66e2001-05-04 14:49:58 +0000430 }
Matt Kraai34251112001-05-02 21:17:38 +0000431
Matt Kraaia7cecbc2001-08-10 15:05:27 +0000432 if (optind + 1 < argc)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000433 directory = bb_simplify_path(argv[optind + 1]);
Matt Kraaia7cecbc2001-08-10 15:05:27 +0000434
Matt Kraai1f0c4362001-12-20 23:13:26 +0000435 if (all || optind + 1 == argc) {
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000436 f = setmntent("/etc/fstab", "r");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000437
Erik Andersen246cc6d2000-03-07 07:41:42 +0000438 if (f == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000439 bb_perror_msg_and_die("\nCannot read /etc/fstab");
Erik Andersen246cc6d2000-03-07 07:41:42 +0000440
Erik Andersene49d5ec2000-02-08 19:58:47 +0000441 while ((m = getmntent(f)) != NULL) {
Glenn L McGrath8042f652002-08-23 06:17:46 +0000442 if (!all && (optind + 1 == argc)
443 && ((strcmp(device, m->mnt_fsname) != 0)
444 && (strcmp(device, m->mnt_dir) != 0))) {
Eric Andersenfdd51032000-08-02 18:48:26 +0000445 continue;
446 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000447
448 if (all && ( /* If we're mounting 'all' */
449 (strstr(m->mnt_opts, "noauto")) || /* and the file system isn't noauto, */
Eric Andersen5ef44822003-02-28 06:29:27 +0000450 (strstr(m->mnt_type, "swap")))) /* and isn't swap, then mount it */
451 {
Eric Andersenfdd51032000-08-02 18:48:26 +0000452 continue;
453 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000454
455 if (all || flags == 0) { /* Allow single mount to override fstab flags */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000456 flags = 0;
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000457 string_flags[0] = 0;
458 parse_mount_options(m->mnt_opts, &flags, &string_flags);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000459 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000460
Matt Kraai34251112001-05-02 21:17:38 +0000461 strcpy(device, m->mnt_fsname);
462 strcpy(directory, m->mnt_dir);
Manuel Novoa III cad53642003-03-19 09:13:01 +0000463 filesystemType = bb_xstrdup(m->mnt_type);
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000464 singlemount:
Eric Andersen8b1aa4d2002-06-22 17:20:50 +0000465 extra_opts = string_flags;
Eric Andersend9d03b82000-12-12 23:20:37 +0000466 rc = EXIT_SUCCESS;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000467#ifdef CONFIG_NFSMOUNT
Eric Andersenfcffa2c2002-04-06 05:17:57 +0000468 if (strchr(device, ':') != NULL) {
Pavel Roskin680d65a2000-06-06 17:03:55 +0000469 filesystemType = "nfs";
Glenn L McGrath8042f652002-08-23 06:17:46 +0000470 if (nfsmount
471 (device, directory, &flags, &extra_opts, &string_flags,
472 1)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000473 bb_perror_msg("nfsmount failed");
Matt Kraai3e856ce2000-12-01 02:55:13 +0000474 rc = EXIT_FAILURE;
Eric Andersenfdd51032000-08-02 18:48:26 +0000475 }
Eric Andersen252bacc2000-09-19 01:21:13 +0000476 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000477#endif
Glenn L McGrath8042f652002-08-23 06:17:46 +0000478 if (!mount_one
479 (device, directory, filesystemType, flags, string_flags,
480 useMtab, fakeIt, extra_opts, TRUE, all)) {
Matt Kraai92ed8a32000-12-06 15:55:23 +0000481 rc = EXIT_FAILURE;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000482 }
483 if (!all) {
Eric Andersenfdd51032000-08-02 18:48:26 +0000484 break;
Glenn L McGrath8042f652002-08-23 06:17:46 +0000485 }
Eric Andersenfdd51032000-08-02 18:48:26 +0000486 }
Glenn L McGrath8042f652002-08-23 06:17:46 +0000487 if (f) {
Eric Andersenfdd51032000-08-02 18:48:26 +0000488 endmntent(f);
Glenn L McGrath8042f652002-08-23 06:17:46 +0000489 }
490 if (!all && f && m == NULL) {
Eric Andersenfdd51032000-08-02 18:48:26 +0000491 fprintf(stderr, "Can't find %s in /etc/fstab\n", device);
Glenn L McGrath8042f652002-08-23 06:17:46 +0000492 }
Matt Kraai93ba60f2001-02-28 15:33:12 +0000493 return rc;
Eric Andersenfdd51032000-08-02 18:48:26 +0000494 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000495
Eric Andersenfdd51032000-08-02 18:48:26 +0000496 goto singlemount;
Eric Andersencc8ed391999-10-05 16:24:54 +0000497}