1 /* $NetBSD: mount_msdos.c,v 1.18 1997/09/16 12:24:18 lukem Exp $ */
4 * SPDX-License-Identifier: BSD-4-Clause
6 * Copyright (c) 1994 Christopher G. Demetriou
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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.
35 #include <sys/param.h>
36 #include <sys/mount.h>
38 #include <sys/iconv.h>
39 #include <sys/linker.h>
40 #include <sys/module.h>
41 #include <vfs/msdosfs/msdosfsmount.h>
57 * XXX - no way to specify "foo=<bar>"-type options; that's what we'd
58 * want for "-u", "-g", "-m", "-M", "-L", and "-D".
60 static struct mntopt mopts
[] = {
66 { "shortnames", 0, MSDOSFSMNT_SHORTNAME
, 1 },
67 { "longnames", 0, MSDOSFSMNT_LONGNAME
, 1 },
68 { "nowin95", 0, MSDOSFSMNT_NOWIN95
, 1 },
72 static gid_t
a_gid(char *);
73 static uid_t
a_uid(char *);
74 static mode_t
a_mask(char *);
75 static void usage(void) __dead2
;
76 int set_charset(struct msdosfs_args
*, const char *, const char *);
79 main(int argc
, char **argv
)
81 struct msdosfs_args args
;
83 int c
, error
, mntflags
, set_gid
, set_uid
, set_mask
, set_dirmask
;
84 char *dev
, *dir
, mntpath
[MAXPATHLEN
], *csp
;
85 const char *quirk
= NULL
;
86 char *cs_local
= NULL
;
89 mntflags
= set_gid
= set_uid
= set_mask
= set_dirmask
= 0;
90 memset(&args
, '\0', sizeof(args
));
92 while ((c
= getopt(argc
, argv
, "sl9u:g:m:M:o:L:D:")) != -1) {
95 args
.flags
|= MSDOSFSMNT_SHORTNAME
;
98 args
.flags
|= MSDOSFSMNT_LONGNAME
;
101 args
.flags
|= MSDOSFSMNT_NOWIN95
;
104 args
.uid
= a_uid(optarg
);
108 args
.gid
= a_gid(optarg
);
112 args
.mask
= a_mask(optarg
);
116 args
.dirmask
= a_mask(optarg
);
120 if (setlocale(LC_CTYPE
, optarg
) == NULL
)
121 err(EX_CONFIG
, "%s", optarg
);
122 csp
= strchr(optarg
,'.');
124 err(EX_CONFIG
, "%s", optarg
);
125 quirk
= kiconv_quirkcs(csp
+ 1, KICONV_VENDOR_MICSFT
);
126 cs_local
= strdup(quirk
);
127 args
.flags
|= MSDOSFSMNT_KICONV
;
131 cs_dos
= strdup(optarg
);
132 args
.flags
|= MSDOSFSMNT_KICONV
;
135 getmntopts(optarg
, mopts
, &mntflags
, &args
.flags
);
144 if (optind
+ 2 != argc
)
147 if (set_mask
&& !set_dirmask
) {
148 args
.dirmask
= args
.mask
;
151 else if (set_dirmask
&& !set_mask
) {
152 args
.mask
= args
.dirmask
;
157 dir
= argv
[optind
+ 1];
160 * Resolve the mountpoint with realpath(3) and remove unnecessary
161 * slashes from the devicename if there are any.
163 checkpath(dir
, mntpath
);
167 * If the device path is not absolute then automatically
168 * add the /dev prefix.
171 asprintf(&args
.fspec
, "/dev/%s", dev
);
174 args
.export
.ex_root
= -2; /* unchecked anyway on DOS fs */
176 if (cs_local
!= NULL
) {
177 if (set_charset(&args
, cs_local
, cs_dos
) == -1)
178 err(EX_OSERR
, "msdos_iconv");
179 } else if (cs_dos
!= NULL
) {
180 if (set_charset(&args
, "ISO8859-1", cs_dos
) == -1)
181 err(EX_OSERR
, "msdos_iconv");
184 if (mntflags
& MNT_RDONLY
)
185 args
.export
.ex_flags
= MNT_EXRDONLY
;
187 args
.export
.ex_flags
= 0;
188 if (!set_gid
|| !set_uid
|| !set_mask
) {
189 if (stat(mntpath
, &sb
) == -1)
190 err(EX_OSERR
, "stat %s", mntpath
);
193 args
.uid
= sb
.st_uid
;
195 args
.gid
= sb
.st_gid
;
197 args
.mask
= args
.dirmask
=
198 sb
.st_mode
& (S_IRWXU
| S_IRWXG
| S_IRWXO
);
201 error
= getvfsbyname("msdos", &vfc
);
202 if (error
&& vfsisloadable("msdos")) {
203 if (vfsload("msdos"))
204 err(EX_OSERR
, "vfsload(msdos)");
205 endvfsent(); /* clear cache */
206 error
= getvfsbyname("msdos", &vfc
);
209 errx(EX_OSERR
, "msdos filesystem is not available");
211 if (mount(vfc
.vfc_name
, mntpath
, mntflags
, &args
) < 0)
212 err(EX_OSERR
, "%s", dev
);
224 if ((gr
= getgrnam(s
)) != NULL
)
227 for (gname
= s
; *s
&& isdigit(*s
); ++s
);
231 errx(EX_NOUSER
, "unknown group id: %s", gname
);
243 if ((pw
= getpwnam(s
)) != NULL
)
246 for (uname
= s
; *s
&& isdigit(*s
); ++s
);
250 errx(EX_NOUSER
, "unknown user id: %s", uname
);
263 if (*s
>= '0' && *s
<= '7') {
265 rv
= strtol(optarg
, &ep
, 8);
267 if (!done
|| rv
< 0 || *ep
)
268 errx(EX_USAGE
, "invalid file mode: %s", s
);
275 fprintf(stderr
, "%s\n%s\n%s\n",
276 "usage: mount_msdos [-9ls] [-D DOS_codepage] [-g gid] [-L locale]",
277 " [-M mask] [-m mask] [-o options] [-u uid]",
283 set_charset(struct msdosfs_args
*args
, const char *cs_local
, const char *cs_dos
)
286 if (modfind("msdos_iconv") < 0) {
287 if (kldload("msdos_iconv") < 0 || modfind("msdos_iconv") < 0) {
288 warnx("cannot find or load \"msdos_iconv\" kernel module");
292 snprintf(args
->cs_local
, ICONV_CSNMAXLEN
, "%s", cs_local
);
293 error
= kiconv_add_xlat16_cspairs(ENCODING_UNICODE
, cs_local
);
297 cs_dos
= strdup("CP437");
298 snprintf(args
->cs_dos
, ICONV_CSNMAXLEN
, "%s", cs_dos
);
299 error
= kiconv_add_xlat16_cspairs(cs_dos
, cs_local
);