extern int mount_main(int argc, char **argv) { struct stat statbuf; char *string_flags = xstrdup(""); char *extra_opts; int flags = 0; char *filesystemType = "auto"; int got_filesystemType = 0; char *device = xmalloc(PATH_MAX); char *directory = xmalloc(PATH_MAX); struct mntent *m = NULL; int all = FALSE; int fakeIt = FALSE; int useMtab = TRUE; int rc = EXIT_FAILURE; FILE *f = 0; int opt; /* Parse options */ while ((opt = getopt(argc, argv, "o:rt:wafnv")) > 0) { switch (opt) { case 'o': parse_mount_options(optarg, &flags, &string_flags); break; case 'r': flags |= MS_RDONLY; break; case 't': filesystemType = optarg; got_filesystemType = 1; break; case 'w': flags &= ~MS_RDONLY; break; case 'a': all = TRUE; break; case 'f': fakeIt = TRUE; break; #ifdef BB_FEATURE_MTAB_SUPPORT case 'n': useMtab = FALSE; break; #endif case 'v': break; /* ignore -v */ } } if (!all && optind == argc) show_mounts(got_filesystemType ? filesystemType : 0); if (optind < argc) { /* if device is a filename get its real path */ if (stat(argv[optind], &statbuf) == 0) { char *tmp = simplify_path(argv[optind]); safe_strncpy(device, tmp, PATH_MAX); } else { safe_strncpy(device, argv[optind], PATH_MAX); } } if (optind + 1 < argc) directory = simplify_path(argv[optind + 1]); if (all || optind + 1 == argc) { f = setmntent("/etc/fstab", "r"); if (f == NULL) perror_msg_and_die( "\nCannot read /etc/fstab"); while ((m = getmntent(f)) != NULL) { if (! all && optind + 1 == argc && ( (strcmp(device, m->mnt_fsname) != 0) && (strcmp(device, m->mnt_dir) != 0) ) ) { continue; } if (all && ( // If we're mounting 'all' (strstr(m->mnt_opts, "noauto")) || // and the file system isn't noauto, (strstr(m->mnt_type, "swap")) || // and isn't swap or nfs, then mount it (strstr(m->mnt_type, "nfs")) ) ) { continue; } if (all || flags == 0) { // Allow single mount to override fstab flags flags = 0; string_flags[0] = 0; parse_mount_options(m->mnt_opts, &flags, &string_flags); } strcpy(device, m->mnt_fsname); strcpy(directory, m->mnt_dir); filesystemType = xstrdup(m->mnt_type); singlemount: extra_opts = string_flags; rc = EXIT_SUCCESS; #ifdef BB_NFSMOUNT if (strchr(device, ':') != NULL) { filesystemType = "nfs"; if (nfsmount (device, directory, &flags, &extra_opts, &string_flags, 1)) { perror_msg("nfsmount failed"); rc = EXIT_FAILURE; } } #endif if (!mount_one(device, directory, filesystemType, flags, string_flags, useMtab, fakeIt, extra_opts, TRUE, all)) rc = EXIT_FAILURE; if (! all) break; } if (f) endmntent(f); if (! all && f && m == NULL) fprintf(stderr, "Can't find %s in /etc/fstab\n", device); return rc; } goto singlemount; }
static int singlemount(struct mntent *mp, int ignore_busy) { int rc = -1, vfsflags; char *loopFile = 0, *filteropts = 0; llist_t *fl = 0; struct stat st; vfsflags = parse_mount_options(mp->mnt_opts, &filteropts); // Treat fstype "auto" as unspecified. if (mp->mnt_type && !strcmp(mp->mnt_type,"auto")) mp->mnt_type = 0; // Might this be an NFS filesystem? if (ENABLE_FEATURE_MOUNT_NFS && (!mp->mnt_type || !strcmp(mp->mnt_type,"nfs")) && strchr(mp->mnt_fsname, ':') != NULL) { if (nfsmount(mp->mnt_fsname, mp->mnt_dir, &vfsflags, &filteropts, 1)) { bb_perror_msg("nfsmount failed"); goto report_error; } else { // Strangely enough, nfsmount() doesn't actually mount() anything. mp->mnt_type = "nfs"; rc = mount_it_now(mp, vfsflags, filteropts); if (ENABLE_FEATURE_CLEAN_UP) free(filteropts); goto report_error; } } // Look at the file. (Not found isn't a failure for remount, or for // a synthetic filesystem like proc or sysfs.) if (stat(mp->mnt_fsname, &st)); else if (!(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) { // Do we need to allocate a loopback device for it? if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) { loopFile = bb_simplify_path(mp->mnt_fsname); mp->mnt_fsname = 0; switch(set_loop(&(mp->mnt_fsname), loopFile, 0)) { case 0: case 1: break; default: bb_error_msg( errno == EPERM || errno == EACCES ? bb_msg_perm_denied_are_you_root : "Couldn't setup loop device"); return errno; } // Autodetect bind mounts } else if (S_ISDIR(st.st_mode) && !mp->mnt_type) vfsflags |= MS_BIND; } /* If we know the fstype (or don't need to), jump straight * to the actual mount. */ if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) rc = mount_it_now(mp, vfsflags, filteropts); // Loop through filesystem types until mount succeeds or we run out else { /* Initialize list of block backed filesystems. This has to be * done here so that during "mount -a", mounts after /proc shows up * can autodetect. */ if (!fslist) { fslist = get_block_backed_filesystems(); if (ENABLE_FEATURE_CLEAN_UP && fslist) atexit(delete_block_backed_filesystems); } for (fl = fslist; fl; fl = fl->link) { mp->mnt_type = fl->data; if (!(rc = mount_it_now(mp,vfsflags, filteropts))) break; mp->mnt_type = 0; } } if (ENABLE_FEATURE_CLEAN_UP) free(filteropts); // If mount failed, clean up loop file (if any). if (ENABLE_FEATURE_MOUNT_LOOP && rc && loopFile) { del_loop(mp->mnt_fsname); if (ENABLE_FEATURE_CLEAN_UP) { free(loopFile); free(mp->mnt_fsname); } } report_error: if (rc && errno == EBUSY && ignore_busy) rc = 0; if (rc < 0) bb_perror_msg("Mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir); return rc; }