svn commit: trunk/busybox/util-linux

vda at busybox.net vda at busybox.net
Fri Sep 15 15:12:01 UTC 2006


Author: vda
Date: 2006-09-15 08:12:00 -0700 (Fri, 15 Sep 2006)
New Revision: 16128

Log:
mount: reorder things, fix NFS-less mount.


Modified:
   trunk/busybox/util-linux/mount.c


Changeset:
Modified: trunk/busybox/util-linux/mount.c
===================================================================
--- trunk/busybox/util-linux/mount.c	2006-09-15 04:10:05 UTC (rev 16127)
+++ trunk/busybox/util-linux/mount.c	2006-09-15 15:12:00 UTC (rev 16128)
@@ -25,6 +25,16 @@
 #include "busybox.h"
 #include <mntent.h>
 
+/* Needed for nfs support only... */
+#include <syslog.h>
+#include <sys/utsname.h>
+#undef TRUE
+#undef FALSE
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+
+
 // Not real flags, but we want to be able to check for this.
 #define MOUNT_NOAUTO    (1<<29)
 #define MOUNT_SWAP      (1<<30)
@@ -86,8 +96,8 @@
 	{"remount", MS_REMOUNT},  // action flag
 };
 
-static int nfsmount(struct mntent *mp, int vfsflags, char *filteropts);
 
+
 /* Append mount options to string */
 static void append_mount_options(char **oldopts, char *newopts)
 {
@@ -272,349 +282,6 @@
 	return rc;
 }
 
