mount_msdosfs.c revision 15771
12892Sdfr/*
22892Sdfr * Copyright (c) 1994 Christopher G. Demetriou
32892Sdfr * All rights reserved.
42892Sdfr *
52892Sdfr * Redistribution and use in source and binary forms, with or without
62892Sdfr * modification, are permitted provided that the following conditions
72892Sdfr * are met:
82892Sdfr * 1. Redistributions of source code must retain the above copyright
92892Sdfr *    notice, this list of conditions and the following disclaimer.
102892Sdfr * 2. Redistributions in binary form must reproduce the above copyright
112892Sdfr *    notice, this list of conditions and the following disclaimer in the
122892Sdfr *    documentation and/or other materials provided with the distribution.
132892Sdfr * 3. All advertising materials mentioning features or use of this software
142892Sdfr *    must display the following acknowledgement:
152892Sdfr *      This product includes software developed by Christopher G. Demetriou.
162892Sdfr * 4. The name of the author may not be used to endorse or promote products
172892Sdfr *    derived from this software without specific prior written permission
182892Sdfr *
192892Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
202892Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
212892Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
222892Sdfr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
232892Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
242892Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252892Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262892Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272892Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
282892Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292892Sdfr */
302892Sdfr
312892Sdfr#ifndef lint
3215771Swollmanstatic const char rcsid[] =
3315771Swollman	"$Id: mount_msdos.c,v 1.3 1994/11/01 23:51:42 wollman Exp $";
342892Sdfr#endif /* not lint */
352892Sdfr
362892Sdfr#include <sys/cdefs.h>
372892Sdfr#include <sys/param.h>
382892Sdfr#define MSDOSFS
392892Sdfr#include <sys/mount.h>
402892Sdfr#include <sys/stat.h>
412892Sdfr#include <ctype.h>
422892Sdfr#include <err.h>
432892Sdfr#include <grp.h>
442892Sdfr#include <pwd.h>
452892Sdfr#include <stdio.h>
462892Sdfr#include <stdlib.h>
472892Sdfr#include <string.h>
4815771Swollman#include <sysexits.h>
492892Sdfr#include <unistd.h>
502892Sdfr
512892Sdfr#include "mntopts.h"
522892Sdfr
5315771Swollmanstatic struct mntopt mopts[] = {
542892Sdfr	MOPT_STDOPTS,
552892Sdfr	{ NULL }
562892Sdfr};
572892Sdfr
5815771Swollmanstatic gid_t	a_gid __P((char *));
5915771Swollmanstatic uid_t	a_uid __P((char *));
6015771Swollmanstatic mode_t	a_mask __P((char *));
6115771Swollmanstatic __dead void	usage __P((void)) __dead2;
622892Sdfr
632892Sdfrint
642892Sdfrmain(argc, argv)
652892Sdfr	int argc;
662892Sdfr	char **argv;
672892Sdfr{
682892Sdfr	struct msdosfs_args args;
692892Sdfr	struct stat sb;
702892Sdfr	int c, mntflags, set_gid, set_uid, set_mask;
712892Sdfr	char *dev, *dir, ndir[MAXPATHLEN+1];
722999Swollman	struct vfsconf *vfc;
732892Sdfr
742892Sdfr	mntflags = set_gid = set_uid = set_mask = 0;
752892Sdfr	(void)memset(&args, '\0', sizeof(args));
762892Sdfr
772892Sdfr	while ((c = getopt(argc, argv, "u:g:m:o:")) != EOF) {
782892Sdfr		switch (c) {
792892Sdfr		case 'u':
802892Sdfr			args.uid = a_uid(optarg);
812892Sdfr			set_uid = 1;
822892Sdfr			break;
832892Sdfr		case 'g':
842892Sdfr			args.gid = a_gid(optarg);
852892Sdfr			set_gid = 1;
862892Sdfr			break;
872892Sdfr		case 'm':
882892Sdfr			args.mask = a_mask(optarg);
892892Sdfr			set_mask = 1;
902892Sdfr			break;
912892Sdfr		case 'o':
924065Swollman			getmntopts(optarg, mopts, &mntflags, 0);
932892Sdfr			break;
942892Sdfr		case '?':
952892Sdfr		default:
962892Sdfr			usage();
972892Sdfr			break;
982892Sdfr		}
992892Sdfr	}
1002892Sdfr
1012892Sdfr	if (optind + 2 != argc)
1022892Sdfr		usage();
1032892Sdfr
1042892Sdfr	dev = argv[optind];
1052892Sdfr	dir = argv[optind + 1];
1062892Sdfr	if (dir[0] != '/') {
10715771Swollman		warnx("\"%s\" is a relative path", dir);
1082892Sdfr		if (getcwd(ndir, sizeof(ndir)) == NULL)
10915771Swollman			err(EX_OSERR, "getcwd");
1102892Sdfr		strncat(ndir, "/", sizeof(ndir) - strlen(ndir) - 1);
1112892Sdfr		strncat(ndir, dir, sizeof(ndir) - strlen(ndir) - 1);
1122892Sdfr		dir = ndir;
11315771Swollman		warnx("using \"%s\" instead", dir);
1142892Sdfr	}
1152892Sdfr
1162892Sdfr	args.fspec = dev;
1172892Sdfr	args.export.ex_root = -2;	/* unchecked anyway on DOS fs */
1182892Sdfr	if (mntflags & MNT_RDONLY)
1192892Sdfr		args.export.ex_flags = MNT_EXRDONLY;
1202892Sdfr	else
1212892Sdfr		args.export.ex_flags = 0;
1222892Sdfr	if (!set_gid || !set_uid || !set_mask) {
1232892Sdfr		if (stat(dir, &sb) == -1)
12415771Swollman			err(EX_OSERR, "stat %s", dir);
1252892Sdfr
1262892Sdfr		if (!set_uid)
1272892Sdfr			args.uid = sb.st_uid;
1282892Sdfr		if (!set_gid)
1292892Sdfr			args.gid = sb.st_gid;
1302892Sdfr		if (!set_mask)
1312892Sdfr			args.mask = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1322892Sdfr	}
1332892Sdfr
1342999Swollman	vfc = getvfsbyname("msdos");
1352999Swollman	if(!vfc && vfsisloadable("msdos")) {
1362999Swollman		if(vfsload("msdos"))
13715771Swollman			err(EX_OSERR, "vfsload(msdos)");
1382999Swollman		endvfsent();	/* clear cache */
1392999Swollman		vfc = getvfsbyname("msdos");
1402999Swollman	}
14115771Swollman	if (!vfc)
14215771Swollman		errx(EX_OSERR, "msdos filesystem is not available");
1432999Swollman
14415771Swollman	if (mount(vfc->vfc_index, dir, mntflags, &args) < 0)
14515771Swollman		err(EX_OSERR, "%s", dev);
1462892Sdfr
1472892Sdfr	exit (0);
1482892Sdfr}
1492892Sdfr
1502892Sdfrgid_t
1512892Sdfra_gid(s)
1522892Sdfr	char *s;
1532892Sdfr{
1542892Sdfr	struct group *gr;
1552892Sdfr	char *gname;
1562892Sdfr	gid_t gid;
1572892Sdfr
1582892Sdfr	if ((gr = getgrnam(s)) != NULL)
1592892Sdfr		gid = gr->gr_gid;
1602892Sdfr	else {
1612892Sdfr		for (gname = s; *s && isdigit(*s); ++s);
1622892Sdfr		if (!*s)
1632892Sdfr			gid = atoi(gname);
1642892Sdfr		else
16515771Swollman			errx(EX_NOUSER, "unknown group id: %s", gname);
1662892Sdfr	}
1672892Sdfr	return (gid);
1682892Sdfr}
1692892Sdfr
1702892Sdfruid_t
1712892Sdfra_uid(s)
1722892Sdfr	char *s;
1732892Sdfr{
1742892Sdfr	struct passwd *pw;
1752892Sdfr	char *uname;
1762892Sdfr	uid_t uid;
1772892Sdfr
1782892Sdfr	if ((pw = getpwnam(s)) != NULL)
1792892Sdfr		uid = pw->pw_uid;
1802892Sdfr	else {
1812892Sdfr		for (uname = s; *s && isdigit(*s); ++s);
1822892Sdfr		if (!*s)
1832892Sdfr			uid = atoi(uname);
1842892Sdfr		else
18515771Swollman			errx(EX_NOUSER, "unknown user id: %s", uname);
1862892Sdfr	}
1872892Sdfr	return (uid);
1882892Sdfr}
1892892Sdfr
1902892Sdfrmode_t
1912892Sdfra_mask(s)
1922892Sdfr	char *s;
1932892Sdfr{
1942892Sdfr	int done, rv;
1952892Sdfr	char *ep;
1962892Sdfr
1972892Sdfr	done = 0;
1982892Sdfr	if (*s >= '0' && *s <= '7') {
1992892Sdfr		done = 1;
2002892Sdfr		rv = strtol(optarg, &ep, 8);
2012892Sdfr	}
2022892Sdfr	if (!done || rv < 0 || *ep)
20315771Swollman		errx(EX_USAGE, "invalid file mode: %s", s);
2042892Sdfr	return (rv);
2052892Sdfr}
2062892Sdfr
2072892Sdfrvoid
2082892Sdfrusage()
2092892Sdfr{
2102892Sdfr	fprintf(stderr, "usage: mount_msdos [-F flags] [-u user] [-g group] [-m mask] bdev dir\n");
21115771Swollman	exit(EX_USAGE);
2122892Sdfr}
213