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$"); 371558Srgrimes 381558Srgrimes#include <sys/param.h> 39152354Srodrigc#include <sys/mount.h> 4052055Sphk#include <sys/stat.h> 41138095Sphk#include <sys/uio.h> 421558Srgrimes 431558Srgrimes#include <err.h> 4452055Sphk#include <errno.h> 45152354Srodrigc#include <stdarg.h> 46152354Srodrigc#include <stdio.h> 471558Srgrimes#include <stdlib.h> 481558Srgrimes#include <string.h> 4952055Sphk#include <sysexits.h> 501558Srgrimes 511558Srgrimes#include "mntopts.h" 521558Srgrimes 534065Swollmanint getmnt_silent = 0; 544065Swollman 551558Srgrimesvoid 56151048Srodrigcgetmntopts(const char *options, const struct mntopt *m0, int *flagp, 57151048Srodrigc int *altflagp) 581558Srgrimes{ 591558Srgrimes const struct mntopt *m; 603202Sache int negative, len; 6123678Speter char *opt, *optbuf, *p; 624065Swollman int *thisflagp; 631558Srgrimes 641558Srgrimes /* Copy option string, since it is about to be torn asunder... */ 651558Srgrimes if ((optbuf = strdup(options)) == NULL) 661558Srgrimes err(1, NULL); 671558Srgrimes 681558Srgrimes for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 691558Srgrimes /* Check for "no" prefix. */ 701558Srgrimes if (opt[0] == 'n' && opt[1] == 'o') { 711558Srgrimes negative = 1; 721558Srgrimes opt += 2; 731558Srgrimes } else 741558Srgrimes negative = 0; 751558Srgrimes 7623678Speter /* 7723678Speter * for options with assignments in them (ie. quotas) 7823678Speter * ignore the assignment as it's handled elsewhere 7923678Speter */ 8023678Speter p = strchr(opt, '='); 81123268Strhodes if (p != NULL) 8225301Smsmith *++p = '\0'; 8323678Speter 841558Srgrimes /* Scan option table. */ 853202Sache for (m = m0; m->m_option != NULL; ++m) { 863202Sache len = strlen(m->m_option); 873202Sache if (strncasecmp(opt, m->m_option, len) == 0) 88138094Sphk if (opt[len] == '\0' || opt[len] == '=') 89138094Sphk break; 903202Sache } 911558Srgrimes 9237425Scharnier /* Save flag, or fail if option is not recognized. */ 931558Srgrimes if (m->m_option) { 944065Swollman thisflagp = m->m_altloc ? altflagp : flagp; 951558Srgrimes if (negative == m->m_inverse) 964065Swollman *thisflagp |= m->m_flag; 971558Srgrimes else 984065Swollman *thisflagp &= ~m->m_flag; 9923678Speter } else if (!getmnt_silent) { 1001558Srgrimes errx(1, "-o %s: option not supported", opt); 1014065Swollman } 1021558Srgrimes } 1031558Srgrimes 1041558Srgrimes free(optbuf); 1051558Srgrimes} 10652055Sphk 10752055Sphkvoid 108151048Srodrigcrmslashes(char *rrpin, char *rrpout) 10952055Sphk{ 11052055Sphk char *rrpoutstart; 11152055Sphk 11252055Sphk *rrpout = *rrpin; 11352055Sphk for (rrpoutstart = rrpout; *rrpin != '\0'; *rrpout++ = *rrpin++) { 11452055Sphk 11552055Sphk /* skip all double slashes */ 11652055Sphk while (*rrpin == '/' && *(rrpin + 1) == '/') 11752055Sphk rrpin++; 11852055Sphk } 11952055Sphk 12052055Sphk /* remove trailing slash if necessary */ 12152055Sphk if (rrpout - rrpoutstart > 1 && *(rrpout - 1) == '/') 12252055Sphk *(rrpout - 1) = '\0'; 12352055Sphk else 12452055Sphk *rrpout = '\0'; 12552055Sphk} 12652055Sphk 12752055Sphkvoid 128151048Srodrigccheckpath(const char *path, char *resolved) 12952055Sphk{ 13052055Sphk struct stat sb; 13152055Sphk 13252055Sphk if (realpath(path, resolved) != NULL && stat(resolved, &sb) == 0) { 133186505Sobrien if (!S_ISDIR(sb.st_mode)) 13452055Sphk errx(EX_USAGE, "%s: not a directory", resolved); 13552055Sphk } else 13652055Sphk errx(EX_USAGE, "%s: %s", resolved, strerror(errno)); 13752055Sphk} 138138095Sphk 139138095Sphkvoid 140152354Srodrigcbuild_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, 141152354Srodrigc size_t len) 142138095Sphk{ 143138095Sphk int i; 144138095Sphk 145138097Sdelphij if (*iovlen < 0) 146138095Sphk return; 147138095Sphk i = *iovlen; 148138095Sphk *iov = realloc(*iov, sizeof **iov * (i + 2)); 149138095Sphk if (*iov == NULL) { 150138095Sphk *iovlen = -1; 151138095Sphk return; 152138095Sphk } 153138095Sphk (*iov)[i].iov_base = strdup(name); 154138095Sphk (*iov)[i].iov_len = strlen(name) + 1; 155138095Sphk i++; 156138095Sphk (*iov)[i].iov_base = val; 157152417Srodrigc if (len == (size_t)-1) { 158152417Srodrigc if (val != NULL) 159152417Srodrigc len = strlen(val) + 1; 160152417Srodrigc else 161152417Srodrigc len = 0; 162152417Srodrigc } 163152354Srodrigc (*iov)[i].iov_len = (int)len; 164138095Sphk *iovlen = ++i; 165138095Sphk} 166152354Srodrigc 167152354Srodrigc/* 168152354Srodrigc * This function is needed for compatibility with parameters 169152354Srodrigc * which used to use the mount_argf() command for the old mount() syscall. 170152354Srodrigc */ 171152354Srodrigcvoid 172152354Srodrigcbuild_iovec_argf(struct iovec **iov, int *iovlen, const char *name, 173152354Srodrigc const char *fmt, ...) 174152354Srodrigc{ 175152354Srodrigc va_list ap; 176152354Srodrigc char val[255] = { 0 }; 177152354Srodrigc 178152354Srodrigc va_start(ap, fmt); 179186505Sobrien vsnprintf(val, sizeof(val), fmt, ap); 180152354Srodrigc va_end(ap); 181152354Srodrigc build_iovec(iov, iovlen, name, strdup(val), (size_t)-1); 182152354Srodrigc} 183