1 /* $OpenBSD: mount_ntfs.c,v 1.19 2022/08/20 07:03:24 tb Exp $ */
2 /* $NetBSD: mount_ntfs.c,v 1.9 2003/05/03 15:37:08 christos Exp $ */
3
4 /*
5 * Copyright (c) 1994 Christopher G. Demetriou
6 * Copyright (c) 1999 Semen Ustimenko
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Christopher G. Demetriou.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * Id: mount_ntfs.c,v 1.1.1.1 1999/02/03 03:51:19 semenu Exp
35 */
36
37 #include <sys/types.h>
38 #include <sys/mount.h>
39 #include <sys/stat.h>
40
41 #include <err.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <limits.h>
47 #include <grp.h>
48 #include <pwd.h>
49
50 #include <mntopts.h>
51
52 static const struct mntopt mopts[] = {
53 MOPT_STDOPTS,
54 { NULL }
55 };
56
57 static __dead void usage(void);
58 static gid_t a_gid(char *);
59 static uid_t a_uid(char *);
60 static mode_t a_mask(char *);
61
62 int
main(int argc,char * argv[])63 main(int argc, char *argv[])
64 {
65 struct ntfs_args args;
66 struct stat sb;
67 int c, mntflags, set_gid, set_uid, set_mask;
68 char *dev, dir[PATH_MAX];
69
70 mntflags = set_gid = set_uid = set_mask = 0;
71 memset(&args, 0, sizeof(args));
72
73 while ((c = getopt(argc, argv, "aiu:g:m:o:")) != -1) {
74 switch (c) {
75 case 'u':
76 args.uid = a_uid(optarg);
77 set_uid = 1;
78 break;
79 case 'g':
80 args.gid = a_gid(optarg);
81 set_gid = 1;
82 break;
83 case 'm':
84 args.mode = a_mask(optarg);
85 set_mask = 1;
86 break;
87 case 'i':
88 args.flag |= NTFS_MFLAG_CASEINS;
89 break;
90 case 'a':
91 args.flag |= NTFS_MFLAG_ALLNAMES;
92 break;
93 case 'o':
94 getmntopts(optarg, mopts, &mntflags);
95 break;
96 default:
97 usage();
98 break;
99 }
100 }
101
102 if (optind + 2 != argc)
103 usage();
104
105 dev = argv[optind];
106 if (realpath(argv[optind + 1], dir) == NULL)
107 err(1, "realpath %s", argv[optind + 1]);
108
109 args.fspec = dev;
110 args.export_info.ex_root = 65534; /* unchecked anyway on NTFS */
111
112 mntflags |= MNT_RDONLY;
113 if (mntflags & MNT_RDONLY)
114 args.export_info.ex_flags = MNT_EXRDONLY;
115 else
116 args.export_info.ex_flags = 0;
117 if (!set_gid || !set_uid || !set_mask) {
118 if (stat(dir, &sb) == -1)
119 err(1, "stat %s", dir);
120
121 if (!set_uid)
122 args.uid = sb.st_uid;
123 if (!set_gid)
124 args.gid = sb.st_gid;
125 if (!set_mask)
126 args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
127 }
128 if (mount(MOUNT_NTFS, dir, mntflags, &args) == -1)
129 err(1, "%s on %s", dev, dir);
130
131 exit(0);
132 }
133
134 gid_t
a_gid(char * s)135 a_gid(char *s)
136 {
137 struct group *gr;
138 const char *errstr;
139 gid_t gid;
140
141 if ((gr = getgrnam(s)) != NULL)
142 return gr->gr_gid;
143 gid = strtonum(s, 0, GID_MAX, &errstr);
144 if (errstr)
145 errx(1, "group is %s: %s", errstr, s);
146 return (gid);
147 }
148
149 uid_t
a_uid(char * s)150 a_uid(char *s)
151 {
152 struct passwd *pw;
153 const char *errstr;
154 uid_t uid;
155
156 if ((pw = getpwnam(s)) != NULL)
157 return pw->pw_uid;
158 uid = strtonum(s, 0, UID_MAX, &errstr);
159 if (errstr)
160 errx(1, "user is %s: %s", errstr, s);
161 return (uid);
162 }
163
164 mode_t
a_mask(char * s)165 a_mask(char *s)
166 {
167 int done, rv;
168 char *ep;
169
170 done = 0;
171 if (*s >= '0' && *s <= '7') {
172 done = 1;
173 rv = strtol(optarg, &ep, 8);
174 }
175 if (!done || rv < 0 || *ep)
176 errx(1, "invalid file mode: %s", s);
177 return (rv);
178 }
179
180 static void
usage(void)181 usage(void)
182 {
183 fprintf(stderr,
184 "usage: mount_ntfs [-ai] [-g group] [-m mask] [-o options] [-u user]"
185 " special node\n");
186 exit(1);
187 }
188