mount_ntfs.c revision 78735
1184610Salfred/* 2184610Salfred * Copyright (c) 1994 Christopher G. Demetriou 3199575Sthompsa * Copyright (c) 1999 Semen Ustimenko 4184610Salfred * All rights reserved. 5184610Salfred * 6184610Salfred * Redistribution and use in source and binary forms, with or without 7184610Salfred * modification, are permitted provided that the following conditions 8184610Salfred * are met: 9184610Salfred * 1. Redistributions of source code must retain the above copyright 10184610Salfred * notice, this list of conditions and the following disclaimer. 11184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 12184610Salfred * notice, this list of conditions and the following disclaimer in the 13184610Salfred * documentation and/or other materials provided with the distribution. 14184610Salfred * 3. All advertising materials mentioning features or use of this software 15184610Salfred * must display the following acknowledgement: 16184610Salfred * This product includes software developed by Christopher G. Demetriou. 17184610Salfred * 4. The name of the author may not be used to endorse or promote products 18184610Salfred * derived from this software without specific prior written permission 19184610Salfred * 20184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21184610Salfred * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22184610Salfred * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23184610Salfred * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24184610Salfred * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25184610Salfred * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26184610Salfred * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27248236Shselasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28248236Shselasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29248236Shselasky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30203815Swkoszek * 31203815Swkoszek * $FreeBSD: head/sbin/mount_ntfs/mount_ntfs.c 78735 2001-06-24 23:31:07Z dd $ 32184610Salfred * 33184610Salfred */ 34184610Salfred 35248236Shselasky#include <sys/cdefs.h> 36248236Shselasky#include <sys/param.h> 37248236Shselasky#define NTFS 38184610Salfred#include <sys/mount.h> 39184610Salfred#include <sys/stat.h> 40184610Salfred#include <fs/ntfs/ntfsmount.h> 41184610Salfred#include <ctype.h> 42184610Salfred#include <err.h> 43184610Salfred#include <grp.h> 44184610Salfred#include <pwd.h> 45184610Salfred#include <stdio.h> 46184610Salfred#include <stdlib.h> 47184610Salfred#include <string.h> 48184610Salfred#include <sysexits.h> 49184610Salfred#include <unistd.h> 50184610Salfred 51184610Salfred#include "mntopts.h" 52184610Salfred 53184610Salfredstatic struct mntopt mopts[] = { 54184610Salfred MOPT_STDOPTS, 55184610Salfred { NULL } 56184610Salfred}; 57184610Salfred 58184610Salfredstatic gid_t a_gid __P((char *)); 59184610Salfredstatic uid_t a_uid __P((char *)); 60184610Salfredstatic mode_t a_mask __P((char *)); 61184610Salfredstatic void usage __P((void)) __dead2; 62184610Salfred 63184610Salfredint 64184610Salfredmain(argc, argv) 65184610Salfred int argc; 66184610Salfred char **argv; 67184610Salfred{ 68184610Salfred struct ntfs_args args; 69184610Salfred struct stat sb; 70184610Salfred int c, mntflags, set_gid, set_uid, set_mask, error; 71184610Salfred char *dev, *dir, mntpath[MAXPATHLEN]; 72184610Salfred#if __FreeBSD_version >= 300000 73184610Salfred struct vfsconf vfc; 74184610Salfred#else 75203147Sthompsa struct vfsconf *vfc; 76184610Salfred#endif 77184610Salfred 78250201Shselasky mntflags = set_gid = set_uid = set_mask = 0; 79246789Shselasky (void)memset(&args, '\0', sizeof(args)); 80184610Salfred 81184610Salfred while ((c = getopt(argc, argv, "aiu:g:m:o:")) != -1) { 82184610Salfred switch (c) { 83184610Salfred case 'u': 84184610Salfred args.uid = a_uid(optarg); 85184610Salfred set_uid = 1; 86184610Salfred break; 87188622Sthompsa case 'g': 88188622Sthompsa args.gid = a_gid(optarg); 89184610Salfred set_gid = 1; 90184610Salfred break; 91184610Salfred case 'm': 92184610Salfred args.mode = a_mask(optarg); 93184610Salfred set_mask = 1; 94184610Salfred break; 95184610Salfred case 'i': 96184610Salfred args.flag |= NTFS_MFLAG_CASEINS; 97184610Salfred break; 98184610Salfred case 'a': 99184610Salfred args.flag |= NTFS_MFLAG_ALLNAMES; 100184610Salfred break; 101184610Salfred case 'o': 102184610Salfred getmntopts(optarg, mopts, &mntflags, 0); 103184610Salfred break; 104184610Salfred case '?': 105184610Salfred default: 106184610Salfred usage(); 107184610Salfred break; 108184610Salfred } 109184610Salfred } 110188622Sthompsa 111184610Salfred if (optind + 2 != argc) 112184610Salfred usage(); 113184610Salfred 114184610Salfred dev = argv[optind]; 115184610Salfred dir = argv[optind + 1]; 116184610Salfred 117184610Salfred /* 118184610Salfred * Resolve the mountpoint with realpath(3) and remove unnecessary 119184610Salfred * slashes from the devicename if there are any. 120188622Sthompsa */ 121184610Salfred (void)checkpath(dir, mntpath); 122184610Salfred (void)rmslashes(dev, dev); 123184610Salfred 124184610Salfred args.fspec = dev; 125184610Salfred args.export.ex_root = 65534; /* unchecked anyway on DOS fs */ 126184610Salfred if (mntflags & MNT_RDONLY) 127184610Salfred args.export.ex_flags = MNT_EXRDONLY; 128184610Salfred else 129184610Salfred args.export.ex_flags = 0; 130184610Salfred if (!set_gid || !set_uid || !set_mask) { 131184610Salfred if (stat(mntpath, &sb) == -1) 132184610Salfred err(EX_OSERR, "stat %s", mntpath); 133188622Sthompsa 134184610Salfred if (!set_uid) 135184610Salfred args.uid = sb.st_uid; 136184610Salfred if (!set_gid) 137184610Salfred args.gid = sb.st_gid; 138184610Salfred if (!set_mask) 139184610Salfred args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 140184610Salfred } 141202025Sthompsa 142297764Spfg#if __FreeBSD_version >= 300000 143297764Spfg error = getvfsbyname("ntfs", &vfc); 144184610Salfred if(error && vfsisloadable("ntfs")) { 145202025Sthompsa if(vfsload("ntfs")) 146202025Sthompsa#else 147202025Sthompsa vfc = getvfsbyname("ntfs"); 148202025Sthompsa if(!vfc && vfsisloadable("ntfs")) { 149202025Sthompsa if(vfsload("ntfs")) 150202025Sthompsa#endif 151202025Sthompsa err(EX_OSERR, "vfsload(ntfs)"); 152202025Sthompsa endvfsent(); /* clear cache */ 153202025Sthompsa#if __FreeBSD_version >= 300000 154184610Salfred error = getvfsbyname("ntfs", &vfc); 155184610Salfred#else 156184610Salfred vfc = getvfsbyname("ntfs"); 157184610Salfred#endif 158184610Salfred } 159184610Salfred#if __FreeBSD_version >= 300000 160184610Salfred if (error) 161184610Salfred#else 162184610Salfred if (!vfc) 163184610Salfred#endif 164239239Shselasky errx(EX_OSERR, "ntfs filesystem is not available"); 165239239Shselasky 166239239Shselasky#if __FreeBSD_version >= 300000 167239239Shselasky if (mount(vfc.vfc_name, mntpath, mntflags, &args) < 0) 168239239Shselasky#else 169239239Shselasky if (mount(vfc->vfc_index, mntpath, mntflags, &args) < 0) 170239239Shselasky#endif 171184610Salfred err(EX_OSERR, "%s", dev); 172219100Shselasky 173184610Salfred exit (0); 174184610Salfred} 175219100Shselasky 176184610Salfredgid_t 177219100Shselaskya_gid(s) 178219100Shselasky char *s; 179219100Shselasky{ 180219100Shselasky struct group *gr; 181219100Shselasky char *gname; 182184610Salfred gid_t gid; 183219100Shselasky 184184610Salfred if ((gr = getgrnam(s)) != NULL) 185219100Shselasky gid = gr->gr_gid; 186184610Salfred else { 187184610Salfred for (gname = s; *s && isdigit(*s); ++s); 188184610Salfred if (!*s) 189184610Salfred gid = atoi(gname); 190184610Salfred else 191184610Salfred errx(EX_NOUSER, "unknown group id: %s", gname); 192184610Salfred } 193184610Salfred return (gid); 194184610Salfred} 195184610Salfred 196184610Salfreduid_t 197184610Salfreda_uid(s) 198184610Salfred char *s; 199184610Salfred{ 200184610Salfred struct passwd *pw; 201184610Salfred char *uname; 202184610Salfred uid_t uid; 203188622Sthompsa 204239239Shselasky if ((pw = getpwnam(s)) != NULL) 205184610Salfred uid = pw->pw_uid; 206184610Salfred else { 207184610Salfred for (uname = s; *s && isdigit(*s); ++s); 208184610Salfred if (!*s) 209184610Salfred uid = atoi(uname); 210184610Salfred else 211184610Salfred errx(EX_NOUSER, "unknown user id: %s", uname); 212184610Salfred } 213184610Salfred return (uid); 214184610Salfred} 215184610Salfred 216184610Salfredmode_t 217184610Salfreda_mask(s) 218184610Salfred char *s; 219184610Salfred{ 220184610Salfred int done, rv=0; 221184610Salfred char *ep; 222184610Salfred 223184610Salfred done = 0; 224184610Salfred if (*s >= '0' && *s <= '7') { 225184610Salfred done = 1; 226184610Salfred rv = strtol(optarg, &ep, 8); 227184610Salfred } 228184610Salfred if (!done || rv < 0 || *ep) 229184610Salfred errx(EX_USAGE, "invalid file mode: %s", s); 230184610Salfred return (rv); 231184610Salfred} 232184610Salfred 233184610Salfredvoid 234184610Salfredusage() 235184610Salfred{ 236184610Salfred fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] bdev dir\n"); 237184610Salfred exit(EX_USAGE); 238184610Salfred} 239184610Salfred