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 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33#include	<stdio.h>
34#include	<stdlib.h>
35#include	<signal.h>
36#include	<string.h>
37#include	<unistd.h>
38#include	<errno.h>
39#include	<sys/mnttab.h>
40#include	<sys/mount.h>
41#include	<sys/types.h>
42#include	<locale.h>
43#include	<fslib.h>
44
45#define	NAME_MAX	64	/* sizeof "fstype myname" */
46
47#define	FSTYPE		"fd"
48
49static char  optbuf[MAX_MNTOPT_STR] = { '\0', };
50static int   optsize = 0;
51
52static int	flags = 0;
53static int	mflg = 0;
54static int	qflg = 0;
55
56static char	typename[NAME_MAX], *myname;
57static char	fstype[] = FSTYPE;
58
59static void usage(void);
60static void do_mount(char *, char *, int);
61
62int
63main(int argc, char **argv)
64{
65	char	*special, *mountp;
66	int	errflag = 0;
67	int	cc;
68
69	(void) setlocale(LC_ALL, "");
70
71#if !defined(TEXT_DOMAIN)
72#define	TEXT_DOMAIN "SYS_TEST"
73#endif
74	(void) textdomain(TEXT_DOMAIN);
75
76	myname = strrchr(argv[0], '/');
77	if (myname)
78		myname++;
79	else
80		myname = argv[0];
81	(void) snprintf(typename, sizeof (typename), "%s %s", fstype, myname);
82	argv[0] = typename;
83
84	/*
85	 *	check for proper arguments
86	 */
87
88	while ((cc = getopt(argc, argv, "o:rmOq")) != -1)
89		switch (cc) {
90		case 'r':
91			if (flags & MS_RDONLY)
92				errflag = 1;
93			else
94				flags |= MS_RDONLY;
95			break;
96		case 'O':
97			flags |= MS_OVERLAY;
98			break;
99		case 'q':
100			qflg = 1;
101			break;
102		case 'm':
103			mflg++;
104			break;
105		case 'o':
106			if (strlcpy(optbuf, optarg, sizeof (optbuf)) >=
107			    sizeof (optbuf)) {
108				(void) fprintf(stderr,
109				    gettext("%s: Invalid argument: %s\n"),
110				    myname, optarg);
111				return (2);
112			}
113			optsize = strlen(optbuf);
114			break;
115		default:
116		case '?':
117			errflag = 1;
118			break;
119		}
120
121	/*
122	 *	There must be at least 2 more arguments, the
123	 *	special file and the directory.
124	 */
125
126	if (((argc - optind) != 2) || (errflag))
127		usage();
128
129	special = argv[optind++];
130	mountp = argv[optind++];
131
132	/*
133	 *	Perform the mount.
134	 *	Only the low-order bit of "flags" is used by the system
135	 *	calls (to denote read-only or read-write).
136	 */
137	if (mflg)
138		flags |= MS_NOMNTTAB;
139	do_mount(special, mountp, flags);
140	exit(0);
141	/* NOTREACHED */
142}
143
144static void
145rpterr(char *bs, char *mp)
146{
147	switch (errno) {
148	case EPERM:
149		(void) fprintf(stderr,
150		    gettext("%s: insufficient privileges\n"), myname);
151		break;
152	case ENXIO:
153		(void) fprintf(stderr,
154			gettext("%s: %s no such device\n"), myname, bs);
155		break;
156	case ENOTDIR:
157		(void) fprintf(stderr,
158		    gettext("%s: %s not a directory\n"
159		    "\tor a component of %s is not a directory\n"),
160			myname, mp, bs);
161		break;
162	case ENOENT:
163		(void) fprintf(stderr,
164			gettext("%s: %s or %s, no such file or directory\n"),
165			myname, bs, mp);
166		break;
167	case EINVAL:
168		(void) fprintf(stderr, gettext("%s: %s is not this fstype.\n"),
169			myname, bs);
170		break;
171	case EBUSY:
172		(void) fprintf(stderr,
173			gettext("%s: %s is already mounted or %s is busy\n"),
174			myname, bs, mp);
175		break;
176	case ENOTBLK:
177		(void) fprintf(stderr, gettext("%s: %s not a block device\n"),
178			myname, bs);
179		break;
180	case EROFS:
181		(void) fprintf(stderr,
182			gettext("%s: %s write-protected\n"), myname, bs);
183		break;
184	case ENOSPC:
185		(void) fprintf(stderr,
186			gettext("%s: the state of %s is not okay\n"
187			    "\tand it was attempted to mount read/write\n"),
188			myname, bs);
189		break;
190	default:
191		perror(myname);
192		(void) fprintf(stderr, gettext("%s: cannot mount %s\n"),
193		    myname, bs);
194	}
195}
196
197
198static void
199do_mount(char *special, char *mountp, int rflag)
200{
201	char *savedoptbuf;
202
203	if ((savedoptbuf = strdup(optbuf)) == NULL) {
204		(void) fprintf(stderr, gettext("%s: out of memory\n"),
205		    myname);
206		exit(2);
207	}
208	if (mount(special, mountp, rflag | MS_OPTIONSTR,
209		fstype, NULL, 0, optbuf, MAX_MNTOPT_STR)) {
210		rpterr(special, mountp);
211		exit(2);
212	}
213	if (optsize && !qflg)
214		cmp_requested_to_actual_options(savedoptbuf, optbuf,
215		    special, mountp);
216}
217
218
219static void
220usage(void)
221{
222	(void) fprintf(stderr,
223		gettext("Usage: %s [-rmOq] [-o specific_options]"
224		" special mount_point\n"), myname);
225	exit(1);
226}
227