1 /* $NetBSD: mount_msdos.c,v 1.18 1997/09/16 12:24:18 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Christopher G. Demetriou 5 * All rights reserved. 6 * 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 20 * 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. 31 */ 32 33 #ifndef lint 34 static const char rcsid[] = 35 "$FreeBSD$"; 36 #endif /* not lint */ 37 38 #include <sys/param.h> 39 #include <sys/mount.h> 40 #include <sys/stat.h> 41 42 #include <fs/msdosfs/msdosfsmount.h> 43 44 #include <ctype.h> 45 #include <err.h> 46 #include <grp.h> 47 #include <locale.h> 48 #include <pwd.h> 49 #include <stdio.h> 50 /* must be after stdio to declare fparseln */ 51 #include <libutil.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <sysexits.h> 55 #include <unistd.h> 56 57 #include "mntopts.h" 58 59 /* 60 * XXX - no way to specify "foo=<bar>"-type options; that's what we'd 61 * want for "-u", "-g", "-m", "-L", and "-W". 62 */ 63 static struct mntopt mopts[] = { 64 MOPT_STDOPTS, 65 MOPT_FORCE, 66 MOPT_SYNC, 67 MOPT_UPDATE, 68 #ifdef MSDOSFSMNT_GEMDOSFS 69 { "gemdosfs", 0, MSDOSFSMNT_GEMDOSFS, 1 }, 70 #endif 71 { "shortnames", 0, MSDOSFSMNT_SHORTNAME, 1 }, 72 { "longnames", 0, MSDOSFSMNT_LONGNAME, 1 }, 73 { "nowin95", 0, MSDOSFSMNT_NOWIN95, 1 }, 74 { NULL } 75 }; 76 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 static void load_u2wtable(struct msdosfs_args *, char *); 82 static void load_ultable(struct msdosfs_args *, char *); 83 84 int 85 main(argc, argv) 86 int argc; 87 char **argv; 88 { 89 struct msdosfs_args args; 90 struct stat sb; 91 int c, mntflags, set_gid, set_uid, set_mask; 92 char *dev, *dir, mntpath[MAXPATHLEN]; 93 94 mntflags = set_gid = set_uid = set_mask = 0; 95 (void)memset(&args, '\0', sizeof(args)); 96 args.magic = MSDOSFS_ARGSMAGIC; 97 98 while ((c = getopt(argc, argv, "sl9u:g:m:o:L:W:")) != -1) { 99 switch (c) { 100 #ifdef MSDOSFSMNT_GEMDOSFS 101 case 'G': 102 args.flags |= MSDOSFSMNT_GEMDOSFS; 103 break; 104 #endif 105 case 's': 106 args.flags |= MSDOSFSMNT_SHORTNAME; 107 break; 108 case 'l': 109 args.flags |= MSDOSFSMNT_LONGNAME; 110 break; 111 case '9': 112 args.flags |= MSDOSFSMNT_NOWIN95; 113 break; 114 case 'u': 115 args.uid = a_uid(optarg); 116 set_uid = 1; 117 break; 118 case 'g': 119 args.gid = a_gid(optarg); 120 set_gid = 1; 121 break; 122 case 'm': 123 args.mask = a_mask(optarg); 124 set_mask = 1; 125 break; 126 case 'L': 127 load_ultable(&args, optarg); 128 args.flags |= MSDOSFSMNT_ULTABLE; 129 break; 130 case 'W': 131 load_u2wtable(&args, optarg); 132 args.flags |= MSDOSFSMNT_U2WTABLE; 133 break; 134 case 'o': 135 getmntopts(optarg, mopts, &mntflags, &args.flags); 136 break; 137 case '?': 138 default: 139 usage(); 140 break; 141 } 142 } 143 144 if (optind + 2 != argc) 145 usage(); 146 147 dev = argv[optind]; 148 dir = argv[optind + 1]; 149 150 /* 151 * Resolve the mountpoint with realpath(3) and remove unnecessary 152 * slashes from the devicename if there are any. 153 */ 154 (void)checkpath(dir, mntpath); 155 (void)rmslashes(dev, dev); 156 157 args.fspec = dev; 158 args.export.ex_root = -2; /* unchecked anyway on DOS fs */ 159 if (mntflags & MNT_RDONLY) 160 args.export.ex_flags = MNT_EXRDONLY; 161 else 162 args.export.ex_flags = 0; 163 if (!set_gid || !set_uid || !set_mask) { 164 if (stat(mntpath, &sb) == -1) 165 err(EX_OSERR, "stat %s", mntpath); 166 167 if (!set_uid) 168 args.uid = sb.st_uid; 169 if (!set_gid) 170 args.gid = sb.st_gid; 171 if (!set_mask) 172 args.mask = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 173 } 174 175 if (mount("msdosfs", mntpath, mntflags, &args) < 0) 176 err(EX_OSERR, "%s", dev); 177 178 exit (0); 179 } 180 181 gid_t 182 a_gid(s) 183 char *s; 184 { 185 struct group *gr; 186 char *gname; 187 gid_t gid; 188 189 if ((gr = getgrnam(s)) != NULL) 190 gid = gr->gr_gid; 191 else { 192 for (gname = s; *s && isdigit(*s); ++s); 193 if (!*s) 194 gid = atoi(gname); 195 else 196 errx(EX_NOUSER, "unknown group id: %s", gname); 197 } 198 return (gid); 199 } 200 201 uid_t 202 a_uid(s) 203 char *s; 204 { 205 struct passwd *pw; 206 char *uname; 207 uid_t uid; 208 209 if ((pw = getpwnam(s)) != NULL) 210 uid = pw->pw_uid; 211 else { 212 for (uname = s; *s && isdigit(*s); ++s); 213 if (!*s) 214 uid = atoi(uname); 215 else 216 errx(EX_NOUSER, "unknown user id: %s", uname); 217 } 218 return (uid); 219 } 220 221 mode_t 222 a_mask(s) 223 char *s; 224 { 225 int done, rv; 226 char *ep; 227 228 done = 0; 229 rv = -1; 230 if (*s >= '0' && *s <= '7') { 231 done = 1; 232 rv = strtol(optarg, &ep, 8); 233 } 234 if (!done || rv < 0 || *ep) 235 errx(EX_USAGE, "invalid file mode: %s", s); 236 return (rv); 237 } 238 239 void 240 usage() 241 { 242 fprintf(stderr, "%s\n%s\n", 243 "usage: mount_msdosfs [-o options] [-u user] [-g group] [-m mask]", 244 " [-s] [-l] [-9] [-L locale] [-W table] bdev dir"); 245 exit(EX_USAGE); 246 } 247 248 void 249 load_u2wtable (pargs, name) 250 struct msdosfs_args *pargs; 251 char *name; 252 { 253 FILE *f; 254 int i, j, code[8]; 255 size_t line = 0; 256 char buf[128]; 257 char *fn, *s, *p; 258 259 if (*name == '/') 260 fn = name; 261 else { 262 snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name); 263 buf[127] = '\0'; 264 fn = buf; 265 } 266 if ((f = fopen(fn, "r")) == NULL) 267 err(EX_NOINPUT, "%s", fn); 268 p = NULL; 269 for (i = 0; i < 16; i++) { 270 do { 271 if (p != NULL) free(p); 272 if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) 273 errx(EX_DATAERR, "can't read u2w table row %d near line %d", i, line); 274 while (isspace((unsigned char)*s)) 275 s++; 276 } while (*s == '\0'); 277 if (sscanf(s, "%i%i%i%i%i%i%i%i", 278 code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) 279 errx(EX_DATAERR, "u2w table: missing item(s) in row %d, line %d", i, line); 280 for (j = 0; j < 8; j++) 281 pargs->u2w[i * 8 + j] = code[j]; 282 } 283 for (i = 0; i < 16; i++) { 284 do { 285 free(p); 286 if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) 287 errx(EX_DATAERR, "can't read d2u table row %d near line %d", i, line); 288 while (isspace((unsigned char)*s)) 289 s++; 290 } while (*s == '\0'); 291 if (sscanf(s, "%i%i%i%i%i%i%i%i", 292 code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) 293 errx(EX_DATAERR, "d2u table: missing item(s) in row %d, line %d", i, line); 294 for (j = 0; j < 8; j++) 295 pargs->d2u[i * 8 + j] = code[j]; 296 } 297 for (i = 0; i < 16; i++) { 298 do { 299 free(p); 300 if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) 301 errx(EX_DATAERR, "can't read u2d table row %d near line %d", i, line); 302 while (isspace((unsigned char)*s)) 303 s++; 304 } while (*s == '\0'); 305 if (sscanf(s, "%i%i%i%i%i%i%i%i", 306 code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) 307 errx(EX_DATAERR, "u2d table: missing item(s) in row %d, line %d", i, line); 308 for (j = 0; j < 8; j++) 309 pargs->u2d[i * 8 + j] = code[j]; 310 } 311 free(p); 312 fclose(f); 313 } 314 315 void 316 load_ultable (pargs, name) 317 struct msdosfs_args *pargs; 318 char *name; 319 { 320 int i; 321 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); 327 } 328 } 329