1*5cf35d2aSpooka /* $NetBSD: getmntopts.c,v 1.4 2007/08/26 22:46:15 pooka Exp $ */
21edd42a9Sjdolecek
31edd42a9Sjdolecek /*-
41edd42a9Sjdolecek * Copyright (c) 1994
51edd42a9Sjdolecek * The Regents of the University of California. All rights reserved.
61edd42a9Sjdolecek *
71edd42a9Sjdolecek * Redistribution and use in source and binary forms, with or without
81edd42a9Sjdolecek * modification, are permitted provided that the following conditions
91edd42a9Sjdolecek * are met:
101edd42a9Sjdolecek * 1. Redistributions of source code must retain the above copyright
111edd42a9Sjdolecek * notice, this list of conditions and the following disclaimer.
121edd42a9Sjdolecek * 2. Redistributions in binary form must reproduce the above copyright
131edd42a9Sjdolecek * notice, this list of conditions and the following disclaimer in the
141edd42a9Sjdolecek * documentation and/or other materials provided with the distribution.
15eb7c1594Sagc * 3. Neither the name of the University nor the names of its contributors
161edd42a9Sjdolecek * may be used to endorse or promote products derived from this software
171edd42a9Sjdolecek * without specific prior written permission.
181edd42a9Sjdolecek *
191edd42a9Sjdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
201edd42a9Sjdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
211edd42a9Sjdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
221edd42a9Sjdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
231edd42a9Sjdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
241edd42a9Sjdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251edd42a9Sjdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261edd42a9Sjdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
271edd42a9Sjdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
281edd42a9Sjdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
291edd42a9Sjdolecek * SUCH DAMAGE.
301edd42a9Sjdolecek */
311edd42a9Sjdolecek
321edd42a9Sjdolecek #include <sys/cdefs.h>
331edd42a9Sjdolecek #ifndef lint
341edd42a9Sjdolecek #if 0
351edd42a9Sjdolecek static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
361edd42a9Sjdolecek #else
37*5cf35d2aSpooka __RCSID("$NetBSD: getmntopts.c,v 1.4 2007/08/26 22:46:15 pooka Exp $");
381edd42a9Sjdolecek #endif
391edd42a9Sjdolecek #endif /* not lint */
401edd42a9Sjdolecek
411edd42a9Sjdolecek #include <sys/param.h>
421edd42a9Sjdolecek #include <sys/mount.h>
431edd42a9Sjdolecek
441edd42a9Sjdolecek #include <err.h>
451edd42a9Sjdolecek #include <errno.h>
461edd42a9Sjdolecek #include <fstab.h>
471edd42a9Sjdolecek #include <stdlib.h>
481edd42a9Sjdolecek #include <string.h>
491edd42a9Sjdolecek
501edd42a9Sjdolecek #include <mntopts.h>
511edd42a9Sjdolecek
521edd42a9Sjdolecek int getmnt_silent = 0;
531edd42a9Sjdolecek
548099c830Schristos static const char errmsg[] = "-o %s: option not supported";
558099c830Schristos
568099c830Schristos struct mntoptparse {
571edd42a9Sjdolecek const char *options;
588099c830Schristos const struct mntopt *mopts;
598099c830Schristos char *optbuf;
608099c830Schristos char **optarg;
618099c830Schristos };
628099c830Schristos
638099c830Schristos const char *
getmntoptstr(mntoptparse_t mp,const char * opt)648099c830Schristos getmntoptstr(mntoptparse_t mp, const char *opt)
658099c830Schristos {
668099c830Schristos const struct mntopt *m;
678099c830Schristos
688099c830Schristos for (m = mp->mopts; m->m_option != NULL; m++)
698099c830Schristos if (strcasecmp(opt, m->m_option) == 0)
708099c830Schristos break;
718099c830Schristos
728099c830Schristos if (m->m_option == NULL) {
738099c830Schristos if (getmnt_silent == 0)
748099c830Schristos errx(1, errmsg, opt);
758099c830Schristos else
768099c830Schristos return NULL;
778099c830Schristos }
788099c830Schristos
798099c830Schristos return mp->optarg[m - mp->mopts];
808099c830Schristos }
818099c830Schristos
828099c830Schristos long
getmntoptnum(mntoptparse_t mp,const char * opt)838099c830Schristos getmntoptnum(mntoptparse_t mp, const char *opt)
848099c830Schristos {
858099c830Schristos char *ep;
868099c830Schristos long rv;
878099c830Schristos void (*fun)(int, const char *, ...) = NULL;
888099c830Schristos const char *val = getmntoptstr(mp, opt);
898099c830Schristos
908099c830Schristos if (val == NULL) {
918099c830Schristos if (getmnt_silent == 0)
928099c830Schristos errx(1, "Missing %s argument", opt);
938099c830Schristos else
948099c830Schristos return -1;
958099c830Schristos }
968099c830Schristos
978099c830Schristos errno = 0;
988099c830Schristos rv = strtol(val, &ep, 0);
998099c830Schristos
1008099c830Schristos if (*ep)
1018099c830Schristos fun = errx;
1028099c830Schristos
1038099c830Schristos if (errno == ERANGE && (rv == LONG_MAX || rv == LONG_MIN))
1048099c830Schristos fun = err;
1058099c830Schristos
1068099c830Schristos if (fun) {
1078099c830Schristos if (getmnt_silent != 0)
1088099c830Schristos return -1;
1098099c830Schristos (*fun)(1, "Invalid %s argument `%s'", opt, val);
1108099c830Schristos }
1118099c830Schristos return rv;
1128099c830Schristos }
1138099c830Schristos
1148099c830Schristos void
freemntopts(mntoptparse_t mp)1158099c830Schristos freemntopts(mntoptparse_t mp)
1168099c830Schristos {
1178099c830Schristos free(mp->optbuf);
1188099c830Schristos free(mp->optarg);
1198099c830Schristos free(mp);
1208099c830Schristos }
1218099c830Schristos
1228099c830Schristos mntoptparse_t
getmntopts(const char * options,const struct mntopt * m0,int * flagp,int * altflagp)1238099c830Schristos getmntopts(const char *options, const struct mntopt *m0, int *flagp,
1248099c830Schristos int *altflagp)
1251edd42a9Sjdolecek {
1261edd42a9Sjdolecek const struct mntopt *m;
1271edd42a9Sjdolecek int negative;
1288099c830Schristos char *opt, *p;
1291edd42a9Sjdolecek int *thisflagp;
1308099c830Schristos size_t nopts;
1318099c830Schristos mntoptparse_t mp;
1328099c830Schristos
1338099c830Schristos for (nopts = 0, m = m0; m->m_option != NULL; ++m, nopts++)
1348099c830Schristos continue;
1358099c830Schristos
1368099c830Schristos if ((mp = malloc(sizeof(struct mntoptparse))) == NULL)
1378099c830Schristos return NULL;
1381edd42a9Sjdolecek
1391edd42a9Sjdolecek /* Copy option string, since it is about to be torn asunder... */
1408099c830Schristos if ((mp->optbuf = strdup(options)) == NULL) {
1418099c830Schristos free(mp);
1428099c830Schristos return NULL;
1438099c830Schristos }
1441edd42a9Sjdolecek
1458099c830Schristos if ((mp->optarg = calloc(nopts, sizeof(char *))) == NULL) {
1468099c830Schristos free(mp->optbuf);
1478099c830Schristos free(mp);
1488099c830Schristos return NULL;
1498099c830Schristos }
1508099c830Schristos
1518099c830Schristos mp->mopts = m0;
1528099c830Schristos mp->options = options;
1538099c830Schristos
1548099c830Schristos for (opt = mp->optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
1551edd42a9Sjdolecek /* Check for "no" prefix. */
1561edd42a9Sjdolecek if (opt[0] == 'n' && opt[1] == 'o') {
1571edd42a9Sjdolecek negative = 1;
1581edd42a9Sjdolecek opt += 2;
1591edd42a9Sjdolecek } else
1601edd42a9Sjdolecek negative = 0;
1611edd42a9Sjdolecek
1621edd42a9Sjdolecek /*
1631edd42a9Sjdolecek * for options with assignments in them (ie. quotas)
1641edd42a9Sjdolecek * ignore the assignment as it's handled elsewhere
1651edd42a9Sjdolecek */
1661edd42a9Sjdolecek p = strchr(opt, '=');
1678099c830Schristos if (p) {
1688099c830Schristos *p++ = '\0';
1698099c830Schristos }
1701edd42a9Sjdolecek
1711edd42a9Sjdolecek /* Scan option table. */
1721edd42a9Sjdolecek for (m = m0; m->m_option != NULL; ++m)
1731edd42a9Sjdolecek if (strcasecmp(opt, m->m_option) == 0)
1741edd42a9Sjdolecek break;
1751edd42a9Sjdolecek
1761edd42a9Sjdolecek /* Save flag, or fail if option is not recognised. */
1771edd42a9Sjdolecek if (m->m_option) {
1788099c830Schristos mp->optarg[m - m0] = p;
1791edd42a9Sjdolecek thisflagp = m->m_altloc ? altflagp : flagp;
1801edd42a9Sjdolecek if (negative == m->m_inverse)
1811edd42a9Sjdolecek *thisflagp |= m->m_flag;
1821edd42a9Sjdolecek else
1831edd42a9Sjdolecek *thisflagp &= ~m->m_flag;
1841edd42a9Sjdolecek } else if (!getmnt_silent) {
1858099c830Schristos errx(1, errmsg, opt);
186*5cf35d2aSpooka } else {
187*5cf35d2aSpooka free(mp->optbuf);
188*5cf35d2aSpooka free(mp);
189*5cf35d2aSpooka
190*5cf35d2aSpooka return NULL;
1911edd42a9Sjdolecek }
1921edd42a9Sjdolecek }
1938099c830Schristos return mp;
1941edd42a9Sjdolecek }
195