aboutsummaryrefslogtreecommitdiff
path: root/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'mount.c')
-rw-r--r--mount.c581
1 files changed, 298 insertions, 283 deletions
diff --git a/mount.c b/mount.c
index 4c9e77be0..c3e3bbd75 100644
--- a/mount.c
+++ b/mount.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini mount implementation for busybox 3 * Mini mount implementation for busybox
3 * 4 *
@@ -55,357 +56,371 @@
55static int use_loop = 0; 56static int use_loop = 0;
56#endif 57#endif
57 58
58extern const char mtab_file[]; /* Defined in utility.c */ 59extern const char mtab_file[]; /* Defined in utility.c */
59 60
60static const char mount_usage[] = "\tmount [flags]\n" 61static const char mount_usage[] = "\tmount [flags]\n"
61 "\tmount [flags] device directory [-o options,more-options]\n" 62 "\tmount [flags] device directory [-o options,more-options]\n"
62 "\n" 63 "\n" "Flags:\n" "\t-a:\tMount all file systems in fstab.\n"
63 "Flags:\n"
64 "\t-a:\tMount all file systems in fstab.\n"
65#ifdef BB_MTAB 64#ifdef BB_MTAB
66 "\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n" 65 "\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n"
67 "\t-n:\tDon't write a mount table entry.\n" 66 "\t-n:\tDon't write a mount table entry.\n"
68#endif 67#endif
69 "\t-o option:\tOne of many filesystem options, listed below.\n" 68 "\t-o option:\tOne of many filesystem options, listed below.\n"
70 "\t-r:\tMount the filesystem read-only.\n" 69 "\t-r:\tMount the filesystem read-only.\n"
71 "\t-t filesystem-type:\tSpecify the filesystem type.\n" 70 "\t-t filesystem-type:\tSpecify the filesystem type.\n"
72 "\t-w:\tMount for reading and writing (default).\n" 71 "\t-w:\tMount for reading and writing (default).\n"
73 "\n" 72 "\n"
74 "Options for use with the \"-o\" flag:\n" 73 "Options for use with the \"-o\" flag:\n"
75 "\tasync / sync:\tWrites are asynchronous / synchronous.\n" 74 "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
76 "\tdev / nodev:\tAllow use of special device files / disallow them.\n" 75 "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
77 "\texec / noexec:\tAllow use of executable files / disallow them.\n" 76 "\texec / noexec:\tAllow use of executable files / disallow them.\n"
78#if defined BB_FEATURE_MOUNT_LOOP 77#if defined BB_FEATURE_MOUNT_LOOP
79 "\tloop: Mounts a file via loop device.\n" 78 "\tloop: Mounts a file via loop device.\n"
80#endif 79#endif
81 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" 80 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
82 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" 81 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
83 "\tro / rw: Mount for read-only / read-write.\n" 82 "\tro / rw: Mount for read-only / read-write.\n"
84 "\t" 83 "\t"
85 "There are EVEN MORE flags that are specific to each filesystem.\n" 84
86 "You'll have to see the written documentation for those.\n"; 85 "There are EVEN MORE flags that are specific to each filesystem.\n"
86 "You'll have to see the written documentation for those.\n";
87 87
88 88
89struct mount_options { 89struct mount_options {
90 const char *name; 90 const char *name;
91 unsigned long and; 91 unsigned long and;
92 unsigned long or; 92 unsigned long or;
93}; 93};
94 94
95static const struct mount_options mount_options[] = { 95static const struct mount_options mount_options[] = {
96 {"async", ~MS_SYNCHRONOUS, 0}, 96 {"async", ~MS_SYNCHRONOUS, 0},
97 {"defaults", ~0, 0}, 97 {"defaults", ~0, 0},
98 {"dev", ~MS_NODEV, 0}, 98 {"dev", ~MS_NODEV, 0},
99 {"exec", ~MS_NOEXEC, 0}, 99 {"exec", ~MS_NOEXEC, 0},
100 {"nodev", ~0, MS_NODEV}, 100 {"nodev", ~0, MS_NODEV},
101 {"noexec", ~0, MS_NOEXEC}, 101 {"noexec", ~0, MS_NOEXEC},
102 {"nosuid", ~0, MS_NOSUID}, 102 {"nosuid", ~0, MS_NOSUID},
103 {"remount", ~0, MS_REMOUNT}, 103 {"remount", ~0, MS_REMOUNT},
104 {"ro", ~0, MS_RDONLY}, 104 {"ro", ~0, MS_RDONLY},
105 {"rw", ~MS_RDONLY, 0}, 105 {"rw", ~MS_RDONLY, 0},
106 {"suid", ~MS_NOSUID, 0}, 106 {"suid", ~MS_NOSUID, 0},
107 {"sync", ~0, MS_SYNCHRONOUS}, 107 {"sync", ~0, MS_SYNCHRONOUS},
108 {0, 0, 0} 108 {0, 0, 0}
109}; 109};
110 110
111static int 111static int
112do_mount(char* specialfile, char* dir, char* filesystemtype, 112do_mount(char *specialfile, char *dir, char *filesystemtype,
113 long flags, void* string_flags, int useMtab, int fakeIt, char* mtab_opts) 113 long flags, void *string_flags, int useMtab, int fakeIt,
114 char *mtab_opts)
114{ 115{
115 int status=0; 116 int status = 0;
116 117
117#if defined BB_MTAB 118#if defined BB_MTAB
118 if (fakeIt==FALSE) 119 if (fakeIt == FALSE)
119#endif 120#endif
120 { 121 {
121#if defined BB_FEATURE_MOUNT_LOOP 122#if defined BB_FEATURE_MOUNT_LOOP
122 if (use_loop) { 123 if (use_loop) {
123 int loro = flags & MS_RDONLY; 124 int loro = flags & MS_RDONLY;
124 char *lofile = specialfile; 125 char *lofile = specialfile;
125 specialfile = find_unused_loop_device(); 126
126 if (specialfile == NULL) { 127 specialfile = find_unused_loop_device();
127 fprintf(stderr, "Could not find a spare loop device\n"); 128 if (specialfile == NULL) {
128 return( FALSE); 129 fprintf(stderr, "Could not find a spare loop device\n");
129 } 130 return (FALSE);
130 if (set_loop (specialfile, lofile, 0, &loro)) { 131 }
131 fprintf(stderr, "Could not setup loop device\n"); 132 if (set_loop(specialfile, lofile, 0, &loro)) {
132 return( FALSE); 133 fprintf(stderr, "Could not setup loop device\n");
133 } 134 return (FALSE);
134 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ 135 }
135 fprintf(stderr, "WARNING: loop device is read-only\n"); 136 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
136 flags &= ~MS_RDONLY; 137 fprintf(stderr, "WARNING: loop device is read-only\n");
137 } 138 flags &= ~MS_RDONLY;
138 } 139 }
140 }
139#endif 141#endif
140 status=mount(specialfile, dir, filesystemtype, flags, string_flags); 142 status =
141 } 143 mount(specialfile, dir, filesystemtype, flags, string_flags);
144 }
142 145
143 146
144 /* If the mount was sucessful, do anything needed, then return TRUE */ 147 /* If the mount was sucessful, do anything needed, then return TRUE */
145 if (status == 0) { 148 if (status == 0) {
146 149
147#if defined BB_MTAB 150#if defined BB_MTAB
148 if (useMtab==TRUE) { 151 if (useMtab == TRUE) {
149 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); 152 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
150 } 153 }
151#endif 154#endif
152 return( TRUE); 155 return (TRUE);
153 } 156 }
154 157
155 /* Bummer. mount failed. Clean up */ 158 /* Bummer. mount failed. Clean up */
156#if defined BB_FEATURE_MOUNT_LOOP 159#if defined BB_FEATURE_MOUNT_LOOP
157 if (specialfile != NULL) { 160 if (specialfile != NULL) {
158 del_loop(specialfile); 161 del_loop(specialfile);
159 } 162 }
160#endif 163#endif
161 return( FALSE); 164 return (FALSE);
162} 165}
163 166
164 167
165 168
166#if defined BB_MTAB 169#if defined BB_MTAB
167#define whine_if_fstab_is_missing() {} 170#define whine_if_fstab_is_missing() {}
168#else 171#else
169extern void whine_if_fstab_is_missing() 172extern void whine_if_fstab_is_missing()
170{ 173{
171 struct stat statBuf; 174 struct stat statBuf;
172 if (stat("/etc/fstab", &statBuf) < 0) 175
173 fprintf(stderr, "/etc/fstab file missing -- install one to name /dev/root.\n\n"); 176 if (stat("/etc/fstab", &statBuf) < 0)
177 fprintf(stderr,
178 "/etc/fstab file missing -- install one to name /dev/root.\n\n");
174} 179}
175#endif 180#endif
176 181
177 182
178/* Seperate standard mount options from the nonstandard string options */ 183/* Seperate standard mount options from the nonstandard string options */
179static void 184static void
180parse_mount_options ( char *options, unsigned long *flags, char *strflags) 185parse_mount_options(char *options, unsigned long *flags, char *strflags)
181{ 186{
182 while (options) { 187 while (options) {
183 int gotone=FALSE; 188 int gotone = FALSE;
184 char *comma = strchr (options, ','); 189 char *comma = strchr(options, ',');
185 const struct mount_options* f = mount_options; 190 const struct mount_options *f = mount_options;
186 if (comma) 191
187 *comma = '\0'; 192 if (comma)
188 193 *comma = '\0';
189 while (f->name != 0) { 194
190 if (strcasecmp (f->name, options) == 0) { 195 while (f->name != 0) {
191 196 if (strcasecmp(f->name, options) == 0) {
192 *flags &= f->and; 197
193 *flags |= f->or; 198 *flags &= f->and;
194 gotone=TRUE; 199 *flags |= f->or;
195 break; 200 gotone = TRUE;
196 } 201 break;
197 f++; 202 }
198 } 203 f++;
204 }
199#if defined BB_FEATURE_MOUNT_LOOP 205#if defined BB_FEATURE_MOUNT_LOOP
200 if (gotone==FALSE && !strcasecmp ("loop", options)) { /* loop device support */ 206 if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */
201 use_loop = 1; 207 use_loop = 1;
202 gotone=TRUE; 208 gotone = TRUE;
203 } 209 }
204#endif 210#endif
205 if (*strflags && strflags!= '\0' && gotone==FALSE) { 211 if (*strflags && strflags != '\0' && gotone == FALSE) {
206 char *temp=strflags; 212 char *temp = strflags;
207 temp += strlen (strflags); 213
208 *temp++ = ','; 214 temp += strlen(strflags);
209 *temp++ = '\0'; 215 *temp++ = ',';
210 } 216 *temp++ = '\0';
211 if (gotone==FALSE) 217 }
212 strcat (strflags, options); 218 if (gotone == FALSE)
213 if (comma) { 219 strcat(strflags, options);
214 *comma = ','; 220 if (comma) {
215 options = ++comma; 221 *comma = ',';
216 } else { 222 options = ++comma;
217 break; 223 } else {
224 break;
225 }
218 } 226 }
219 }
220} 227}
221 228
222int 229int
223mount_one(char *blockDevice, char *directory, char *filesystemType, 230mount_one(char *blockDevice, char *directory, char *filesystemType,
224 unsigned long flags, char *string_flags, int useMtab, int fakeIt, char *mtab_opts) 231 unsigned long flags, char *string_flags, int useMtab, int fakeIt,
232 char *mtab_opts)
225{ 233{
226 int status = 0; 234 int status = 0;
227 235
228 char buf[255]; 236 char buf[255];
229 237
230#if defined BB_FEATURE_USE_PROCFS 238#if defined BB_FEATURE_USE_PROCFS
231 if (strcmp(filesystemType, "auto") == 0) { 239 if (strcmp(filesystemType, "auto") == 0) {
232 FILE *f = fopen ("/proc/filesystems", "r"); 240 FILE *f = fopen("/proc/filesystems", "r");
233 241
234 if (f == NULL) 242 if (f == NULL)
235 return( FALSE); 243 return (FALSE);
236 244
237 while (fgets (buf, sizeof (buf), f) != NULL) { 245 while (fgets(buf, sizeof(buf), f) != NULL) {
238 filesystemType = buf; 246 filesystemType = buf;
239 if (*filesystemType == '\t') { // Not a nodev filesystem 247 if (*filesystemType == '\t') { // Not a nodev filesystem
240 248
241 // Add NULL termination to each line 249 // Add NULL termination to each line
242 while (*filesystemType && *filesystemType != '\n') 250 while (*filesystemType && *filesystemType != '\n')
243 filesystemType++; 251 filesystemType++;
244 *filesystemType = '\0'; 252 *filesystemType = '\0';
245 253
246 filesystemType = buf; 254 filesystemType = buf;
247 filesystemType++; // hop past tab 255 filesystemType++; // hop past tab
248 256
249 status = do_mount (blockDevice, directory, filesystemType, 257 status = do_mount(blockDevice, directory, filesystemType,
250 flags | MS_MGC_VAL, string_flags, useMtab, 258 flags | MS_MGC_VAL, string_flags,
251 fakeIt, mtab_opts); 259 useMtab, fakeIt, mtab_opts);
252 if (status == TRUE) 260 if (status == TRUE)
253 break; 261 break;
254 } 262 }
255 } 263 }
256 fclose (f); 264 fclose(f);
257 } else 265 } else
258#endif 266#endif
259 { 267 {
260 status = do_mount (blockDevice, directory, filesystemType, 268 status = do_mount(blockDevice, directory, filesystemType,
261 flags | MS_MGC_VAL, string_flags, useMtab, 269 flags | MS_MGC_VAL, string_flags, useMtab,
262 fakeIt, mtab_opts); 270 fakeIt, mtab_opts);
263 } 271 }
264 272
265 if (status==FALSE) { 273 if (status == FALSE) {
266 fprintf (stderr, "Mounting %s on %s failed: %s\n", 274 fprintf(stderr, "Mounting %s on %s failed: %s\n",
267 blockDevice, directory, strerror(errno)); 275 blockDevice, directory, strerror(errno));
268 return (FALSE); 276 return (FALSE);
269 } 277 }
270 return (TRUE); 278 return (TRUE);
271} 279}
272 280
273extern int mount_main (int argc, char **argv) 281extern int mount_main(int argc, char **argv)
274{ 282{
275 char string_flags_buf[1024]=""; 283 char string_flags_buf[1024] = "";
276 char *string_flags = string_flags_buf; 284 char *string_flags = string_flags_buf;
277 char *extra_opts = string_flags_buf; 285 char *extra_opts = string_flags_buf;
278 unsigned long flags = 0; 286 unsigned long flags = 0;
279 char *filesystemType = "auto"; 287 char *filesystemType = "auto";
280 char *device = NULL; 288 char *device = NULL;
281 char *directory = NULL; 289 char *directory = NULL;
282 int all = FALSE; 290 int all = FALSE;
283 int fakeIt = FALSE; 291 int fakeIt = FALSE;
284 int useMtab = TRUE; 292 int useMtab = TRUE;
285 int i; 293 int i;
286 294
287 /* Only compiled in if BB_MTAB is not defined */ 295 /* Only compiled in if BB_MTAB is not defined */
288 whine_if_fstab_is_missing(); 296 whine_if_fstab_is_missing();
289 297
290 if (argc == 1) { 298 if (argc == 1) {
291 FILE *mountTable = setmntent (mtab_file, "r"); 299 FILE *mountTable = setmntent(mtab_file, "r");
292 if (mountTable) { 300
293 struct mntent *m; 301 if (mountTable) {
294 while ((m = getmntent (mountTable)) != 0) { 302 struct mntent *m;
295 struct fstab* fstabItem; 303
296 char *blockDevice = m->mnt_fsname; 304 while ((m = getmntent(mountTable)) != 0) {
297 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */ 305 struct fstab *fstabItem;
298 if (strcmp (blockDevice, "/dev/root") == 0) { 306 char *blockDevice = m->mnt_fsname;
299 fstabItem = getfsfile ("/"); 307
300 if (fstabItem != NULL) 308 /* Note that if /etc/fstab is missing, libc can't fix up /dev/root for us */
301 blockDevice = fstabItem->fs_spec; 309 if (strcmp(blockDevice, "/dev/root") == 0) {
310 fstabItem = getfsfile("/");
311 if (fstabItem != NULL)
312 blockDevice = fstabItem->fs_spec;
313 }
314 printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir,
315 m->mnt_type, m->mnt_opts);
316 }
317 endmntent(mountTable);
318 } else {
319 perror(mtab_file);
302 } 320 }
303 printf ("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, 321 exit(TRUE);
304 m->mnt_type, m->mnt_opts);
305 }
306 endmntent (mountTable);
307 } else {
308 perror(mtab_file);
309 } 322 }
310 exit( TRUE); 323
311 } 324
312 325 /* Parse options */
313 326 i = --argc;
314 /* Parse options */ 327 argv++;
315 i = --argc; 328 while (i > 0 && **argv) {
316 argv++; 329 if (**argv == '-') {
317 while (i > 0 && **argv) { 330 char *opt = *argv;
318 if (**argv == '-') { 331
319 char *opt = *argv; 332 while (i > 0 && *++opt)
320 while (i>0 && *++opt) switch (*opt) { 333 switch (*opt) {
321 case 'o': 334 case 'o':
322 if (--i == 0) { 335 if (--i == 0) {
323 goto goodbye; 336 goto goodbye;
324 } 337 }
325 parse_mount_options (*(++argv), &flags, string_flags); 338 parse_mount_options(*(++argv), &flags, string_flags);
326 break; 339 break;
327 case 'r': 340 case 'r':
328 flags |= MS_RDONLY; 341 flags |= MS_RDONLY;
329 break; 342 break;
330 case 't': 343 case 't':
331 if (--i == 0) { 344 if (--i == 0) {
332 goto goodbye; 345 goto goodbye;
333 } 346 }
334 filesystemType = *(++argv); 347 filesystemType = *(++argv);
335 break; 348 break;
336 case 'w': 349 case 'w':
337 flags &= ~MS_RDONLY; 350 flags &= ~MS_RDONLY;
338 break; 351 break;
339 case 'a': 352 case 'a':
340 all = TRUE; 353 all = TRUE;
341 break; 354 break;
342#ifdef BB_MTAB 355#ifdef BB_MTAB
343 case 'f': 356 case 'f':
344 fakeIt = TRUE; 357 fakeIt = TRUE;
345 break; 358 break;
346 case 'n': 359 case 'n':
347 useMtab = FALSE; 360 useMtab = FALSE;
348 break; 361 break;
349#endif 362#endif
350 case 'v': 363 case 'v':
351 case 'h': 364 case 'h':
352 case '-': 365 case '-':
353 goto goodbye; 366 goto goodbye;
354 } 367 }
355 } else { 368 } else {
356 if (device == NULL) 369 if (device == NULL)
357 device = *argv; 370 device = *argv;
358 else if (directory == NULL) 371 else if (directory == NULL)
359 directory = *argv; 372 directory = *argv;
360 else { 373 else {
361 goto goodbye; 374 goto goodbye;
362 } 375 }
376 }
377 i--;
378 argv++;
363 } 379 }
364 i--;
365 argv++;
366 }
367 380
368 if (all == TRUE) { 381 if (all == TRUE) {
369 struct mntent *m; 382 struct mntent *m;
370 FILE *f = setmntent ("/etc/fstab", "r"); 383 FILE *f = setmntent("/etc/fstab", "r");
371 384
372 if (f == NULL) { 385 if (f == NULL) {
373 perror("/etc/fstab"); 386 perror("/etc/fstab");
374 exit( FALSE); 387 exit(FALSE);
375 } 388 }
376 while ((m = getmntent (f)) != NULL) { 389 while ((m = getmntent(f)) != NULL) {
377 // If the file system isn't noauto, and isn't mounted on /, 390 // If the file system isn't noauto, and isn't mounted on /,
378 // and isn't swap or nfs, then mount it 391 // and isn't swap or nfs, then mount it
379 if ((!strstr (m->mnt_opts, "noauto")) && 392 if ((!strstr(m->mnt_opts, "noauto")) &&
380 (m->mnt_dir[1] != '\0') && 393 (m->mnt_dir[1] != '\0') &&
381 (!strstr (m->mnt_type, "swap")) && 394 (!strstr(m->mnt_type, "swap")) &&
382 (!strstr (m->mnt_type, "nfs"))) 395 (!strstr(m->mnt_type, "nfs"))) {
383 { 396 flags = 0;
384 flags = 0; 397 *string_flags = '\0';
385 *string_flags = '\0'; 398 parse_mount_options(m->mnt_opts, &flags, string_flags);
386 parse_mount_options(m->mnt_opts, &flags, string_flags); 399 mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
387 mount_one (m->mnt_fsname, m->mnt_dir, m->mnt_type, 400 flags, string_flags, useMtab, fakeIt,
388 flags, string_flags, useMtab, fakeIt, extra_opts); 401 extra_opts);
389 } 402 }
390 } 403 }
391 endmntent (f); 404 endmntent(f);
392 } else { 405 } else {
393 if (device && directory) { 406 if (device && directory) {
394#ifdef BB_NFSMOUNT 407#ifdef BB_NFSMOUNT
395 if (strcmp(filesystemType, "nfs") == 0) { 408 if (strcmp(filesystemType, "nfs") == 0) {
396 if (nfsmount(device, directory, &flags, &extra_opts, &string_flags, 1) != 0) 409 if (nfsmount
397 exit(FALSE); 410 (device, directory, &flags, &extra_opts, &string_flags,
398 } 411 1) != 0)
412 exit(FALSE);
413 }
399#endif 414#endif
400 exit (mount_one (device, directory, filesystemType, 415 exit(mount_one(device, directory, filesystemType,
401 flags, string_flags, useMtab, fakeIt, extra_opts)); 416 flags, string_flags, useMtab, fakeIt,
402 } else { 417 extra_opts));
403 goto goodbye; 418 } else {
419 goto goodbye;
420 }
404 } 421 }
405 } 422 exit(TRUE);
406 exit( TRUE);
407 423
408goodbye: 424 goodbye:
409 usage( mount_usage); 425 usage(mount_usage);
410} 426}
411