xref: /illumos-gate/usr/src/cmd/fs.d/tmpfs/mount.c (revision 7a6d80f1660abd4755c68cbd094d4a914681d26e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/mount.h>
33 #include <sys/types.h>
34 #include <locale.h>
35 #include <sys/stat.h>
36 #include <fslib.h>
37 #include <stdio.h>
38 #include <sys/mnttab.h>
39 #include <poll.h>
40 
41 #define	MNTTYPE_TMPFS	"tmpfs"
42 
43 static int	nmflg = 0;
44 static int	qflg = 0;
45 
46 static boolean_t
47 in_mnttab(char *mountp)
48 {
49 	FILE *file;
50 	int found = B_FALSE;
51 	struct mnttab mntent;
52 
53 	if ((file = fopen("/etc/mnttab", "r")) == NULL)
54 		return (B_FALSE);
55 	while (getmntent(file, &mntent) == 0) {
56 		if (mntent.mnt_mountp != NULL &&
57 		    strcmp(mntent.mnt_mountp, mountp) == 0 &&
58 		    mntent.mnt_fstype != NULL &&
59 		    strcmp(mntent.mnt_fstype, MNTTYPE_TMPFS) == 0) {
60 			found = B_TRUE;
61 			break;
62 		}
63 	}
64 	(void) fclose(file);
65 	return (found);
66 }
67 
68 int
69 main(int argc, char *argv[])
70 {
71 	/* mount information */
72 	char *special;
73 	char *mountp;
74 
75 	int c;
76 	char *myname;
77 	char typename[64];
78 	extern int optind;
79 	extern char *optarg;
80 	int error = 0;
81 	int verbose = 0;
82 	int mflg = 0;
83 	int optcnt = 0;
84 	int mount_attempts = 5;
85 
86 	char optbuf[MAX_MNTOPT_STR];
87 	int optsize = 0;
88 	char *saveoptbuf;
89 
90 	(void) setlocale(LC_ALL, "");
91 
92 #if !defined(TEXT_DOMAIN)
93 #define	TEXT_DOMAIN "SYS_TEST"
94 #endif
95 	(void) textdomain(TEXT_DOMAIN);
96 
97 	myname = strrchr(argv[0], '/');
98 	myname = myname ? myname + 1 : argv[0];
99 	(void) snprintf(typename, sizeof (typename), "%s_%s",
100 	    MNTTYPE_TMPFS, myname);
101 	argv[0] = typename;
102 	optbuf[0] = '\0';
103 
104 	while ((c = getopt(argc, argv, "?o:VmOq")) != EOF) {
105 		switch (c) {
106 		case 'V':
107 			verbose++;
108 			break;
109 		case '?':
110 			error++;
111 			break;
112 		case 'm':
113 			nmflg++;
114 			break;
115 		case 'O':
116 			mflg |= MS_OVERLAY;
117 			break;
118 		case 'o':
119 			(void) strncpy(optbuf, optarg, MAX_MNTOPT_STR);
120 			optbuf[MAX_MNTOPT_STR - 1] = '\0';
121 			optsize = strlen(optbuf);
122 
123 			if (verbose)
124 				(void) fprintf(stderr, "optsize:%d optbuf:%s\n",
125 				    optsize, optbuf);
126 			break;
127 		case 'q':
128 			qflg++;
129 			break;
130 		}
131 	}
132 
133 	if (verbose && !error) {
134 		char *optptr;
135 
136 		(void) fprintf(stderr, "%s", typename);
137 		for (optcnt = 1; optcnt < argc; optcnt++) {
138 			optptr = argv[optcnt];
139 			if (optptr)
140 				(void) fprintf(stderr, " %s", optptr);
141 		}
142 		(void) fprintf(stderr, "\n");
143 	}
144 
145 	if (argc - optind != 2 || error) {
146 		(void) fprintf(stderr,
147 		    gettext("Usage: %s [-o size] swap mount_point\n"),
148 		    typename);
149 		exit(32);
150 	}
151 
152 	special = argv[optind++];
153 	mountp = argv[optind++];
154 	mflg |= MS_OPTIONSTR;
155 	mflg |= (nmflg ? MS_NOMNTTAB : 0);
156 
157 	if (verbose) {
158 		(void) fprintf(stderr, "mount(%s, \"%s\", %d, %s",
159 		    special, mountp, mflg, MNTTYPE_TMPFS);
160 		if (optsize)
161 			(void) fprintf(stderr, ", \"%s\", %d)\n",
162 			    optbuf, strlen(optbuf));
163 		else
164 			(void) fprintf(stderr, ")\n");
165 	}
166 	if (optsize) {
167 		if ((saveoptbuf = strdup(optbuf)) == NULL) {
168 			(void) fprintf(stderr, gettext("%s: out of memory\n"),
169 				"mount");
170 			exit(1);
171 		}
172 	}
173 again:	if (mount(special, mountp, mflg, MNTTYPE_TMPFS, NULL, 0,
174 	    optbuf, MAX_MNTOPT_STR)) {
175 		if (errno == EBUSY && !(mflg & MS_OVERLAY)) {
176 			/*
177 			 * Because of bug 6176743, any attempt to mount
178 			 * tmpfs filesystem could fail for reasons
179 			 * described in that bug.  We're trying to detect
180 			 * that situation here by checking that the filesystem
181 			 * we're mounting is not in /etc/mnttab yet.
182 			 * When that bug is fixed, this code can be removed.
183 			 */
184 			if (!in_mnttab(mountp) && mount_attempts-- > 0) {
185 				(void) poll(NULL, 0, 50);
186 				goto again;
187 			}
188 			(void) fprintf(stderr, gettext(
189 			    "%s: %s is already mounted or %s is busy\n"),
190 			    myname, mountp, special);
191 		} else {
192 			perror("mount");
193 		}
194 		exit(32);
195 	}
196 
197 	if (optsize && !qflg)
198 		cmp_requested_to_actual_options(saveoptbuf, optbuf,
199 			special, mountp);
200 	return (0);
201 }
202