154371Ssemenu/* 254371Ssemenu * Copyright (c) 1994 Christopher G. Demetriou 354371Ssemenu * Copyright (c) 1999 Semen Ustimenko (semenu@FreeBSD.org) 454371Ssemenu * All rights reserved. 554371Ssemenu * 654371Ssemenu * Redistribution and use in source and binary forms, with or without 754371Ssemenu * modification, are permitted provided that the following conditions 854371Ssemenu * are met: 954371Ssemenu * 1. Redistributions of source code must retain the above copyright 1054371Ssemenu * notice, this list of conditions and the following disclaimer. 1154371Ssemenu * 2. Redistributions in binary form must reproduce the above copyright 1254371Ssemenu * notice, this list of conditions and the following disclaimer in the 1354371Ssemenu * documentation and/or other materials provided with the distribution. 1454371Ssemenu * 3. All advertising materials mentioning features or use of this software 1554371Ssemenu * must display the following acknowledgement: 1654371Ssemenu * This product includes software developed by Christopher G. Demetriou. 1754371Ssemenu * 4. The name of the author may not be used to endorse or promote products 1854371Ssemenu * derived from this software without specific prior written permission 1954371Ssemenu * 2054371Ssemenu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2154371Ssemenu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2254371Ssemenu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2354371Ssemenu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2454371Ssemenu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2554371Ssemenu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2654371Ssemenu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2754371Ssemenu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2854371Ssemenu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2954371Ssemenu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3054371Ssemenu * 3154371Ssemenu * $FreeBSD$ 3254371Ssemenu */ 3354371Ssemenu 3454371Ssemenu#include <sys/cdefs.h> 3554371Ssemenu#include <sys/param.h> 3654371Ssemenu#include <sys/mount.h> 3754371Ssemenu#include <sys/stat.h> 3854371Ssemenu#include <fs/hpfs/hpfsmount.h> 3954371Ssemenu#include <ctype.h> 4054371Ssemenu#include <err.h> 4154371Ssemenu#include <grp.h> 4254371Ssemenu#include <pwd.h> 4354371Ssemenu#include <stdio.h> 4454371Ssemenu#include <stdlib.h> 4554371Ssemenu#include <string.h> 4654371Ssemenu#include <sysexits.h> 4754371Ssemenu#include <unistd.h> 4854371Ssemenu 4954371Ssemenu#include "mntopts.h" 5054371Ssemenu 5154371Ssemenustatic struct mntopt mopts[] = { 5254371Ssemenu MOPT_STDOPTS, 53147242Sdelphij MOPT_END 5454371Ssemenu}; 5554371Ssemenu 5692882Simpstatic gid_t a_gid(char *); 5792882Simpstatic uid_t a_uid(char *); 5892882Simpstatic mode_t a_mask(char *); 5992882Simpstatic void usage(void) __dead2; 6092882Simpstatic void load_u2wtable(struct hpfs_args *, char *); 6154371Ssemenu 6254371Ssemenuint 63204403Suqsmain(int argc, char *argv[]) 6454371Ssemenu{ 6554371Ssemenu struct hpfs_args args; 6654371Ssemenu struct stat sb; 67101270Smux int c, mntflags, set_gid, set_uid, set_mask; 6854371Ssemenu int forcerw = 0; 69118579Simp char *dev, *dir, ndir[MAXPATHLEN]; 7054371Ssemenu 7154371Ssemenu mntflags = set_gid = set_uid = set_mask = 0; 7254371Ssemenu (void)memset(&args, '\0', sizeof(args)); 7354371Ssemenu 7454371Ssemenu while ((c = getopt(argc, argv, "u:g:m:o:c:W:F")) != -1) { 7554371Ssemenu switch (c) { 7654371Ssemenu case 'F': 7754371Ssemenu forcerw=1; 7854371Ssemenu break; 7954371Ssemenu case 'u': 8054371Ssemenu args.uid = a_uid(optarg); 8154371Ssemenu set_uid = 1; 8254371Ssemenu break; 8354371Ssemenu case 'g': 8454371Ssemenu args.gid = a_gid(optarg); 8554371Ssemenu set_gid = 1; 8654371Ssemenu break; 8754371Ssemenu case 'm': 8854371Ssemenu args.mode = a_mask(optarg); 8954371Ssemenu set_mask = 1; 9054371Ssemenu break; 9154371Ssemenu case 'o': 9254371Ssemenu getmntopts(optarg, mopts, &mntflags, 0); 9354371Ssemenu break; 9454371Ssemenu case 'W': 9554371Ssemenu load_u2wtable(&args, optarg); 9654371Ssemenu args.flags |= HPFSMNT_TABLES; 9754371Ssemenu break; 9854371Ssemenu case '?': 9954371Ssemenu default: 10054371Ssemenu usage(); 10154371Ssemenu break; 10254371Ssemenu } 10354371Ssemenu } 10454371Ssemenu 10554371Ssemenu if (optind + 2 != argc) 10654371Ssemenu usage(); 10754371Ssemenu 10854371Ssemenu if (!(mntflags & MNT_RDONLY) && !forcerw) { 10954371Ssemenu warnx("Write support is BETA, you need -F flag to enable RW mount!"); 11054371Ssemenu exit (111); 11154371Ssemenu } 11254371Ssemenu 11354371Ssemenu dev = argv[optind]; 11454371Ssemenu dir = argv[optind + 1]; 11554371Ssemenu if (dir[0] != '/') { 11654371Ssemenu warnx("\"%s\" is a relative path", dir); 11754371Ssemenu if (getcwd(ndir, sizeof(ndir)) == NULL) 11854371Ssemenu err(EX_OSERR, "getcwd"); 11954371Ssemenu strncat(ndir, "/", sizeof(ndir) - strlen(ndir) - 1); 12054371Ssemenu strncat(ndir, dir, sizeof(ndir) - strlen(ndir) - 1); 12154371Ssemenu dir = ndir; 12254371Ssemenu warnx("using \"%s\" instead", dir); 12354371Ssemenu } 12454371Ssemenu 12554371Ssemenu args.fspec = dev; 12654371Ssemenu args.export.ex_root = 65534; /* unchecked anyway on DOS fs */ 12754371Ssemenu if (mntflags & MNT_RDONLY) 12854371Ssemenu args.export.ex_flags = MNT_EXRDONLY; 12954371Ssemenu else 13054371Ssemenu args.export.ex_flags = 0; 13154371Ssemenu 13254371Ssemenu if (!set_gid || !set_uid || !set_mask) { 13354371Ssemenu if (stat(dir, &sb) == -1) 13454371Ssemenu err(EX_OSERR, "stat %s", dir); 13554371Ssemenu 13654371Ssemenu if (!set_uid) 13754371Ssemenu args.uid = sb.st_uid; 13854371Ssemenu if (!set_gid) 13954371Ssemenu args.gid = sb.st_gid; 14054371Ssemenu if (!set_mask) 14154371Ssemenu args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 14254371Ssemenu } 14354371Ssemenu 144101270Smux if (mount("hpfs", dir, mntflags, &args) < 0) 14554371Ssemenu err(EX_OSERR, "%s", dev); 14654371Ssemenu 14754371Ssemenu exit (0); 14854371Ssemenu} 14954371Ssemenu 15054371Ssemenugid_t 151204403Suqsa_gid(char *s) 15254371Ssemenu{ 15354371Ssemenu struct group *gr; 15454371Ssemenu char *gname; 15554371Ssemenu gid_t gid; 15654371Ssemenu 15754371Ssemenu if ((gr = getgrnam(s)) != NULL) 15854371Ssemenu gid = gr->gr_gid; 15954371Ssemenu else { 16054371Ssemenu for (gname = s; *s && isdigit(*s); ++s); 16154371Ssemenu if (!*s) 16254371Ssemenu gid = atoi(gname); 16354371Ssemenu else 16454371Ssemenu errx(EX_NOUSER, "unknown group id: %s", gname); 16554371Ssemenu } 16654371Ssemenu return (gid); 16754371Ssemenu} 16854371Ssemenu 16954371Ssemenuuid_t 170204403Suqsa_uid(char *s) 17154371Ssemenu{ 17254371Ssemenu struct passwd *pw; 17354371Ssemenu char *uname; 17454371Ssemenu uid_t uid; 17554371Ssemenu 17654371Ssemenu if ((pw = getpwnam(s)) != NULL) 17754371Ssemenu uid = pw->pw_uid; 17854371Ssemenu else { 17954371Ssemenu for (uname = s; *s && isdigit(*s); ++s); 18054371Ssemenu if (!*s) 18154371Ssemenu uid = atoi(uname); 18254371Ssemenu else 18354371Ssemenu errx(EX_NOUSER, "unknown user id: %s", uname); 18454371Ssemenu } 18554371Ssemenu return (uid); 18654371Ssemenu} 18754371Ssemenu 18854371Ssemenumode_t 189204403Suqsa_mask(char *s) 19054371Ssemenu{ 19154371Ssemenu int done, rv=0; 19254371Ssemenu char *ep; 19354371Ssemenu 19454371Ssemenu done = 0; 19554371Ssemenu if (*s >= '0' && *s <= '7') { 19654371Ssemenu done = 1; 19754371Ssemenu rv = strtol(optarg, &ep, 8); 19854371Ssemenu } 19954371Ssemenu if (!done || rv < 0 || *ep) 20054371Ssemenu errx(EX_USAGE, "invalid file mode: %s", s); 20154371Ssemenu return (rv); 20254371Ssemenu} 20354371Ssemenu 20454371Ssemenuvoid 205204403Suqsusage(void) 20654371Ssemenu{ 20754371Ssemenu fprintf(stderr, "usage: mount_hpfs [-u user] [-g group] [-m mask] bdev dir\n"); 20854371Ssemenu exit(EX_USAGE); 20954371Ssemenu} 21054371Ssemenu 21154371Ssemenuvoid 212204403Suqsload_u2wtable (struct hpfs_args *pargs, char *name) 21354371Ssemenu{ 21454371Ssemenu FILE *f; 21554371Ssemenu int i, code; 21654371Ssemenu char buf[128]; 21754371Ssemenu char *fn; 21854371Ssemenu 21954371Ssemenu if (*name == '/') 22054371Ssemenu fn = name; 22154371Ssemenu else { 22254371Ssemenu snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name); 22354371Ssemenu buf[127] = '\0'; 22454371Ssemenu fn = buf; 22554371Ssemenu } 22654371Ssemenu if ((f = fopen(fn, "r")) == NULL) 22754371Ssemenu err(EX_NOINPUT, "%s", fn); 22854371Ssemenu for (i = 0; i < 128; i++) { 22954371Ssemenu if (fscanf(f, "%i", &code) != 1) 23054371Ssemenu errx(EX_DATAERR, "u2w: missing item number %d", i); 23154371Ssemenu /* pargs->u2w[i] = code; */ 23254371Ssemenu } 23354371Ssemenu for (i = 0; i < 128; i++) { 23454371Ssemenu if (fscanf(f, "%i", &code) != 1) 23554371Ssemenu errx(EX_DATAERR, "d2u: missing item number %d", i); 23654371Ssemenu pargs->d2u[i] = code; 23754371Ssemenu } 23854371Ssemenu for (i = 0; i < 128; i++) { 23954371Ssemenu if (fscanf(f, "%i", &code) != 1) 24054371Ssemenu errx(EX_DATAERR, "u2d: missing item number %d", i); 24154371Ssemenu pargs->u2d[i] = code; 24254371Ssemenu } 24354371Ssemenu fclose(f); 24454371Ssemenu} 245