mount_ntfs.c revision 43548
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 * $Id: mount_ntfs.c,v 1.2 1999/02/02 01:47:22 semen Exp $
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];
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	if (dir[0] != '/') {
117		warnx("\"%s\" is a relative path", dir);
118		if (getcwd(ndir, sizeof(ndir)) == NULL)
119			err(EX_OSERR, "getcwd");
120		strncat(ndir, "/", sizeof(ndir) - strlen(ndir) - 1);
121		strncat(ndir, dir, sizeof(ndir) - strlen(ndir) - 1);
122		dir = ndir;
123		warnx("using \"%s\" instead", dir);
124	}
125
126	args.fspec = dev;
127	args.export.ex_root = 65534;	/* unchecked anyway on DOS fs */
128	if (mntflags & MNT_RDONLY)
129		args.export.ex_flags = MNT_EXRDONLY;
130	else
131		args.export.ex_flags = 0;
132	if (!set_gid || !set_uid || !set_mask) {
133		if (stat(dir, &sb) == -1)
134			err(EX_OSERR, "stat %s", dir);
135
136		if (!set_uid)
137			args.uid = sb.st_uid;
138		if (!set_gid)
139			args.gid = sb.st_gid;
140		if (!set_mask)
141			args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
142	}
143
144#if __FreeBSD_version >= 300000
145	error = getvfsbyname("ntfs", &vfc);
146	if(error && vfsisloadable("ntfs")) {
147		if(vfsload("ntfs"))
148#else
149	vfc = getvfsbyname("ntfs");
150	if(!vfc && vfsisloadable("ntfs")) {
151		if(vfsload("ntfs"))
152#endif
153			err(EX_OSERR, "vfsload(ntfs)");
154		endvfsent();	/* clear cache */
155#if __FreeBSD_version >= 300000
156		error = getvfsbyname("ntfs", &vfc);
157#else
158		vfc = getvfsbyname("ntfs");
159#endif
160	}
161#if __FreeBSD_version >= 300000
162	if (error)
163#else
164	if (!vfc)
165#endif
166		errx(EX_OSERR, "ntfs filesystem is not available");
167
168#if __FreeBSD_version >= 300000
169	if (mount(vfc.vfc_name, dir, mntflags, &args) < 0)
170#else
171	if (mount(vfc->vfc_index, dir, mntflags, &args) < 0)
172#endif
173		err(EX_OSERR, "%s", dev);
174
175	exit (0);
176}
177
178gid_t
179a_gid(s)
180	char *s;
181{
182	struct group *gr;
183	char *gname;
184	gid_t gid;
185
186	if ((gr = getgrnam(s)) != NULL)
187		gid = gr->gr_gid;
188	else {
189		for (gname = s; *s && isdigit(*s); ++s);
190		if (!*s)
191			gid = atoi(gname);
192		else
193			errx(EX_NOUSER, "unknown group id: %s", gname);
194	}
195	return (gid);
196}
197
198uid_t
199a_uid(s)
200	char *s;
201{
202	struct passwd *pw;
203	char *uname;
204	uid_t uid;
205
206	if ((pw = getpwnam(s)) != NULL)
207		uid = pw->pw_uid;
208	else {
209		for (uname = s; *s && isdigit(*s); ++s);
210		if (!*s)
211			uid = atoi(uname);
212		else
213			errx(EX_NOUSER, "unknown user id: %s", uname);
214	}
215	return (uid);
216}
217
218mode_t
219a_mask(s)
220	char *s;
221{
222	int done, rv=0;
223	char *ep;
224
225	done = 0;
226	if (*s >= '0' && *s <= '7') {
227		done = 1;
228		rv = strtol(optarg, &ep, 8);
229	}
230	if (!done || rv < 0 || *ep)
231		errx(EX_USAGE, "invalid file mode: %s", s);
232	return (rv);
233}
234
235void
236usage()
237{
238	fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] bdev dir\n");
239	exit(EX_USAGE);
240}
241