Implement non-booting support for the DragonFly 64 bit disklabel:
[dragonfly/vkernel-mp.git] / sbin / mount_msdos / mount_msdos.c
blob542900a6786ad18f6cbadbed83d0daf186aa929e
1 /* $NetBSD: mount_msdos.c,v 1.18 1997/09/16 12:24:18 lukem Exp $ */
3 /*
4 * Copyright (c) 1994 Christopher G. Demetriou
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Christopher G. Demetriou.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: src/sbin/mount_msdos/mount_msdos.c,v 1.19.2.1 2000/07/20 10:35:13 kris Exp $
33 * $DragonFly: src/sbin/mount_msdos/mount_msdos.c,v 1.7 2005/04/02 23:41:06 dillon Exp $
36 #include <sys/param.h>
37 #include <sys/mount.h>
38 #include <sys/stat.h>
40 #include <vfs/msdosfs/msdosfsmount.h>
42 #include <ctype.h>
43 #include <err.h>
44 #include <grp.h>
45 #include <locale.h>
46 #include <pwd.h>
47 #include <stdio.h>
48 /* must be after stdio to declare fparseln */
49 #include <libutil.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <sysexits.h>
53 #include <unistd.h>
55 #include "mntopts.h"
58 * XXX - no way to specify "foo=<bar>"-type options; that's what we'd
59 * want for "-u", "-g", "-m", "-L", and "-W".
61 static struct mntopt mopts[] = {
62 MOPT_STDOPTS,
63 MOPT_FORCE,
64 MOPT_SYNC,
65 MOPT_UPDATE,
66 #ifdef MSDOSFSMNT_GEMDOSFS
67 { "gemdosfs", 0, MSDOSFSMNT_GEMDOSFS, 1 },
68 #endif
69 { "shortnames", 0, MSDOSFSMNT_SHORTNAME, 1 },
70 { "longnames", 0, MSDOSFSMNT_LONGNAME, 1 },
71 { "nowin95", 0, MSDOSFSMNT_NOWIN95, 1 },
72 MOPT_NULL
75 static gid_t a_gid(char *);
76 static uid_t a_uid(char *);
77 static mode_t a_mask(char *);
78 static void usage(void) __dead2;
79 static void load_u2wtable(struct msdosfs_args *, char *);
80 static void load_ultable(struct msdosfs_args *, char *);
82 int
83 main(int argc, char **argv)
85 struct msdosfs_args args;
86 struct stat sb;
87 int c, error, mntflags, set_gid, set_uid, set_mask;
88 char *dev, *dir, mntpath[MAXPATHLEN];
89 struct vfsconf vfc;
91 mntflags = set_gid = set_uid = set_mask = 0;
92 memset(&args, '\0', sizeof(args));
93 args.magic = MSDOSFS_ARGSMAGIC;
95 while ((c = getopt(argc, argv, "sl9u:g:m:o:L:W:")) != -1) {
96 switch (c) {
97 #ifdef MSDOSFSMNT_GEMDOSFS
98 case 'G':
99 args.flags |= MSDOSFSMNT_GEMDOSFS;
100 break;
101 #endif
102 case 's':
103 args.flags |= MSDOSFSMNT_SHORTNAME;
104 break;
105 case 'l':
106 args.flags |= MSDOSFSMNT_LONGNAME;
107 break;
108 case '9':
109 args.flags |= MSDOSFSMNT_NOWIN95;
110 break;
111 case 'u':
112 args.uid = a_uid(optarg);
113 set_uid = 1;
114 break;
115 case 'g':
116 args.gid = a_gid(optarg);
117 set_gid = 1;
118 break;
119 case 'm':
120 args.mask = a_mask(optarg);
121 set_mask = 1;
122 break;
123 case 'L':
124 load_ultable(&args, optarg);
125 args.flags |= MSDOSFSMNT_ULTABLE;
126 break;
127 case 'W':
128 load_u2wtable(&args, optarg);
129 args.flags |= MSDOSFSMNT_U2WTABLE;
130 break;
131 case 'o':
132 getmntopts(optarg, mopts, &mntflags, &args.flags);
133 break;
134 case '?':
135 default:
136 usage();
137 break;
141 if (optind + 2 != argc)
142 usage();
144 dev = argv[optind];
145 dir = argv[optind + 1];
148 * Resolve the mountpoint with realpath(3) and remove unnecessary
149 * slashes from the devicename if there are any.
151 checkpath(dir, mntpath);
152 rmslashes(dev, dev);
154 args.fspec = dev;
155 args.export.ex_root = -2; /* unchecked anyway on DOS fs */
156 if (mntflags & MNT_RDONLY)
157 args.export.ex_flags = MNT_EXRDONLY;
158 else
159 args.export.ex_flags = 0;
160 if (!set_gid || !set_uid || !set_mask) {
161 if (stat(mntpath, &sb) == -1)
162 err(EX_OSERR, "stat %s", mntpath);
164 if (!set_uid)
165 args.uid = sb.st_uid;
166 if (!set_gid)
167 args.gid = sb.st_gid;
168 if (!set_mask)
169 args.mask = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
172 error = getvfsbyname("msdos", &vfc);
173 if (error && vfsisloadable("msdos")) {
174 if (vfsload("msdos"))
175 err(EX_OSERR, "vfsload(msdos)");
176 endvfsent(); /* clear cache */
177 error = getvfsbyname("msdos", &vfc);
179 if (error)
180 errx(EX_OSERR, "msdos filesystem is not available");
182 if (mount(vfc.vfc_name, mntpath, mntflags, &args) < 0)
183 err(EX_OSERR, "%s", dev);
185 exit (0);
188 static gid_t
189 a_gid(char *s)
191 struct group *gr;
192 char *gname;
193 gid_t gid;
195 if ((gr = getgrnam(s)) != NULL)
196 gid = gr->gr_gid;
197 else {
198 for (gname = s; *s && isdigit(*s); ++s);
199 if (!*s)
200 gid = atoi(gname);
201 else
202 errx(EX_NOUSER, "unknown group id: %s", gname);
204 return (gid);
207 static uid_t
208 a_uid(char *s)
210 struct passwd *pw;
211 char *uname;
212 uid_t uid;
214 if ((pw = getpwnam(s)) != NULL)
215 uid = pw->pw_uid;
216 else {
217 for (uname = s; *s && isdigit(*s); ++s);
218 if (!*s)
219 uid = atoi(uname);
220 else
221 errx(EX_NOUSER, "unknown user id: %s", uname);
223 return (uid);
226 static mode_t
227 a_mask(char *s)
229 int done, rv;
230 char *ep;
232 done = 0;
233 rv = -1;
234 if (*s >= '0' && *s <= '7') {
235 done = 1;
236 rv = strtol(optarg, &ep, 8);
238 if (!done || rv < 0 || *ep)
239 errx(EX_USAGE, "invalid file mode: %s", s);
240 return (rv);
243 static void
244 usage(void)
246 fprintf(stderr, "%s\n%s\n",
247 "usage: mount_msdos [-o options] [-u user] [-g group] [-m mask]",
248 " [-s] [-l] [-9] [-L locale] [-W table] bdev dir");
249 exit(EX_USAGE);
252 static void
253 load_u2wtable (struct msdosfs_args *pargs, char *name)
255 FILE *f;
256 int i, j, code[8];
257 size_t line = 0;
258 char buf[128];
259 char *fn, *s, *p;
261 if (*name == '/')
262 fn = name;
263 else {
264 snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name);
265 buf[127] = '\0';
266 fn = buf;
268 if ((f = fopen(fn, "r")) == NULL)
269 err(EX_NOINPUT, "%s", fn);
270 p = NULL;
271 for (i = 0; i < 16; i++) {
272 do {
273 if (p != NULL) free(p);
274 if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL)
275 errx(EX_DATAERR, "can't read u2w table row %d near line %d", i, line);
276 while (isspace((unsigned char)*s))
277 s++;
278 } while (*s == '\0');
279 if (sscanf(s, "%i%i%i%i%i%i%i%i",
280 code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8)
281 errx(EX_DATAERR, "u2w table: missing item(s) in row %d, line %d", i, line);
282 for (j = 0; j < 8; j++)
283 pargs->u2w[i * 8 + j] = code[j];
285 for (i = 0; i < 16; i++) {
286 do {
287 free(p);
288 if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL)
289 errx(EX_DATAERR, "can't read d2u table row %d near line %d", i, line);
290 while (isspace((unsigned char)*s))
291 s++;
292 } while (*s == '\0');
293 if (sscanf(s, "%i%i%i%i%i%i%i%i",
294 code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8)
295 errx(EX_DATAERR, "d2u table: missing item(s) in row %d, line %d", i, line);
296 for (j = 0; j < 8; j++)
297 pargs->d2u[i * 8 + j] = code[j];
299 for (i = 0; i < 16; i++) {
300 do {
301 free(p);
302 if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL)
303 errx(EX_DATAERR, "can't read u2d table row %d near line %d", i, line);
304 while (isspace((unsigned char)*s))
305 s++;
306 } while (*s == '\0');
307 if (sscanf(s, "%i%i%i%i%i%i%i%i",
308 code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8)
309 errx(EX_DATAERR, "u2d table: missing item(s) in row %d, line %d", i, line);
310 for (j = 0; j < 8; j++)
311 pargs->u2d[i * 8 + j] = code[j];
313 free(p);
314 fclose(f);
317 static void
318 load_ultable (struct msdosfs_args *pargs, char *name)
320 int i;
322 if (setlocale(LC_CTYPE, name) == NULL)
323 err(EX_CONFIG, "%s", name);
324 for (i = 0; i < 128; i++) {
325 pargs->ul[i] = tolower(i | 0x80);
326 pargs->lu[i] = toupper(i | 0x80);