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: stable/11/sbin/mount/getmntopts.c 310374 2016-12-21 22:04:44Z brooks $"); 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> 491558Srgrimes 501558Srgrimes#include "mntopts.h" 511558Srgrimes 524065Swollmanint getmnt_silent = 0; 534065Swollman 541558Srgrimesvoid 55151048Srodrigcgetmntopts(const char *options, const struct mntopt *m0, int *flagp, 56151048Srodrigc int *altflagp) 571558Srgrimes{ 581558Srgrimes const struct mntopt *m; 593202Sache int negative, len; 6023678Speter char *opt, *optbuf, *p; 614065Swollman int *thisflagp; 621558Srgrimes 631558Srgrimes /* Copy option string, since it is about to be torn asunder... */ 641558Srgrimes if ((optbuf = strdup(options)) == NULL) 651558Srgrimes err(1, NULL); 661558Srgrimes 671558Srgrimes for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 681558Srgrimes /* Check for "no" prefix. */ 691558Srgrimes if (opt[0] == 'n' && opt[1] == 'o') { 701558Srgrimes negative = 1; 711558Srgrimes opt += 2; 721558Srgrimes } else 731558Srgrimes negative = 0; 741558Srgrimes 7523678Speter /* 7623678Speter * for options with assignments in them (ie. quotas) 7723678Speter * ignore the assignment as it's handled elsewhere 7823678Speter */ 7923678Speter p = strchr(opt, '='); 80123268Strhodes if (p != NULL) 8125301Smsmith *++p = '\0'; 8223678Speter 831558Srgrimes /* Scan option table. */ 843202Sache for (m = m0; m->m_option != NULL; ++m) { 853202Sache len = strlen(m->m_option); 863202Sache if (strncasecmp(opt, m->m_option, len) == 0) 87138094Sphk if (opt[len] == '\0' || opt[len] == '=') 88138094Sphk break; 893202Sache } 901558Srgrimes 9137425Scharnier /* Save flag, or fail if option is not recognized. */ 921558Srgrimes if (m->m_option) { 934065Swollman thisflagp = m->m_altloc ? altflagp : flagp; 941558Srgrimes if (negative == m->m_inverse) 954065Swollman *thisflagp |= m->m_flag; 961558Srgrimes else 974065Swollman *thisflagp &= ~m->m_flag; 9823678Speter } else if (!getmnt_silent) { 991558Srgrimes errx(1, "-o %s: option not supported", opt); 1004065Swollman } 1011558Srgrimes } 1021558Srgrimes 1031558Srgrimes free(optbuf); 1041558Srgrimes} 10552055Sphk 10652055Sphkvoid 107151048Srodrigcrmslashes(char *rrpin, char *rrpout) 10852055Sphk{ 10952055Sphk char *rrpoutstart; 11052055Sphk 11152055Sphk *rrpout = *rrpin; 11252055Sphk for (rrpoutstart = rrpout; *rrpin != '\0'; *rrpout++ = *rrpin++) { 11352055Sphk 11452055Sphk /* skip all double slashes */ 11552055Sphk while (*rrpin == '/' && *(rrpin + 1) == '/') 11652055Sphk rrpin++; 11752055Sphk } 11852055Sphk 11952055Sphk /* remove trailing slash if necessary */ 12052055Sphk if (rrpout - rrpoutstart > 1 && *(rrpout - 1) == '/') 12152055Sphk *(rrpout - 1) = '\0'; 12252055Sphk else 12352055Sphk *rrpout = '\0'; 12452055Sphk} 12552055Sphk 126230226Sjhint 127151048Srodrigccheckpath(const char *path, char *resolved) 12852055Sphk{ 12952055Sphk struct stat sb; 13052055Sphk 131230372Sjh if (realpath(path, resolved) == NULL || stat(resolved, &sb) != 0) 132230226Sjh return (1); 133230372Sjh if (!S_ISDIR(sb.st_mode)) { 134230372Sjh errno = ENOTDIR; 135230372Sjh return (1); 136230372Sjh } 137230226Sjh return (0); 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; 158152417Srodrigc if (len == (size_t)-1) { 159152417Srodrigc if (val != NULL) 160152417Srodrigc len = strlen(val) + 1; 161152417Srodrigc else 162152417Srodrigc len = 0; 163152417Srodrigc } 164152354Srodrigc (*iov)[i].iov_len = (int)len; 165138095Sphk *iovlen = ++i; 166138095Sphk} 167152354Srodrigc 168152354Srodrigc/* 169152354Srodrigc * This function is needed for compatibility with parameters 170152354Srodrigc * which used to use the mount_argf() command for the old mount() syscall. 171152354Srodrigc */ 172152354Srodrigcvoid 173152354Srodrigcbuild_iovec_argf(struct iovec **iov, int *iovlen, const char *name, 174152354Srodrigc const char *fmt, ...) 175152354Srodrigc{ 176152354Srodrigc va_list ap; 177152354Srodrigc char val[255] = { 0 }; 178152354Srodrigc 179152354Srodrigc va_start(ap, fmt); 180186505Sobrien vsnprintf(val, sizeof(val), fmt, ap); 181152354Srodrigc va_end(ap); 182152354Srodrigc build_iovec(iov, iovlen, name, strdup(val), (size_t)-1); 183152354Srodrigc} 184310374Sbrooks 185310374Sbrooks/* 186310374Sbrooks * Free the iovec and reset to NULL with zero length. Useful for calling 187310374Sbrooks * nmount in a loop. 188310374Sbrooks */ 189310374Sbrooksvoid 190310374Sbrooksfree_iovec(struct iovec **iov, int *iovlen) 191310374Sbrooks{ 192310374Sbrooks int i; 193310374Sbrooks 194310374Sbrooks for (i = 0; i < *iovlen; i++) 195310374Sbrooks free((*iov)[i].iov_base); 196310374Sbrooks free(*iov); 197310374Sbrooks} 198