mount_ntfs.c revision 78735
1184610Salfred/*
2184610Salfred * Copyright (c) 1994 Christopher G. Demetriou
3199575Sthompsa * Copyright (c) 1999 Semen Ustimenko
4184610Salfred * All rights reserved.
5184610Salfred *
6184610Salfred * Redistribution and use in source and binary forms, with or without
7184610Salfred * modification, are permitted provided that the following conditions
8184610Salfred * are met:
9184610Salfred * 1. Redistributions of source code must retain the above copyright
10184610Salfred *    notice, this list of conditions and the following disclaimer.
11184610Salfred * 2. Redistributions in binary form must reproduce the above copyright
12184610Salfred *    notice, this list of conditions and the following disclaimer in the
13184610Salfred *    documentation and/or other materials provided with the distribution.
14184610Salfred * 3. All advertising materials mentioning features or use of this software
15184610Salfred *    must display the following acknowledgement:
16184610Salfred *      This product includes software developed by Christopher G. Demetriou.
17184610Salfred * 4. The name of the author may not be used to endorse or promote products
18184610Salfred *    derived from this software without specific prior written permission
19184610Salfred *
20184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21184610Salfred * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22184610Salfred * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23184610Salfred * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24184610Salfred * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25184610Salfred * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26184610Salfred * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27248236Shselasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28248236Shselasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29248236Shselasky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30203815Swkoszek *
31203815Swkoszek * $FreeBSD: head/sbin/mount_ntfs/mount_ntfs.c 78735 2001-06-24 23:31:07Z dd $
32184610Salfred *
33184610Salfred */
34184610Salfred
35248236Shselasky#include <sys/cdefs.h>
36248236Shselasky#include <sys/param.h>
37248236Shselasky#define NTFS
38184610Salfred#include <sys/mount.h>
39184610Salfred#include <sys/stat.h>
40184610Salfred#include <fs/ntfs/ntfsmount.h>
41184610Salfred#include <ctype.h>
42184610Salfred#include <err.h>
43184610Salfred#include <grp.h>
44184610Salfred#include <pwd.h>
45184610Salfred#include <stdio.h>
46184610Salfred#include <stdlib.h>
47184610Salfred#include <string.h>
48184610Salfred#include <sysexits.h>
49184610Salfred#include <unistd.h>
50184610Salfred
51184610Salfred#include "mntopts.h"
52184610Salfred
53184610Salfredstatic struct mntopt mopts[] = {
54184610Salfred	MOPT_STDOPTS,
55184610Salfred	{ NULL }
56184610Salfred};
57184610Salfred
58184610Salfredstatic gid_t	a_gid __P((char *));
59184610Salfredstatic uid_t	a_uid __P((char *));
60184610Salfredstatic mode_t	a_mask __P((char *));
61184610Salfredstatic void	usage __P((void)) __dead2;
62184610Salfred
63184610Salfredint
64184610Salfredmain(argc, argv)
65184610Salfred	int argc;
66184610Salfred	char **argv;
67184610Salfred{
68184610Salfred	struct ntfs_args args;
69184610Salfred	struct stat sb;
70184610Salfred	int c, mntflags, set_gid, set_uid, set_mask, error;
71184610Salfred	char *dev, *dir, mntpath[MAXPATHLEN];
72184610Salfred#if __FreeBSD_version >= 300000
73184610Salfred	struct vfsconf vfc;
74184610Salfred#else
75203147Sthompsa	struct vfsconf *vfc;
76184610Salfred#endif
77184610Salfred
78250201Shselasky	mntflags = set_gid = set_uid = set_mask = 0;
79246789Shselasky	(void)memset(&args, '\0', sizeof(args));
80184610Salfred
81184610Salfred	while ((c = getopt(argc, argv, "aiu:g:m:o:")) !=  -1) {
82184610Salfred		switch (c) {
83184610Salfred		case 'u':
84184610Salfred			args.uid = a_uid(optarg);
85184610Salfred			set_uid = 1;
86184610Salfred			break;
87188622Sthompsa		case 'g':
88188622Sthompsa			args.gid = a_gid(optarg);
89184610Salfred			set_gid = 1;
90184610Salfred			break;
91184610Salfred		case 'm':
92184610Salfred			args.mode = a_mask(optarg);
93184610Salfred			set_mask = 1;
94184610Salfred			break;
95184610Salfred		case 'i':
96184610Salfred			args.flag |= NTFS_MFLAG_CASEINS;
97184610Salfred			break;
98184610Salfred		case 'a':
99184610Salfred			args.flag |= NTFS_MFLAG_ALLNAMES;
100184610Salfred			break;
101184610Salfred		case 'o':
102184610Salfred			getmntopts(optarg, mopts, &mntflags, 0);
103184610Salfred			break;
104184610Salfred		case '?':
105184610Salfred		default:
106184610Salfred			usage();
107184610Salfred			break;
108184610Salfred		}
109184610Salfred	}
110188622Sthompsa
111184610Salfred	if (optind + 2 != argc)
112184610Salfred		usage();
113184610Salfred
114184610Salfred	dev = argv[optind];
115184610Salfred	dir = argv[optind + 1];
116184610Salfred
117184610Salfred	/*
118184610Salfred	 * Resolve the mountpoint with realpath(3) and remove unnecessary
119184610Salfred	 * slashes from the devicename if there are any.
120188622Sthompsa	 */
121184610Salfred	(void)checkpath(dir, mntpath);
122184610Salfred	(void)rmslashes(dev, dev);
123184610Salfred
124184610Salfred	args.fspec = dev;
125184610Salfred	args.export.ex_root = 65534;	/* unchecked anyway on DOS fs */
126184610Salfred	if (mntflags & MNT_RDONLY)
127184610Salfred		args.export.ex_flags = MNT_EXRDONLY;
128184610Salfred	else
129184610Salfred		args.export.ex_flags = 0;
130184610Salfred	if (!set_gid || !set_uid || !set_mask) {
131184610Salfred		if (stat(mntpath, &sb) == -1)
132184610Salfred			err(EX_OSERR, "stat %s", mntpath);
133188622Sthompsa
134184610Salfred		if (!set_uid)
135184610Salfred			args.uid = sb.st_uid;
136184610Salfred		if (!set_gid)
137184610Salfred			args.gid = sb.st_gid;
138184610Salfred		if (!set_mask)
139184610Salfred			args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
140184610Salfred	}
141202025Sthompsa
142297764Spfg#if __FreeBSD_version >= 300000
143297764Spfg	error = getvfsbyname("ntfs", &vfc);
144184610Salfred	if(error && vfsisloadable("ntfs")) {
145202025Sthompsa		if(vfsload("ntfs"))
146202025Sthompsa#else
147202025Sthompsa	vfc = getvfsbyname("ntfs");
148202025Sthompsa	if(!vfc && vfsisloadable("ntfs")) {
149202025Sthompsa		if(vfsload("ntfs"))
150202025Sthompsa#endif
151202025Sthompsa			err(EX_OSERR, "vfsload(ntfs)");
152202025Sthompsa		endvfsent();	/* clear cache */
153202025Sthompsa#if __FreeBSD_version >= 300000
154184610Salfred		error = getvfsbyname("ntfs", &vfc);
155184610Salfred#else
156184610Salfred		vfc = getvfsbyname("ntfs");
157184610Salfred#endif
158184610Salfred	}
159184610Salfred#if __FreeBSD_version >= 300000
160184610Salfred	if (error)
161184610Salfred#else
162184610Salfred	if (!vfc)
163184610Salfred#endif
164239239Shselasky		errx(EX_OSERR, "ntfs filesystem is not available");
165239239Shselasky
166239239Shselasky#if __FreeBSD_version >= 300000
167239239Shselasky	if (mount(vfc.vfc_name, mntpath, mntflags, &args) < 0)
168239239Shselasky#else
169239239Shselasky	if (mount(vfc->vfc_index, mntpath, mntflags, &args) < 0)
170239239Shselasky#endif
171184610Salfred		err(EX_OSERR, "%s", dev);
172219100Shselasky
173184610Salfred	exit (0);
174184610Salfred}
175219100Shselasky
176184610Salfredgid_t
177219100Shselaskya_gid(s)
178219100Shselasky	char *s;
179219100Shselasky{
180219100Shselasky	struct group *gr;
181219100Shselasky	char *gname;
182184610Salfred	gid_t gid;
183219100Shselasky
184184610Salfred	if ((gr = getgrnam(s)) != NULL)
185219100Shselasky		gid = gr->gr_gid;
186184610Salfred	else {
187184610Salfred		for (gname = s; *s && isdigit(*s); ++s);
188184610Salfred		if (!*s)
189184610Salfred			gid = atoi(gname);
190184610Salfred		else
191184610Salfred			errx(EX_NOUSER, "unknown group id: %s", gname);
192184610Salfred	}
193184610Salfred	return (gid);
194184610Salfred}
195184610Salfred
196184610Salfreduid_t
197184610Salfreda_uid(s)
198184610Salfred	char *s;
199184610Salfred{
200184610Salfred	struct passwd *pw;
201184610Salfred	char *uname;
202184610Salfred	uid_t uid;
203188622Sthompsa
204239239Shselasky	if ((pw = getpwnam(s)) != NULL)
205184610Salfred		uid = pw->pw_uid;
206184610Salfred	else {
207184610Salfred		for (uname = s; *s && isdigit(*s); ++s);
208184610Salfred		if (!*s)
209184610Salfred			uid = atoi(uname);
210184610Salfred		else
211184610Salfred			errx(EX_NOUSER, "unknown user id: %s", uname);
212184610Salfred	}
213184610Salfred	return (uid);
214184610Salfred}
215184610Salfred
216184610Salfredmode_t
217184610Salfreda_mask(s)
218184610Salfred	char *s;
219184610Salfred{
220184610Salfred	int done, rv=0;
221184610Salfred	char *ep;
222184610Salfred
223184610Salfred	done = 0;
224184610Salfred	if (*s >= '0' && *s <= '7') {
225184610Salfred		done = 1;
226184610Salfred		rv = strtol(optarg, &ep, 8);
227184610Salfred	}
228184610Salfred	if (!done || rv < 0 || *ep)
229184610Salfred		errx(EX_USAGE, "invalid file mode: %s", s);
230184610Salfred	return (rv);
231184610Salfred}
232184610Salfred
233184610Salfredvoid
234184610Salfredusage()
235184610Salfred{
236184610Salfred	fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] bdev dir\n");
237184610Salfred	exit(EX_USAGE);
238184610Salfred}
239184610Salfred