-// Mount one directory.  Handles CIFS, NFS, loopback, autobind, and filesystem
-// type detection.  Returns 0 for success, nonzero for failure.
-
-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 CIFS filesystem?
-
-	if(ENABLE_FEATURE_MOUNT_CIFS &&
-		(!mp->mnt_type || !strcmp(mp->mnt_type,"cifs")) &&
-		(mp->mnt_fsname[0]==mp->mnt_fsname[1] && (mp->mnt_fsname[0]=='/' || mp->mnt_fsname[0]=='\\')))
-	{
-		struct hostent *he;
-		char ip[32], *s;
-
-		rc = 1;
-		// Replace '/' with '\' and verify that unc points to "//server/share".
-
-		for (s = mp->mnt_fsname; *s; ++s)
-			if (*s == '/') *s = '\\';
-
-		// get server IP
-
-		s = strrchr(mp->mnt_fsname, '\\');
-		if (s == mp->mnt_fsname+1) goto report_error;
-		*s = 0;
-	   	he = gethostbyname(mp->mnt_fsname+2);
-		*s = '\\';
-		if (!he) goto report_error;
-
-		// Insert ip=... option into string flags.  (NOTE: Add IPv6 support.)
-
-		sprintf(ip, "ip=%d.%d.%d.%d", he->h_addr[0], he->h_addr[1],
-				he->h_addr[2], he->h_addr[3]);
-		parse_mount_options(ip, &filteropts);
-
-		// compose new unc '\\server-ip\share'
-
-		s = xasprintf("\\\\%s%s",ip+3,strchr(mp->mnt_fsname+2,'\\'));
-		if (ENABLE_FEATURE_CLEAN_UP) free(mp->mnt_fsname);
-		mp->mnt_fsname = s;
-
-		// lock is required
-		vfsflags |= MS_MANDLOCK;
-
-		mp->mnt_type = "cifs";
-		rc = mount_it_now(mp, vfsflags, filteropts);
-		goto report_error;
-	}
-
-	// Might this be an NFS filesystem?
-
-	if (ENABLE_FEATURE_MOUNT_NFS &&
-		(!mp->mnt_type || !strcmp(mp->mnt_type,"nfs")) &&
-		strchr(mp->mnt_fsname, ':') != NULL)
-	{
-		rc = nfsmount(mp, vfsflags, 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 (!lstat(mp->mnt_fsname, &st) && !(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
-						: "cannot 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 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 (ENABLE_FEATURE_CLEAN_UP) free(filteropts);
-
-	if (rc && errno == EBUSY && ignore_busy) rc = 0;
-	if (rc < 0)
-		/* perror here sometimes says "mounting ... on ... failed: Success" */
-		bb_error_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
-
-	return rc;
-}
-
-// Parse options, if necessary parse fstab/mtab, and call singlemount for
-// each directory to be mounted.
-
-int mount_main(int argc, char **argv)
-{
-	char *cmdopts = xstrdup(""), *fstabname, *fstype=0, *storage_path=0;
-	FILE *fstab;
-	int i, opt, all = FALSE, rc = 0;
-	struct mntent mtpair[2], *mtcur = mtpair;
-
-	/* parse long options, like --bind and --move.  Note that -o option
-	 * and --option are synonymous.  Yes, this means --remount,rw works. */
-
-	for (i = opt = 0; i < argc; i++) {
-		if (argv[i][0] == '-' && argv[i][1] == '-') {
-			append_mount_options(&cmdopts,argv[i]+2);
-		} else argv[opt++] = argv[i];
-	}
-	argc = opt;
-
-	// Parse remaining options
-
-	while ((opt = getopt(argc, argv, "o:t:rwavnf")) > 0) {
-		switch (opt) {
-			case 'o':
-				append_mount_options(&cmdopts, optarg);
-				break;
-			case 't':
-				fstype = optarg;
-				break;
-			case 'r':
-				append_mount_options(&cmdopts, "ro");
-				break;
-			case 'w':
-				append_mount_options(&cmdopts, "rw");
-				break;
-			case 'a':
-				all = TRUE;
-				break;
-			case 'n':
-				USE_FEATURE_MTAB_SUPPORT(useMtab = FALSE;)
-				break;
-			case 'f':
-				USE_FEATURE_MTAB_SUPPORT(fakeIt = FALSE;)
-				break;
-			case 'v':
-				break;		// ignore -v
-			default:
-				bb_show_usage();
-		}
-	}
-
-	// Three or more non-option arguments?  Die with a usage message.
-
-	if (optind-argc>2) bb_show_usage();
-
-	// If we have no arguments, show currently mounted filesystems
-
-	if (optind == argc) {
-		if (!all) {
-			FILE *mountTable = setmntent(bb_path_mtab_file, "r");
-
-			if(!mountTable) bb_error_msg_and_die("no %s",bb_path_mtab_file);
-
-			while (getmntent_r(mountTable,mtpair,bb_common_bufsiz1,
-								sizeof(bb_common_bufsiz1)))
-			{
-				// Don't show rootfs.
-				if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue;
-
-				if (!fstype || !strcmp(mtpair->mnt_type, fstype))
-					printf("%s on %s type %s (%s)\n", mtpair->mnt_fsname,
-							mtpair->mnt_dir, mtpair->mnt_type,
-							mtpair->mnt_opts);
-			}
-			if (ENABLE_FEATURE_CLEAN_UP) endmntent(mountTable);
-			return EXIT_SUCCESS;
-		}
-	} else storage_path = bb_simplify_path(argv[optind]);
-
-	// When we have two arguments, the second is the directory and we can
-	// skip looking at fstab entirely.  We can always abspath() the directory
-	// argument when we get it.
-
-	if (optind+2 == argc) {
-		mtpair->mnt_fsname = argv[optind];
-		mtpair->mnt_dir = argv[optind+1];
-		mtpair->mnt_type = fstype;
-		mtpair->mnt_opts = cmdopts;
-		rc = singlemount(mtpair, 0);
-		goto clean_up;
-	}
-
-	// If we have a shared subtree flag, don't worry about fstab or mtab.
-	i = parse_mount_options(cmdopts,0);
-	if (ENABLE_FEATURE_MOUNT_FLAGS &&
-			(i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE )))
-	{
-		rc = mount("", argv[optind], "", i, "");
-		if (rc) bb_perror_msg_and_die("%s", argv[optind]);
-		goto clean_up;
-	}
-	
-	// Open either fstab or mtab
-
-	if (parse_mount_options(cmdopts,0) & MS_REMOUNT)
-		fstabname = bb_path_mtab_file;
-	else fstabname="/etc/fstab";
-
-	if (!(fstab=setmntent(fstabname,"r")))
-		bb_perror_msg_and_die("cannot read %s",fstabname);
-
-	// Loop through entries until we find what we're looking for.
-
-	memset(mtpair,0,sizeof(mtpair));
-	for (;;) {
-		struct mntent *mtnext = mtpair + (mtcur==mtpair ? 1 : 0);
-
-		// Get next fstab entry
-
-		if (!getmntent_r(fstab, mtcur, bb_common_bufsiz1
-					+ (mtcur==mtpair ? sizeof(bb_common_bufsiz1)/2 : 0),
-				sizeof(bb_common_bufsiz1)/2))
-		{
-			// Were we looking for something specific?
-
-			if (optind != argc) {
-
-				// If we didn't find anything, complain.
-
-				if (!mtnext->mnt_fsname)
-					bb_error_msg_and_die("can't find %s in %s",
-						argv[optind], fstabname);
-
-				// Mount the last thing we found.
-
-				mtcur = mtnext;
-				mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
-				append_mount_options(&(mtcur->mnt_opts),cmdopts);
-				rc = singlemount(mtcur, 0);
-				free(mtcur->mnt_opts);
-			}
-			goto clean_up;
-		}
-
-		/* If we're trying to mount something specific and this isn't it,
-		 * skip it.  Note we must match both the exact text in fstab (ala
-		 * "proc") or a full path from root */
-
-		if (optind != argc) {
-
-			// Is this what we're looking for?
-
-			if(strcmp(argv[optind],mtcur->mnt_fsname) &&
-			   strcmp(storage_path,mtcur->mnt_fsname) &&
-			   strcmp(argv[optind],mtcur->mnt_dir) &&
-			   strcmp(storage_path,mtcur->mnt_dir)) continue;
-
-			// Remember this entry.  Something later may have overmounted
-			// it, and we want the _last_ match.
-
-			mtcur = mtnext;
-
-		// If we're mounting all.
-
-		} else {
-
-			// Do we need to match a filesystem type?
-			if (fstype && strcmp(mtcur->mnt_type,fstype)) continue;
-
-			// Skip noauto and swap anyway.
-
-			if (parse_mount_options(mtcur->mnt_opts,0)
-				& (MOUNT_NOAUTO | MOUNT_SWAP)) continue;
-
-			// Mount this thing.
-
-			if (singlemount(mtcur, 1)) {
-				/* Count number of failed mounts */
-				rc++;
-			}
-		}
-	}
-	if (ENABLE_FEATURE_CLEAN_UP) endmntent(fstab);
-
-clean_up:
-
-	if (ENABLE_FEATURE_CLEAN_UP) {
-		free(storage_path);
-		free(cmdopts);
-	}
-
-	return rc;
-}
-
-
 #if ENABLE_FEATURE_MOUNT_NFS
 
 /*
@@ -639,17 +306,9 @@
  * plus NFSv3 stuff.
  */
 
-#include <syslog.h>
-#include <sys/utsname.h>
-#undef TRUE
-#undef FALSE
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <rpc/pmap_clnt.h>
-
 /* This is just a warning of a common mistake.  Possibly this should be a
  * uclibc faq entry rather than in busybox... */
-#if ENABLE_FEATURE_MOUNT_NFS && defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
+#if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
 #error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support."
 #endif
 
@@ -1314,25 +973,6 @@
 	if (!data.timeo)
 		data.timeo = tcp ? 70 : 7;
 
-#ifdef NFS_MOUNT_DEBUG
-	printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
-		data.rsize, data.wsize, data.timeo, data.retrans);
-	printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
-		data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
-	printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
-		port, bg, retry, data.flags);
-	printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
-		mountprog, mountvers, nfsprog, nfsvers);
-	printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
-		(data.flags & NFS_MOUNT_SOFT) != 0,
-		(data.flags & NFS_MOUNT_INTR) != 0,
-		(data.flags & NFS_MOUNT_POSIX) != 0,
-		(data.flags & NFS_MOUNT_NOCTO) != 0,
-		(data.flags & NFS_MOUNT_NOAC) != 0);
-	printf("tcp = %d\n",
-		(data.flags & NFS_MOUNT_TCP) != 0);
-#endif
-
 	data.version = nfs_mount_version;
 
 	if (vfsflags & MS_REMOUNT)
