getmntopts.c revision 152354
11558Srgrimes/*- 21558Srgrimes * Copyright (c) 1994 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 4. Neither the name of the University nor the names of its contributors 141558Srgrimes * may be used to endorse or promote products derived from this software 151558Srgrimes * without specific prior written permission. 161558Srgrimes * 171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271558Srgrimes * SUCH DAMAGE. 281558Srgrimes */ 291558Srgrimes 30114589Sobrien#if 0 311558Srgrimes#ifndef lint 3223678Speterstatic char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95"; 33114589Sobrien#endif /* not lint */ 3428671Ssteve#endif 35114589Sobrien#include <sys/cdefs.h> 36114589Sobrien__FBSDID("$FreeBSD: head/sbin/mount/getmntopts.c 152354 2005-11-13 01:27:57Z rodrigc $"); 371558Srgrimes 381558Srgrimes#include <sys/param.h> 39152354Srodrigc#include <sys/mount.h> 4052055Sphk#include <sys/stat.h> 41138095Sphk#include <sys/uio.h> 421558Srgrimes 43152354Srodrigc#include <assert.h> 441558Srgrimes#include <err.h> 4552055Sphk#include <errno.h> 46152354Srodrigc#include <stdarg.h> 47152354Srodrigc#include <stdio.h> 481558Srgrimes#include <stdlib.h> 491558Srgrimes#include <string.h> 5052055Sphk#include <sysexits.h> 511558Srgrimes 521558Srgrimes#include "mntopts.h" 531558Srgrimes 544065Swollmanint getmnt_silent = 0; 554065Swollman 561558Srgrimesvoid 57151048Srodrigcgetmntopts(const char *options, const struct mntopt *m0, int *flagp, 58151048Srodrigc int *altflagp) 591558Srgrimes{ 601558Srgrimes const struct mntopt *m; 613202Sache int negative, len; 6223678Speter char *opt, *optbuf, *p; 634065Swollman int *thisflagp; 641558Srgrimes 651558Srgrimes /* Copy option string, since it is about to be torn asunder... */ 661558Srgrimes if ((optbuf = strdup(options)) == NULL) 671558Srgrimes err(1, NULL); 681558Srgrimes 691558Srgrimes for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 701558Srgrimes /* Check for "no" prefix. */ 711558Srgrimes if (opt[0] == 'n' && opt[1] == 'o') { 721558Srgrimes negative = 1; 731558Srgrimes opt += 2; 741558Srgrimes } else 751558Srgrimes negative = 0; 761558Srgrimes 7723678Speter /* 7823678Speter * for options with assignments in them (ie. quotas) 7923678Speter * ignore the assignment as it's handled elsewhere 8023678Speter */ 8123678Speter p = strchr(opt, '='); 82123268Strhodes if (p != NULL) 8325301Smsmith *++p = '\0'; 8423678Speter 851558Srgrimes /* Scan option table. */ 863202Sache for (m = m0; m->m_option != NULL; ++m) { 873202Sache len = strlen(m->m_option); 883202Sache if (strncasecmp(opt, m->m_option, len) == 0) 89138094Sphk if (opt[len] == '\0' || opt[len] == '=') 90138094Sphk break; 913202Sache } 921558Srgrimes 9337425Scharnier /* Save flag, or fail if option is not recognized. */ 941558Srgrimes if (m->m_option) { 954065Swollman thisflagp = m->m_altloc ? altflagp : flagp; 961558Srgrimes if (negative == m->m_inverse) 974065Swollman *thisflagp |= m->m_flag; 981558Srgrimes else 994065Swollman *thisflagp &= ~m->m_flag; 10023678Speter } else if (!getmnt_silent) { 1011558Srgrimes errx(1, "-o %s: option not supported", opt); 1024065Swollman } 1031558Srgrimes } 1041558Srgrimes 1051558Srgrimes free(optbuf); 1061558Srgrimes} 10752055Sphk 10852055Sphkvoid 109151048Srodrigcrmslashes(char *rrpin, char *rrpout) 11052055Sphk{ 11152055Sphk char *rrpoutstart; 11252055Sphk 11352055Sphk *rrpout = *rrpin; 11452055Sphk for (rrpoutstart = rrpout; *rrpin != '\0'; *rrpout++ = *rrpin++) { 11552055Sphk 11652055Sphk /* skip all double slashes */ 11752055Sphk while (*rrpin == '/' && *(rrpin + 1) == '/') 11852055Sphk rrpin++; 11952055Sphk } 12052055Sphk 12152055Sphk /* remove trailing slash if necessary */ 12252055Sphk if (rrpout - rrpoutstart > 1 && *(rrpout - 1) == '/') 12352055Sphk *(rrpout - 1) = '\0'; 12452055Sphk else 12552055Sphk *rrpout = '\0'; 12652055Sphk} 12752055Sphk 12852055Sphkvoid 129151048Srodrigccheckpath(const char *path, char *resolved) 13052055Sphk{ 13152055Sphk struct stat sb; 13252055Sphk 13352055Sphk if (realpath(path, resolved) != NULL && stat(resolved, &sb) == 0) { 13452055Sphk if (!S_ISDIR(sb.st_mode)) 13552055Sphk errx(EX_USAGE, "%s: not a directory", resolved); 13652055Sphk } else 13752055Sphk errx(EX_USAGE, "%s: %s", resolved, strerror(errno)); 13852055Sphk} 139138095Sphk 140138095Sphkvoid 141152354Srodrigcbuild_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, 142152354Srodrigc size_t len) 143138095Sphk{ 144138095Sphk int i; 145138095Sphk 146138097Sdelphij if (*iovlen < 0) 147138095Sphk return; 148138095Sphk i = *iovlen; 149138095Sphk *iov = realloc(*iov, sizeof **iov * (i + 2)); 150138095Sphk if (*iov == NULL) { 151138095Sphk *iovlen = -1; 152138095Sphk return; 153138095Sphk } 154138095Sphk (*iov)[i].iov_base = strdup(name); 155138095Sphk (*iov)[i].iov_len = strlen(name) + 1; 156138095Sphk i++; 157138095Sphk (*iov)[i].iov_base = val; 158152354Srodrigc if (len == (size_t)-1) 159138095Sphk len = strlen(val) + 1; 160152354Srodrigc (*iov)[i].iov_len = (int)len; 161138095Sphk *iovlen = ++i; 162138095Sphk} 163152354Srodrigc 164152354Srodrigc/* 165152354Srodrigc * This function is needed for compatibility with parameters 166152354Srodrigc * which used to use the mount_argf() command for the old mount() syscall. 167152354Srodrigc */ 168152354Srodrigcvoid 169152354Srodrigcbuild_iovec_argf(struct iovec **iov, int *iovlen, const char *name, 170152354Srodrigc const char *fmt, ...) 171152354Srodrigc{ 172152354Srodrigc va_list ap; 173152354Srodrigc char val[255] = { 0 }; 174152354Srodrigc 175152354Srodrigc va_start(ap, fmt); 176152354Srodrigc vsnprintf(val, sizeof(val), fmt, ap); 177152354Srodrigc va_end(ap); 178152354Srodrigc build_iovec(iov, iovlen, name, strdup(val), (size_t)-1); 179152354Srodrigc} 180