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