blob: d7b2682ced75076eb1fe71b58774e59ad367ba90 [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 Andersen596e5461999-10-07 08:30:23 +000040const char mount_usage[] = "Usage:\tmount [flags]\n"
41 "\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 Andersen596e5461999-10-07 08:30:23 +0000177 int all = 0;
Eric Andersen8341a151999-10-08 17:14:14 +0000178 int i;
Eric Andersencc8ed391999-10-05 16:24:54 +0000179
Eric Andersen596e5461999-10-07 08:30:23 +0000180 if (argc == 1) {
181 FILE *mountTable;
182 if ((mountTable = setmntent ("/proc/mounts", "r"))) {
183 struct mntent *m;
184 while ((m = getmntent (mountTable)) != 0) {
185 char *blockDevice = m->mnt_fsname;
186 if (strcmp (blockDevice, "/dev/root") == 0)
187 blockDevice = (getfsfile ("/"))->fs_spec;
188 printf ("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
189 m->mnt_type, m->mnt_opts);
190 }
191 endmntent (mountTable);
Eric Andersencc8ed391999-10-05 16:24:54 +0000192 }
Eric Andersen3c163821999-10-14 22:16:57 +0000193 exit( TRUE);
Eric Andersen596e5461999-10-07 08:30:23 +0000194 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000195
Eric Andersen596e5461999-10-07 08:30:23 +0000196
197 /* Parse options */
Eric Andersen8341a151999-10-08 17:14:14 +0000198 i = --argc;
199 argv++;
200 while (i > 0 && **argv) {
Eric Andersen596e5461999-10-07 08:30:23 +0000201 if (**argv == '-') {
Eric Andersen8341a151999-10-08 17:14:14 +0000202 while (i>0 && *++(*argv)) switch (**argv) {
Eric Andersen596e5461999-10-07 08:30:23 +0000203 case 'o':
Eric Andersen8341a151999-10-08 17:14:14 +0000204 if (--i == 0) {
Eric Andersen596e5461999-10-07 08:30:23 +0000205 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000206 exit( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000207 }
Eric Andersen8341a151999-10-08 17:14:14 +0000208 parse_mount_options (*(++argv), &flags, string_flags);
209 --i;
210 ++argv;
Eric Andersen596e5461999-10-07 08:30:23 +0000211 break;
212 case 'r':
213 flags |= MS_RDONLY;
214 break;
215 case 't':
Eric Andersen8341a151999-10-08 17:14:14 +0000216 if (--i == 0) {
Eric Andersen596e5461999-10-07 08:30:23 +0000217 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000218 exit( FALSE);
Eric Andersen596e5461999-10-07 08:30:23 +0000219 }
Eric Andersen8341a151999-10-08 17:14:14 +0000220 filesystemType = *(++argv);
221 --i;
222 ++argv;
Eric Andersen596e5461999-10-07 08:30:23 +0000223 break;
224 case 'w':
225 flags &= ~MS_RDONLY;
226 break;
227 case 'a':
228 all = 1;
229 break;
230 case 'v':
231 case 'h':
232 case '-':
233 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000234 exit( TRUE);
Eric Andersen8341a151999-10-08 17:14:14 +0000235 break;
236 }
237 } else {
238 if (device == NULL)
239 device=*argv;
240 else if (directory == NULL)
241 directory=*argv;
242 else {
243 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000244 exit( TRUE);
Eric Andersen596e5461999-10-07 08:30:23 +0000245 }
246 }
247 i--;
248 argv++;
249 }
250
251 if (all == 1) {
252 struct mntent *m;
253 FILE *f = setmntent ("/etc/fstab", "r");
254
255 if (f == NULL) {
256 perror("/etc/fstab");
Eric Andersen3c163821999-10-14 22:16:57 +0000257 exit( FALSE);
Eric Andersen596e5461999-10-07 08:30:23 +0000258 }
Eric Andersen596e5461999-10-07 08:30:23 +0000259 while ((m = getmntent (f)) != NULL) {
260 // If the file system isn't noauto, and isn't mounted on /, mount
261 // it
262 if ((!strstr (m->mnt_opts, "noauto"))
263 && (m->mnt_dir[1] != '\0') && !((m->mnt_type[0] == 's')
264 && (m->mnt_type[1] == 'w'))
265 && !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) {
266 mount_one (m->mnt_fsname, m->mnt_dir, m->mnt_type, flags,
267 m->mnt_opts);
268 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000269 }
Eric Andersen596e5461999-10-07 08:30:23 +0000270 endmntent (f);
271 } else {
Eric Andersen8341a151999-10-08 17:14:14 +0000272 if (device && directory) {
Eric Andersen3c163821999-10-14 22:16:57 +0000273 exit (mount_one (device, directory, filesystemType,
Eric Andersen8341a151999-10-08 17:14:14 +0000274 flags, string_flags));
Eric Andersencc8ed391999-10-05 16:24:54 +0000275 } else {
Eric Andersen596e5461999-10-07 08:30:23 +0000276 fprintf (stderr, "%s\n", mount_usage);
Eric Andersen3c163821999-10-14 22:16:57 +0000277 exit( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000278 }
Eric Andersen596e5461999-10-07 08:30:23 +0000279 }
Eric Andersen3c163821999-10-14 22:16:57 +0000280 exit( TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000281}