1/* $NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $ */ 2 3/*- 4 * Copyright (c) 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34#if 0 35static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95"; 36#else 37__RCSID("$NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $"); 38#endif 39#endif /* not lint */ 40 41#include <sys/param.h> 42 43#include <err.h> 44#include <errno.h> 45#include <fstab.h> 46#include <stdlib.h> 47#include <string.h> 48 49#include <mntopts.h> 50 51int getmnt_silent = 0; 52 53static const char errmsg[] = "-o %s: option not supported"; 54 55struct mntoptparse { 56 const char *options; 57 const struct mntopt *mopts; 58 char *optbuf; 59 char **optarg; 60}; 61 62const char * 63getmntoptstr(mntoptparse_t mp, const char *opt) 64{ 65 const struct mntopt *m; 66 67 for (m = mp->mopts; m->m_option != NULL; m++) 68 if (strcasecmp(opt, m->m_option) == 0) 69 break; 70 71 if (m->m_option == NULL) { 72 if (getmnt_silent == 0) 73 errx(1, errmsg, opt); 74 else 75 return NULL; 76 } 77 78 return mp->optarg[m - mp->mopts]; 79} 80 81long 82getmntoptnum(mntoptparse_t mp, const char *opt) 83{ 84 char *ep; 85 long rv; 86 void (*fun)(int, const char *, ...) = NULL; 87 const char *val = getmntoptstr(mp, opt); 88 89 if (val == NULL) { 90 if (getmnt_silent == 0) 91 errx(1, "Missing %s argument", opt); 92 else 93 return -1; 94 } 95 96 errno = 0; 97 rv = strtol(val, &ep, 0); 98 99 if (*ep) 100 fun = errx; 101 102 if (errno == ERANGE && (rv == LONG_MAX || rv == LONG_MIN)) 103 fun = err; 104 105 if (fun) { 106 if (getmnt_silent != 0) 107 return -1; 108 (*fun)(1, "Invalid %s argument `%s'", opt, val); 109 } 110 return rv; 111} 112 113void 114freemntopts(mntoptparse_t mp) 115{ 116 free(mp->optbuf); 117 free(mp->optarg); 118 free(mp); 119} 120 121mntoptparse_t 122getmntopts(const char *options, const struct mntopt *m0, int *flagp, 123 int *altflagp) 124{ 125 const struct mntopt *m; 126 int negative; 127 char *opt, *p, *ctx = NULL; 128 int *thisflagp; 129 size_t nopts; 130 mntoptparse_t mp; 131 132 for (nopts = 0, m = m0; m->m_option != NULL; ++m, nopts++) 133 continue; 134 135 if ((mp = malloc(sizeof(struct mntoptparse))) == NULL) 136 return NULL; 137 138 /* Copy option string, since it is about to be torn asunder... */ 139 if ((mp->optbuf = strdup(options)) == NULL) { 140 free(mp); 141 return NULL; 142 } 143 144 if ((mp->optarg = calloc(nopts, sizeof(char *))) == NULL) { 145 free(mp->optbuf); 146 free(mp); 147 return NULL; 148 } 149 150 mp->mopts = m0; 151 mp->options = options; 152 153 for (opt = mp->optbuf; (opt = strtok_r(opt, ",", &ctx)) != NULL; opt = NULL) { 154 /* Check for "no" prefix. */ 155 if (opt[0] == 'n' && opt[1] == 'o') { 156 negative = 1; 157 opt += 2; 158 } else 159 negative = 0; 160 161 /* 162 * for options with assignments in them (ie. quotas) 163 * ignore the assignment as it's handled elsewhere 164 */ 165 p = strchr(opt, '='); 166 if (p) { 167 *p++ = '\0'; 168 } 169 170 /* Scan option table. */ 171 for (m = m0; m->m_option != NULL; ++m) 172 if (strcasecmp(opt, m->m_option) == 0) 173 break; 174 175 /* Save flag, or fail if option is not recognised. */ 176 if (m->m_option) { 177 mp->optarg[m - m0] = p; 178 thisflagp = m->m_altloc ? altflagp : flagp; 179 if (negative == m->m_inverse) 180 *thisflagp |= m->m_flag; 181 else 182 *thisflagp &= ~m->m_flag; 183 } else if (!getmnt_silent) { 184 errx(1, errmsg, opt); 185 } 186 } 187 return mp; 188} 189