1 /* $NetBSD: mount_msdos.c,v 1.18 1997/09/16 12:24:18 lukem Exp $ */
4 * Copyright (c) 1994 Christopher G. Demetriou
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.8 2008/11/02 21:52:46 swildner Exp $
36 #include <sys/param.h>
37 #include <sys/mount.h>
39 #include <sys/iconv.h>
40 #include <sys/linker.h>
41 #include <sys/module.h>
42 #include <vfs/msdosfs/msdosfsmount.h>
50 /* must be after stdio to declare fparseln */
60 * XXX - no way to specify "foo=<bar>"-type options; that's what we'd
61 * want for "-u", "-g", "-m", "-L", and "-D".
63 static struct mntopt mopts
[] = {
68 #ifdef MSDOSFSMNT_GEMDOSFS
69 { "gemdosfs", 0, MSDOSFSMNT_GEMDOSFS
, 1 },
71 { "shortnames", 0, MSDOSFSMNT_SHORTNAME
, 1 },
72 { "longnames", 0, MSDOSFSMNT_LONGNAME
, 1 },
73 { "nowin95", 0, MSDOSFSMNT_NOWIN95
, 1 },
77 static gid_t
a_gid(char *);
78 static uid_t
a_uid(char *);
79 static mode_t
a_mask(char *);
80 static void usage(void) __dead2
;
81 int set_charset(struct msdosfs_args
*, const char*, const char*);
84 main(int argc
, char **argv
)
86 struct msdosfs_args args
;
88 int c
, error
, mntflags
, set_gid
, set_uid
, set_mask
;
89 char *dev
, *dir
, mntpath
[MAXPATHLEN
], *csp
;
90 const char *quirk
= NULL
;
91 char *cs_local
= NULL
;
94 mntflags
= set_gid
= set_uid
= set_mask
= 0;
95 memset(&args
, '\0', sizeof(args
));
96 args
.magic
= MSDOSFS_ARGSMAGIC
;
98 while ((c
= getopt(argc
, argv
, "sl9u:g:m:o:L:D:")) != -1) {
100 #ifdef MSDOSFSMNT_GEMDOSFS
102 args
.flags
|= MSDOSFSMNT_GEMDOSFS
;
106 args
.flags
|= MSDOSFSMNT_SHORTNAME
;
109 args
.flags
|= MSDOSFSMNT_LONGNAME
;
112 args
.flags
|= MSDOSFSMNT_NOWIN95
;
115 args
.uid
= a_uid(optarg
);
119 args
.gid
= a_gid(optarg
);
123 args
.mask
= a_mask(optarg
);
127 if (setlocale(LC_CTYPE
, optarg
) == NULL
)
128 err(EX_CONFIG
, "%s", optarg
);
129 csp
= strchr(optarg
,'.');
131 err(EX_CONFIG
, "%s", optarg
);
132 quirk
= kiconv_quirkcs(csp
+ 1, KICONV_VENDOR_MICSFT
);
133 cs_local
= strdup(quirk
);
134 args
.flags
|= MSDOSFSMNT_KICONV
;
138 cs_dos
= strdup(optarg
);
139 args
.flags
|= MSDOSFSMNT_KICONV
;
142 getmntopts(optarg
, mopts
, &mntflags
, &args
.flags
);
151 if (optind
+ 2 != argc
)
155 dir
= argv
[optind
+ 1];
158 * Resolve the mountpoint with realpath(3) and remove unnecessary
159 * slashes from the devicename if there are any.
161 checkpath(dir
, mntpath
);
165 args
.export
.ex_root
= -2; /* unchecked anyway on DOS fs */
167 if (cs_local
!= NULL
) {
168 if (set_charset(&args
, cs_local
, cs_dos
) == -1)
169 err(EX_OSERR
, "msdos_iconv");
170 } else if (cs_dos
!= NULL
) {
171 if (set_charset(&args
, "ISO8859-1", cs_dos
) == -1)
172 err(EX_OSERR
, "msdos_iconv");
175 if (mntflags
& MNT_RDONLY
)
176 args
.export
.ex_flags
= MNT_EXRDONLY
;
178 args
.export
.ex_flags
= 0;
179 if (!set_gid
|| !set_uid
|| !set_mask
) {
180 if (stat(mntpath
, &sb
) == -1)
181 err(EX_OSERR
, "stat %s", mntpath
);
184 args
.uid
= sb
.st_uid
;
186 args
.gid
= sb
.st_gid
;
188 args
.mask
= sb
.st_mode
& (S_IRWXU
| S_IRWXG
| S_IRWXO
);
191 error
= getvfsbyname("msdos", &vfc
);
192 if (error
&& vfsisloadable("msdos")) {
193 if (vfsload("msdos"))
194 err(EX_OSERR
, "vfsload(msdos)");
195 endvfsent(); /* clear cache */
196 error
= getvfsbyname("msdos", &vfc
);
199 errx(EX_OSERR
, "msdos filesystem is not available");
201 if (mount(vfc
.vfc_name
, mntpath
, mntflags
, &args
) < 0)
202 err(EX_OSERR
, "%s", dev
);
214 if ((gr
= getgrnam(s
)) != NULL
)
217 for (gname
= s
; *s
&& isdigit(*s
); ++s
);
221 errx(EX_NOUSER
, "unknown group id: %s", gname
);
233 if ((pw
= getpwnam(s
)) != NULL
)
236 for (uname
= s
; *s
&& isdigit(*s
); ++s
);
240 errx(EX_NOUSER
, "unknown user id: %s", uname
);
253 if (*s
>= '0' && *s
<= '7') {
255 rv
= strtol(optarg
, &ep
, 8);
257 if (!done
|| rv
< 0 || *ep
)
258 errx(EX_USAGE
, "invalid file mode: %s", s
);
265 fprintf(stderr
, "%s\n%s\n",
266 "usage: mount_msdos [-o options] [-u user] [-g group] [-m mask]",
267 " [-s] [-l] [-9] [-L locale] [-D codepage] bdev dir");
272 set_charset(struct msdosfs_args
*args
, const char *cs_local
, const char *cs_dos
)
275 if (modfind("msdos_iconv") < 0) {
276 if (kldload("msdos_iconv") < 0 || modfind("msdos_iconv") < 0)
278 warnx("cannot find or load \"msdos_iconv\" kernel module");
282 snprintf(args
->cs_local
, ICONV_CSNMAXLEN
, "%s", cs_local
);
283 error
= kiconv_add_xlat16_cspairs(ENCODING_UNICODE
, cs_local
);
287 cs_dos
= strdup("CP437");
288 snprintf(args
->cs_dos
, ICONV_CSNMAXLEN
, "%s", cs_dos
);
289 error
= kiconv_add_xlat16_cspairs(cs_dos
, cs_local
);