getmntopts.c revision 152354
133965Sjdp/*-
233965Sjdp * Copyright (c) 1994
333965Sjdp *	The Regents of the University of California.  All rights reserved.
433965Sjdp *
533965Sjdp * Redistribution and use in source and binary forms, with or without
660517Sobrien * modification, are permitted provided that the following conditions
733965Sjdp * are met:
838891Sjdp * 1. Redistributions of source code must retain the above copyright
960517Sobrien *    notice, this list of conditions and the following disclaimer.
1038891Sjdp * 2. Redistributions in binary form must reproduce the above copyright
1138891Sjdp *    notice, this list of conditions and the following disclaimer in the
1238891Sjdp *    documentation and/or other materials provided with the distribution.
1377310Sobrien * 4. Neither the name of the University nor the names of its contributors
1438891Sjdp *    may be used to endorse or promote products derived from this software
1577310Sobrien *    without specific prior written permission.
1638891Sjdp *
1738891Sjdp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1838891Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1933965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2033965Sjdp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2133965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2233965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2333965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2433965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2533965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2633965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2733965Sjdp * SUCH DAMAGE.
2833965Sjdp */
2933965Sjdp
3033965Sjdp#if 0
3133965Sjdp#ifndef lint
3233965Sjdpstatic char sccsid[] = "@(#)getmntopts.c	8.3 (Berkeley) 3/29/95";
3333965Sjdp#endif /* not lint */
3433965Sjdp#endif
3533965Sjdp#include <sys/cdefs.h>
3633965Sjdp__FBSDID("$FreeBSD: head/sbin/mount/getmntopts.c 152354 2005-11-13 01:27:57Z rodrigc $");
3733965Sjdp
3833965Sjdp#include <sys/param.h>
3933965Sjdp#include <sys/mount.h>
4033965Sjdp#include <sys/stat.h>
4133965Sjdp#include <sys/uio.h>
4233965Sjdp
4360517Sobrien#include <assert.h>
4460517Sobrien#include <err.h>
4577310Sobrien#include <errno.h>
4677310Sobrien#include <stdarg.h>
4777310Sobrien#include <stdio.h>
4877310Sobrien#include <stdlib.h>
4977310Sobrien#include <string.h>
5077310Sobrien#include <sysexits.h>
5177310Sobrien
5277310Sobrien#include "mntopts.h"
5377310Sobrien
5477310Sobrienint getmnt_silent = 0;
5577310Sobrien
5677310Sobrienvoid
5777310Sobriengetmntopts(const char *options, const struct mntopt *m0, int *flagp,
5877310Sobrien	int *altflagp)
5977310Sobrien{
6077310Sobrien	const struct mntopt *m;
6177310Sobrien	int negative, len;
6277310Sobrien	char *opt, *optbuf, *p;
6377310Sobrien	int *thisflagp;
6477310Sobrien
6577310Sobrien	/* Copy option string, since it is about to be torn asunder... */
6638891Sjdp	if ((optbuf = strdup(options)) == NULL)
6738891Sjdp		err(1, NULL);
6833965Sjdp
6960517Sobrien	for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
7060517Sobrien		/* Check for "no" prefix. */
7160517Sobrien		if (opt[0] == 'n' && opt[1] == 'o') {
7260517Sobrien			negative = 1;
7360517Sobrien			opt += 2;
7460517Sobrien		} else
7560517Sobrien			negative = 0;
7660517Sobrien
7760517Sobrien		/*
7860517Sobrien		 * for options with assignments in them (ie. quotas)
7933965Sjdp		 * ignore the assignment as it's handled elsewhere
8033965Sjdp		 */
8160517Sobrien		p = strchr(opt, '=');
8260517Sobrien		if (p != NULL)
8360517Sobrien			 *++p = '\0';
8433965Sjdp
8560517Sobrien		/* Scan option table. */
8633965Sjdp		for (m = m0; m->m_option != NULL; ++m) {
8733965Sjdp			len = strlen(m->m_option);
8860517Sobrien			if (strncasecmp(opt, m->m_option, len) == 0)
8960517Sobrien				if (opt[len] == '\0' || opt[len] == '=')
9060517Sobrien					break;
9160517Sobrien		}
9260517Sobrien
9333965Sjdp		/* Save flag, or fail if option is not recognized. */
9433965Sjdp		if (m->m_option) {
9533965Sjdp			thisflagp = m->m_altloc ? altflagp : flagp;
9633965Sjdp			if (negative == m->m_inverse)
9733965Sjdp				*thisflagp |= m->m_flag;
9833965Sjdp			else
9933965Sjdp				*thisflagp &= ~m->m_flag;
10033965Sjdp		} else if (!getmnt_silent) {
10133965Sjdp			errx(1, "-o %s: option not supported", opt);
10233965Sjdp		}
10333965Sjdp	}
10433965Sjdp
10533965Sjdp	free(optbuf);
10633965Sjdp}
10733965Sjdp
10833965Sjdpvoid
10933965Sjdprmslashes(char *rrpin, char *rrpout)
11033965Sjdp{
11133965Sjdp	char *rrpoutstart;
11238891Sjdp
11338891Sjdp	*rrpout = *rrpin;
11433965Sjdp	for (rrpoutstart = rrpout; *rrpin != '\0'; *rrpout++ = *rrpin++) {
11538891Sjdp
11633965Sjdp		/* skip all double slashes */
11733965Sjdp		while (*rrpin == '/' && *(rrpin + 1) == '/')
11860517Sobrien			 rrpin++;
11960517Sobrien	}
12060517Sobrien
12177310Sobrien	/* remove trailing slash if necessary */
12260517Sobrien	if (rrpout - rrpoutstart > 1 && *(rrpout - 1) == '/')
12338891Sjdp		*(rrpout - 1) = '\0';
12433965Sjdp	else
12533965Sjdp		*rrpout = '\0';
12677310Sobrien}
12777310Sobrien
12877310Sobrienvoid
12977310Sobriencheckpath(const char *path, char *resolved)
13033965Sjdp{
13160517Sobrien	struct stat sb;
13233965Sjdp
13333965Sjdp	if (realpath(path, resolved) != NULL && stat(resolved, &sb) == 0) {
13460517Sobrien		if (!S_ISDIR(sb.st_mode))
13533965Sjdp			errx(EX_USAGE, "%s: not a directory", resolved);
13633965Sjdp	} else
13733965Sjdp		errx(EX_USAGE, "%s: %s", resolved, strerror(errno));
13860517Sobrien}
13960517Sobrien
14033965Sjdpvoid
14133965Sjdpbuild_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
14233965Sjdp	    size_t len)
14338891Sjdp{
14438891Sjdp	int i;
14538891Sjdp
14660517Sobrien	if (*iovlen < 0)
14738891Sjdp		return;
14838891Sjdp	i = *iovlen;
14933965Sjdp	*iov = realloc(*iov, sizeof **iov * (i + 2));
15033965Sjdp	if (*iov == NULL) {
15133965Sjdp		*iovlen = -1;
15233965Sjdp		return;
15333965Sjdp	}
15433965Sjdp	(*iov)[i].iov_base = strdup(name);
15533965Sjdp	(*iov)[i].iov_len = strlen(name) + 1;
15633965Sjdp	i++;
15733965Sjdp	(*iov)[i].iov_base = val;
15833965Sjdp	if (len == (size_t)-1)
15933965Sjdp		len = strlen(val) + 1;
16033965Sjdp	(*iov)[i].iov_len = (int)len;
16133965Sjdp	*iovlen = ++i;
16233965Sjdp}
16333965Sjdp
16433965Sjdp/*
16538891Sjdp * This function is needed for compatibility with parameters
16638891Sjdp * which used to use the mount_argf() command for the old mount() syscall.
16738891Sjdp */
16838891Sjdpvoid
16977310Sobrienbuild_iovec_argf(struct iovec **iov, int *iovlen, const char *name,
17033965Sjdp    const char *fmt, ...)
17133965Sjdp{
17238891Sjdp	va_list ap;
17338891Sjdp	char val[255] = { 0 };
17438891Sjdp
17538891Sjdp	va_start(ap, fmt);
17638891Sjdp	vsnprintf(val, sizeof(val), fmt, ap);
17738891Sjdp	va_end(ap);
17838891Sjdp	build_iovec(iov, iovlen, name, strdup(val), (size_t)-1);
17933965Sjdp}
18038891Sjdp