blob: a7d5aed2d46b196b8d76f3fa2e097b0c24b0c0b5 [file] [log] [blame]
Eric Andersencc8ed391999-10-05 16:24:54 +00001/*
Eric Andersen596e5461999-10-07 08:30:23 +00002 * Mini mount implementation for busybox
3 *
4 * Copyright (C) 1999 by Erik Andersen <andersee@debian.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * 3/21/1999 Charles P. Wright <cpwright@cpwright.com>
21 * searches through fstab when -a is passed
22 * will try mounting stuff with all fses when passed -t auto
23 *
24 * 1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab.
Eric Andersen8341a151999-10-08 17:14:14 +000025 * 1999-10-07 Erik Andersen. Rewrote of a lot of code. Removed mtab
26 * usage, major adjustments, and some serious dieting all around.
Eric Andersencc8ed391999-10-05 16:24:54 +000027*/
28
29#include "internal.h"
30#include <stdlib.h>
31#include <unistd.h>
32#include <errno.h>
33#include <string.h>
34#include <stdio.h>
35#include <mntent.h>
36#include <sys/mount.h>
37#include <ctype.h>
Eric Andersen596e5461999-10-07 08:30:23 +000038#include <fstab.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000039
Eric Andersene77ae3a1999-10-19 20:03:34 +000040static const char mount_usage[] = "Usage:\tmount [flags]\n"
Eric Andersen596e5461999-10-07 08:30:23 +000041 "\tmount [flags] device directory [-o options,more-options]\n"
42 "\n"
43 "Flags:\n"
44 "\t-a:\tMount all file systems in fstab.\n"
45 "\t-o option:\tOne of many filesystem options, listed below.\n"
46 "\t-r:\tMount the filesystem read-only.\n"
47 "\t-t filesystem-type:\tSpecify the filesystem type.\n"
48 "\t-w:\tMount for reading and writing (default).\n"
49 "\n"
50 "Options for use with the \"-o\" flag:\n"
51 "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
52 "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
53 "\texec / noexec:\tAllow use of executable files / disallow them.\n"
54 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
55 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
56 "\tro / rw: Mount for read-only / read-write.\n"
57 "\t"
58 "There are EVEN MORE flags that are specific to each filesystem.\n"
59 "You'll have to see the written documentation for those.\n";
Eric Andersencc8ed391999-10-05 16:24:54 +000060
61struct mount_options {
Eric Andersen596e5461999-10-07 08:30:23 +000062 const char *name;
63 unsigned long and;
64 unsigned long or;
Eric Andersencc8ed391999-10-05 16:24:54 +000065};
66
Eric Andersen596e5461999-10-07 08:30:23 +000067static const struct mount_options mount_options[] = {
68 {"async", ~MS_SYNCHRONOUS, 0},
69 {"defaults", ~0, 0},
70 {"dev", ~MS_NODEV, 0},
71 {"exec", ~MS_NOEXEC, 0},
72 {"nodev", ~0, MS_NODEV},
73 {"noexec", ~0, MS_NOEXEC},
74 {"nosuid", ~0, MS_NOSUID},
75 {"remount", ~0, MS_REMOUNT},
76 {"ro", ~0, MS_RDONLY},
77 {"rw", ~MS_RDONLY, 0},
78 {"suid", ~MS_NOSUID, 0},
79 {"sync", ~0, MS_SYNCHRONOUS},
80 {0, 0, 0}
Eric Andersencc8ed391999-10-05 16:24:54 +000081};
82
Eric Andersencc8ed391999-10-05 16:24:54 +000083
Eric Andersen8341a151999-10-08 17:14:14 +000084/* Seperate standard mount options from the nonstandard string options */
Eric Andersencc8ed391999-10-05 16:24:54 +000085static void
Eric Andersen8341a151999-10-08 17:14:14 +000086parse_mount_options ( char *options, unsigned long *flags, char *strflags)
Eric Andersencc8ed391999-10-05 16:24:54 +000087{
Eric Andersen8341a151999-10-08 17:14:14 +000088 while (options) {
89 int gotone=FALSE;
Eric Andersen596e5461999-10-07 08:30:23 +000090 char *comma = strchr (options, ',');
91 const struct mount_options* f = mount_options;
92 if (comma)
93 *comma = '\0';
Eric Andersencc8ed391999-10-05 16:24:54 +000094
Eric Andersen596e5461999-10-07 08:30:23 +000095 while (f->name != 0) {
Eric Andersen596e5461999-10-07 08:30:23 +000096 if (strcasecmp (f->name, options) == 0) {
97 *flags &= f->and;
98 *flags |= f->or;
Eric Andersen8341a151999-10-08 17:14:14 +000099 gotone=TRUE;
100 break;
Eric Andersen596e5461999-10-07 08:30:23 +0000101 }
102 f++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000103 }
Eric Andersen8341a151999-10-08 17:14:14 +0000104 if (*strflags && strflags!= '\0' && gotone==FALSE) {
105 char *temp=strflags;
106 temp += strlen (strflags);
107 *temp++ = ',';
108 *temp++ = '\0';
Eric Andersencc8ed391999-10-05 16:24:54 +0000109 }
Eric Andersen8341a151999-10-08 17:14:14 +0000110 if (gotone==FALSE) {
111 strcat (strflags, options);
112 gotone=FALSE;
113 }
Eric Andersen596e5461999-10-07 08:30:23 +0000114 if (comma) {
115 *comma = ',';
116 options = ++comma;
Eric Andersen8341a151999-10-08 17:14:14 +0000117 } else {
Eric Andersen596e5461999-10-07 08:30:23 +0000118 break;
Eric Andersen8341a151999-10-08 17:14:14 +0000119 }
Eric Andersen596e5461999-10-07 08:30:23 +0000120 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000121}
122
123int
Eric Andersen596e5461999-10-07 08:30:23 +0000124mount_one (
125 char *blockDevice, char *directory, char *filesystemType,
126 unsigned long flags, char *string_flags)
Eric Andersencc8ed391999-10-05 16:24:54 +0000127{
Eric Andersen596e5461999-10-07 08:30:23 +0000128 int status = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000129
Eric Andersen596e5461999-10-07 08:30:23 +0000130 char buf[255];
Eric Andersencc8ed391999-10-05 16:24:54 +0000131
Eric Andersen596e5461999-10-07 08:30:23 +0000132 if (strcmp(filesystemType, "auto") == 0) {
133 FILE *f = fopen ("/proc/filesystems", "r");
Eric Andersencc8ed391999-10-05 16:24:54 +0000134
Eric Andersen596e5461999-10-07 08:30:23 +0000135 if (f == NULL)
136 return( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000137
Eric Andersen596e5461999-10-07 08:30:23 +0000138 while (fgets (buf, sizeof (buf), f) != NULL) {
139 filesystemType = buf;
140 if (*filesystemType == '\t') { // Not a nodev filesystem
Eric Andersencc8ed391999-10-05 16:24:54 +0000141
Eric Andersen596e5461999-10-07 08:30:23 +0000142 // Add NULL termination to each line
143 while (*filesystemType && *filesystemType != '\n')
144 filesystemType++;
145 *filesystemType = '\0';
Eric Andersencc8ed391999-10-05 16:24:54 +0000146
Eric Andersen596e5461999-10-07 08:30:23 +0000147 filesystemType = buf;
148 filesystemType++; // hop past tab
149
150 status = mount (blockDevice, directory, filesystemType,
151 flags | MS_MGC_VAL, string_flags);
152 if (status == 0)
153 break;
154 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000155 }
Eric Andersen596e5461999-10-07 08:30:23 +0000156 fclose (f);
157 } else {
158 status = mount (blockDevice, directory, filesystemType,
159 flags | MS_MGC_VAL, string_flags);
160 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000161
Eric Andersen596e5461999-10-07 08:30:23 +0000162 if (status) {
163 fprintf (stderr, "Mounting %s on %s failed: %s\n",
164 blockDevice, directory, strerror(errno));
165 return (FALSE);
166 }
167 return (TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000168}
169
Eric Andersen596e5461999-10-07 08:30:23 +0000170extern int mount_main (int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000171{
Eric Andersen8341a151999-10-08 17:14:14 +0000172 char string_flags[1024]="";
Eric Andersen596e5461999-10-07 08:30:23 +0000173 unsigned long flags = 0;
174 char *filesystemType = "auto";
Eric Andersen8341a151999-10-08 17:14:14 +0000175 char *device = NULL;
176 char *directory = NULL;
Eric Andersencb6e2561999-10-16 15:48:40 +0000177 struct stat statBuf;
Eric Andersen596e5461999-10-07 08:30:23 +0000178 int all = 0;
Eric Andersen8341a151999-10-08 17:14:14 +0000179 int i;
Eric Andersencc8ed391999-10-05 16:24:54 +0000180
Eric Andersencb6e2561999-10-16 15:48:40 +0000181 if (stat("/etc/fstab", &statBuf) < 0)
182 fprintf(stderr, "/etc/fstab file missing -- Please install one.\n\n");
183
Eric Andersen596e5461999-10-07 08:30:23 +0000184 if (argc == 1) {
185 FILE *mountTable;
186 if ((mountTable = setmntent ("/proc/mounts", "r"))) {
187 struct mntent *m;
188 while ((m = getmntent (mountTable)) != 0) {
Eric Andersencb6e2561999-10-16 15:48:40 +0000189 struct fstab* fstabItem;
Eric Andersen596e5461999-10-07 08:30:23 +0000190 char *blockDevice = m->mnt_fsname;
Eric Andersencb6e2561999-10-16 15:48:40 +0000191 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
192 if (strcmp (blockDevice, "/dev/root") == 0) {
193 fstabItem = getfsfile ("/");
194 if (fstabItem != NULL)
195 blockDevice = fstabItem->fs_spec;
196 }
Eric Andersen596e5461999-10-07 08:30:23 +0000197 printf ("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
198 m->mnt_type, m->mnt_opts);
199 }
200 endmntent (mountTable);
Eric Andersencc8ed391999-10-05 16:24:54 +0000201 }
Eric Andersen3c163821999-10-14 22:16:57 +0000202 exit( TRUE);
Eric Andersen596e5461999-10-07 08:30:23 +0000203 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000204
Eric Andersen596e5461999-10-07 08:30:23 +0000205
206 /* Parse options */
Eric Andersen8341a151999-10-08 17:14:14 +0000207 i = --argc;
208 argv++;
209 while (i > 0 && **argv) {
Eric Andersen596e5461999-10-07 08:30:23 +0000210 if (**argv == '-') {
Eric Andersen8341a151999-10-08 17:14:14 +0000211 while (i>0 && *++(*argv)) switch (**argv) {
Eric Andersen596e5461999-10-07 08:30:23 +0000212 case 'o':
Eric Andersen8341a151999-10-08 17:14:14 +0000213 if (--i == 0) {
Eric Andersen596e5461999-10-07 08:30:23 +0000214 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000215 exit( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000216 }
Eric Andersen8341a151999-10-08 17:14:14 +0000217 parse_mount_options (*(++argv), &flags, string_flags);
218 --i;
219 ++argv;
Eric Andersen596e5461999-10-07 08:30:23 +0000220 break;
221 case 'r':
222 flags |= MS_RDONLY;
223 break;
224 case 't':
Eric Andersen8341a151999-10-08 17:14:14 +0000225 if (--i == 0) {
Eric Andersen596e5461999-10-07 08:30:23 +0000226 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000227 exit( FALSE);
Eric Andersen596e5461999-10-07 08:30:23 +0000228 }
Eric Andersen8341a151999-10-08 17:14:14 +0000229 filesystemType = *(++argv);
230 --i;
231 ++argv;
Eric Andersen596e5461999-10-07 08:30:23 +0000232 break;
233 case 'w':
234 flags &= ~MS_RDONLY;
235 break;
236 case 'a':
237 all = 1;
238 break;
239 case 'v':
240 case 'h':
241 case '-':
242 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000243 exit( TRUE);
Eric Andersen8341a151999-10-08 17:14:14 +0000244 break;
245 }
246 } else {
247 if (device == NULL)
248 device=*argv;
249 else if (directory == NULL)
250 directory=*argv;
251 else {
252 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000253 exit( TRUE);
Eric Andersen596e5461999-10-07 08:30:23 +0000254 }
255 }
256 i--;
257 argv++;
258 }
259
260 if (all == 1) {
261 struct mntent *m;
262 FILE *f = setmntent ("/etc/fstab", "r");
263
264 if (f == NULL) {
265 perror("/etc/fstab");
Eric Andersen3c163821999-10-14 22:16:57 +0000266 exit( FALSE);
Eric Andersen596e5461999-10-07 08:30:23 +0000267 }
Eric Andersen596e5461999-10-07 08:30:23 +0000268 while ((m = getmntent (f)) != NULL) {
269 // If the file system isn't noauto, and isn't mounted on /, mount
270 // it
271 if ((!strstr (m->mnt_opts, "noauto"))
272 && (m->mnt_dir[1] != '\0') && !((m->mnt_type[0] == 's')
273 && (m->mnt_type[1] == 'w'))
274 && !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) {
275 mount_one (m->mnt_fsname, m->mnt_dir, m->mnt_type, flags,
276 m->mnt_opts);
277 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000278 }
Eric Andersen596e5461999-10-07 08:30:23 +0000279 endmntent (f);
280 } else {
Eric Andersen8341a151999-10-08 17:14:14 +0000281 if (device && directory) {
Eric Andersen3c163821999-10-14 22:16:57 +0000282 exit (mount_one (device, directory, filesystemType,
Eric Andersen8341a151999-10-08 17:14:14 +0000283 flags, string_flags));
Eric Andersencc8ed391999-10-05 16:24:54 +0000284 } else {
Eric Andersen596e5461999-10-07 08:30:23 +0000285 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000286 exit( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000287 }
Eric Andersen596e5461999-10-07 08:30:23 +0000288 }
Eric Andersen3c163821999-10-14 22:16:57 +0000289 exit( TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000290}