@@ -1559,14 +1199,7 @@
 					tcp ? IPPROTO_TCP : IPPROTO_UDP);
 		if (port == 0)
 			port = NFS_PORT;
-#ifdef NFS_MOUNT_DEBUG
-		else
-			printf("used portmapper to find NFS port\n");
-#endif
 	}
-#ifdef NFS_MOUNT_DEBUG
-	printf("using port %d for nfs daemon\n", port);
-#endif
 	server_addr.sin_port = htons(port);
 
 	/* prepare data structure for kernel */
@@ -1625,4 +1258,351 @@
 	return retval;
 }
 
-#endif /* ENABLE_FEATURE_MOUNT_NFS */
+#else /* !ENABLE_FEATURE_MOUNT_NFS */
+
+/* Never called. Call should be optimized out. */
+int nfsmount(struct mntent *mp, int vfsflags, char *filteropts);
+
+#endif /* !ENABLE_FEATURE_MOUNT_NFS */
+
+// Mount one directory.  Handles CIFS, NFS, loopback, autobind, and filesystem
+// type detection.  Returns 0 for success, nonzero for failure.
+
+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 CIFS filesystem?
+
+	if(ENABLE_FEATURE_MOUNT_CIFS &&
+		(!mp->mnt_type || !strcmp(mp->mnt_type,"cifs")) &&
+		(mp->mnt_fsname[0]==mp->mnt_fsname[1] && (mp->mnt_fsname[0]=='/' || mp->mnt_fsname[0]=='\\')))
+	{
+		struct hostent *he;
+		char ip[32], *s;
+
+		rc = 1;
+		// Replace '/' with '\' and verify that unc points to "//server/share".
+
+		for (s = mp->mnt_fsname; *s; ++s)
+			if (*s == '/') *s = '\\';
+
+		// get server IP
+
+		s = strrchr(mp->mnt_fsname, '\\');
+		if (s == mp->mnt_fsname+1) goto report_error;
+		*s = 0;
+	   	he = gethostbyname(mp->mnt_fsname+2);
+		*s = '\\';
+		if (!he) goto report_error;
+
+		// Insert ip=... option into string flags.  (NOTE: Add IPv6 support.)
+
+		sprintf(ip, "ip=%d.%d.%d.%d", he->h_addr[0], he->h_addr[1],
+				he->h_addr[2], he->h_addr[3]);
+		parse_mount_options(ip, &filteropts);
+
+		// compose new unc '\\server-ip\share'
+
+		s = xasprintf("\\\\%s%s",ip+3,strchr(mp->mnt_fsname+2,'\\'));
+		if (ENABLE_FEATURE_CLEAN_UP) free(mp->mnt_fsname);
+		mp->mnt_fsname = s;
+
+		// lock is required
+		vfsflags |= MS_MANDLOCK;
+
+		mp->mnt_type = "cifs";
+		rc = mount_it_now(mp, vfsflags, filteropts);
+		goto report_error;
+	}
+
+	// Might this be an NFS filesystem?
+
+	if (ENABLE_FEATURE_MOUNT_NFS &&
+		(!mp->mnt_type || !strcmp(mp->mnt_type,"nfs")) &&
+		strchr(mp->mnt_fsname, ':') != NULL)
+	{
+		rc = nfsmount(mp, vfsflags, 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 (!lstat(mp->mnt_fsname, &st) && !(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
+						: "cannot 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 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 (ENABLE_FEATURE_CLEAN_UP) free(filteropts);
+
+	if (rc && errno == EBUSY && ignore_busy) rc = 0;
+	if (rc < 0)
+		/* perror here sometimes says "mounting ... on ... failed: Success" */
+		bb_error_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
+
+	return rc;
+}
+
+// Parse options, if necessary parse fstab/mtab, and call singlemount for
+// each directory to be mounted.
+
+int mount_main(int argc, char **argv)
+{
+	char *cmdopts = xstrdup(""), *fstabname, *fstype=0, *storage_path=0;
+	FILE *fstab;
+	int i, opt, all = FALSE, rc = 0;
+	struct mntent mtpair[2], *mtcur = mtpair;
+
+	/* parse long options, like --bind and --move.  Note that -o option
+	 * and --option are synonymous.  Yes, this means --remount,rw works. */
+
+	for (i = opt = 0; i < argc; i++) {
+		if (argv[i][0] == '-' && argv[i][1] == '-') {
+			append_mount_options(&cmdopts,argv[i]+2);
+		} else argv[opt++] = argv[i];
+	}
+	argc = opt;
+
+	// Parse remaining options
+
+	while ((opt = getopt(argc, argv, "o:t:rwavnf")) > 0) {
+		switch (opt) {
+			case 'o':
+				append_mount_options(&cmdopts, optarg);
+				break;
+			case 't':
+				fstype = optarg;
+				break;
+			case 'r':
+				append_mount_options(&cmdopts, "ro");
+				break;
+			case 'w':
+				append_mount_options(&cmdopts, "rw");
+				break;
+			case 'a':
+				all = TRUE;
+				break;
+			case 'n':
+				USE_FEATURE_MTAB_SUPPORT(useMtab = FALSE;)
+				break;
+			case 'f':
+				USE_FEATURE_MTAB_SUPPORT(fakeIt = FALSE;)
+				break;
+			case 'v':
+				break;		// ignore -v
+			default:
+				bb_show_usage();
+		}
+	}
+
+	// Three or more non-option arguments?  Die with a usage message.
+
+	if (optind-argc>2) bb_show_usage();
+
+	// If we have no arguments, show currently mounted filesystems
+
+	if (optind == argc) {
+		if (!all) {
+			FILE *mountTable = setmntent(bb_path_mtab_file, "r");
+
+			if(!mountTable) bb_error_msg_and_die("no %s",bb_path_mtab_file);
+
+			while (getmntent_r(mountTable,mtpair,bb_common_bufsiz1,
+								sizeof(bb_common_bufsiz1)))
+			{
+				// Don't show rootfs.
+				if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue;
+
+				if (!fstype || !strcmp(mtpair->mnt_type, fstype))
+					printf("%s on %s type %s (%s)\n", mtpair->mnt_fsname,
+							mtpair->mnt_dir, mtpair->mnt_type,
+							mtpair->mnt_opts);
+			}
+			if (ENABLE_FEATURE_CLEAN_UP) endmntent(mountTable);
+			return EXIT_SUCCESS;
+		}
+	} else storage_path = bb_simplify_path(argv[optind]);
+
+	// When we have two arguments, the second is the directory and we can
+	// skip looking at fstab entirely.  We can always abspath() the directory
+	// argument when we get it.
+
+	if (optind+2 == argc) {
+		mtpair->mnt_fsname = argv[optind];
+		mtpair->mnt_dir = argv[optind+1];
+		mtpair->mnt_type = fstype;
+		mtpair->mnt_opts = cmdopts;
+		rc = singlemount(mtpair, 0);
+		goto clean_up;
+	}
+
+	// If we have a shared subtree flag, don't worry about fstab or mtab.
+	i = parse_mount_options(cmdopts,0);
+	if (ENABLE_FEATURE_MOUNT_FLAGS &&
+			(i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE )))
+	{
+		rc = mount("", argv[optind], "", i, "");
+		if (rc) bb_perror_msg_and_die("%s", argv[optind]);
+		goto clean_up;
+	}
+	
+	// Open either fstab or mtab
+
+	if (parse_mount_options(cmdopts,0) & MS_REMOUNT)
+		fstabname = bb_path_mtab_file;
+	else fstabname="/etc/fstab";
+
+	if (!(fstab=setmntent(fstabname,"r")))
+		bb_perror_msg_and_die("cannot read %s",fstabname);
+
+	// Loop through entries until we find what we're looking for.
+
+	memset(mtpair,0,sizeof(mtpair));
+	for (;;) {
+		struct mntent *mtnext = mtpair + (mtcur==mtpair ? 1 : 0);
+
+		// Get next fstab entry
+
+		if (!getmntent_r(fstab, mtcur, bb_common_bufsiz1
+					+ (mtcur==mtpair ? sizeof(bb_common_bufsiz1)/2 : 0),
+				sizeof(bb_common_bufsiz1)/2))
+		{
+			// Were we looking for something specific?
+
+			if (optind != argc) {
+
+				// If we didn't find anything, complain.
+
+				if (!mtnext->mnt_fsname)
+					bb_error_msg_and_die("can't find %s in %s",
+						argv[optind], fstabname);
+
+				// Mount the last thing we found.
+
+				mtcur = mtnext;
+				mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
+				append_mount_options(&(mtcur->mnt_opts),cmdopts);
+				rc = singlemount(mtcur, 0);
+				free(mtcur->mnt_opts);
+			}
+			goto clean_up;
+		}
+
+		/* If we're trying to mount something specific and this isn't it,
+		 * skip it.  Note we must match both the exact text in fstab (ala
+		 * "proc") or a full path from root */
+
+		if (optind != argc) {
+
+			// Is this what we're looking for?
+
+			if(strcmp(argv[optind],mtcur->mnt_fsname) &&
+			   strcmp(storage_path,mtcur->mnt_fsname) &&
+			   strcmp(argv[optind],mtcur->mnt_dir) &&
+			   strcmp(storage_path,mtcur->mnt_dir)) continue;
+
+			// Remember this entry.  Something later may have overmounted
+			// it, and we want the _last_ match.
+
+			mtcur = mtnext;
+
+		// If we're mounting all.
+
+		} else {
+
+			// Do we need to match a filesystem type?
+			if (fstype && strcmp(mtcur->mnt_type,fstype)) continue;
+
+			// Skip noauto and swap anyway.
+
+			if (parse_mount_options(mtcur->mnt_opts,0)
+				& (MOUNT_NOAUTO | MOUNT_SWAP)) continue;
+
+			// Mount this thing.
+
+			if (singlemount(mtcur, 1)) {
+				/* Count number of failed mounts */
+				rc++;
+			}
+		}
+	}
+	if (ENABLE_FEATURE_CLEAN_UP) endmntent(fstab);
+
+clean_up:
+
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		free(storage_path);
+		free(cmdopts);
+	}
+
+	return rc;
+}




More information about the busybox-cvs mailing list