mount_ntfs.c revision 52055
1/*
2 * Copyright (c) 1994 Christopher G. Demetriou
3 * Copyright (c) 1999 Semen Ustimenko
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *      This product includes software developed by Christopher G. Demetriou.
17 * 4. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD: head/sbin/mount_ntfs/mount_ntfs.c 52055 1999-10-09 11:54:14Z phk $
32 *
33 */
34
35#include <sys/cdefs.h>
36#include <sys/param.h>
37#define NTFS
38#include <sys/mount.h>
39#include <sys/stat.h>
40#include <ntfs/ntfsmount.h>
41#include <ctype.h>
42#include <err.h>
43#include <grp.h>
44#include <pwd.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <sysexits.h>
49#include <unistd.h>
50
51#include "mntopts.h"
52
53static struct mntopt mopts[] = {
54	MOPT_STDOPTS,
55	{ NULL }
56};
57
58static gid_t	a_gid __P((char *));
59static uid_t	a_uid __P((char *));
60static mode_t	a_mask __P((char *));
61static void	usage __P((void)) __dead2;
62
63int
64main(argc, argv)
65	int argc;
66	char **argv;
67{
68	struct ntfs_args args;
69	struct stat sb;
70	int c, mntflags, set_gid, set_uid, set_mask, error;
71	char *dev, *dir, ndir[MAXPATHLEN+1], mntpath[MAXPATHLEN];
72#if __FreeBSD_version >= 300000
73	struct vfsconf vfc;
74#else
75	struct vfsconf *vfc;
76#endif
77
78	mntflags = set_gid = set_uid = set_mask = 0;
79	(void)memset(&args, '\0', sizeof(args));
80
81	while ((c = getopt(argc, argv, "aiu:g:m:o:")) !=  -1) {
82		switch (c) {
83		case 'u':
84			args.uid = a_uid(optarg);
85			set_uid = 1;
86			break;
87		case 'g':
88			args.gid = a_gid(optarg);
89			set_gid = 1;
90			break;
91		case 'm':
92			args.mode = a_mask(optarg);
93			set_mask = 1;
94			break;
95		case 'i':
96			args.flag |= NTFS_MFLAG_CASEINS;
97			break;
98		case 'a':
99			args.flag |= NTFS_MFLAG_ALLNAMES;
100			break;
101		case 'o':
102			getmntopts(optarg, mopts, &mntflags, 0);
103			break;
104		case '?':
105		default:
106			usage();
107			break;
108		}
109	}
110
111	if (optind + 2 != argc)
112		usage();
113
114	dev = argv[optind];
115	dir = argv[optind + 1];
116
117	/*
118	 * Resolve the mountpoint with realpath(3) and remove unnecessary
119	 * slashes from the devicename if there are any.
120	 */
121	(void)checkpath(dir, mntpath);
122	(void)rmslashes(dev, dev);
123
124	args.fspec = dev;
125	args.export.ex_root = 65534;	/* unchecked anyway on DOS fs */
126	if (mntflags & MNT_RDONLY)
127		args.export.ex_flags = MNT_EXRDONLY;
128	else
129		args.export.ex_flags = 0;
130	if (!set_gid || !set_uid || !set_mask) {
131		if (stat(mntpath, &sb) == -1)
132			err(EX_OSERR, "stat %s", mntpath);
133
134		if (!set_uid)
135			args.uid = sb.st_uid;
136		if (!set_gid)
137			args.gid = sb.st_gid;
138		if (!set_mask)
139			args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
140	}
141
142#if __FreeBSD_version >= 300000
143	error = getvfsbyname("ntfs", &vfc);
144	if(error && vfsisloadable("ntfs")) {
145		if(vfsload("ntfs"))
146#else
147	vfc = getvfsbyname("ntfs");
148	if(!vfc && vfsisloadable("ntfs")) {
149		if(vfsload("ntfs"))
150#endif
151			err(EX_OSERR, "vfsload(ntfs)");
152		endvfsent();	/* clear cache */
153#if __FreeBSD_version >= 300000
154		error = getvfsbyname("ntfs", &vfc);
155#else
156		vfc = getvfsbyname("ntfs");
157#endif
158	}
159#if __FreeBSD_version >= 300000
160	if (error)
161#else
162	if (!vfc)
163#endif
164		errx(EX_OSERR, "ntfs filesystem is not available");
165
166#if __FreeBSD_version >= 300000
167	if (mount(vfc.vfc_name, mntpath, mntflags, &args) < 0)
168#else
169	if (mount(vfc->vfc_index, mntpath, mntflags, &args) < 0)
170#endif
171		err(EX_OSERR, "%s", dev);
172
173	exit (0);
174}
175
176gid_t
177a_gid(s)
178	char *s;
179{
180	struct group *gr;
181	char *gname;
182	gid_t gid;
183
184	if ((gr = getgrnam(s)) != NULL)
185		gid = gr->gr_gid;
186	else {
187		for (gname = s; *s && isdigit(*s); ++s);
188		if (!*s)
189			gid = atoi(gname);
190		else
191			errx(EX_NOUSER, "unknown group id: %s", gname);
192	}
193	return (gid);
194}
195
196uid_t
197a_uid(s)
198	char *s;
199{
200	struct passwd *pw;
201	char *uname;
202	uid_t uid;
203
204	if ((pw = getpwnam(s)) != NULL)
205		uid = pw->pw_uid;
206	else {
207		for (uname = s; *s && isdigit(*s); ++s);
208		if (!*s)
209			uid = atoi(uname);
210		else
211			errx(EX_NOUSER, "unknown user id: %s", uname);
212	}
213	return (uid);
214}
215
216mode_t
217a_mask(s)
218	char *s;
219{
220	int done, rv=0;
221	char *ep;
222
223	done = 0;
224	if (*s >= '0' && *s <= '7') {
225		done = 1;
226		rv = strtol(optarg, &ep, 8);
227	}
228	if (!done || rv < 0 || *ep)
229		errx(EX_USAGE, "invalid file mode: %s", s);
230	return (rv);
231}
232
233void
234usage()
235{
236	fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] bdev dir\n");
237	exit(EX_USAGE);
238}
239