1168404Spjd/*-
2168404Spjd * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3168404Spjd * All rights reserved.
4168404Spjd *
5168404Spjd * Redistribution and use in source and binary forms, with or without
6168404Spjd * modification, are permitted provided that the following conditions
7168404Spjd * are met:
8168404Spjd * 1. Redistributions of source code must retain the above copyright
9168404Spjd *    notice, this list of conditions and the following disclaimer.
10168404Spjd * 2. Redistributions in binary form must reproduce the above copyright
11168404Spjd *    notice, this list of conditions and the following disclaimer in the
12168404Spjd *    documentation and/or other materials provided with the distribution.
13168404Spjd *
14168404Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17168404Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18168404Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19168404Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20168404Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24168404Spjd * SUCH DAMAGE.
25168404Spjd */
26168404Spjd
27168404Spjd/*
28168404Spjd * This file implements Solaris compatible zmount() function.
29168404Spjd */
30168404Spjd
31168404Spjd#include <sys/cdefs.h>
32168404Spjd__FBSDID("$FreeBSD: stable/10/cddl/compat/opensolaris/misc/zmount.c 326327 2017-11-28 17:30:25Z asomers $");
33168404Spjd
34168404Spjd#include <sys/param.h>
35168404Spjd#include <sys/mount.h>
36168404Spjd#include <sys/uio.h>
37168404Spjd#include <sys/mntent.h>
38185029Spjd#include <assert.h>
39168404Spjd#include <stdio.h>
40168404Spjd#include <stdlib.h>
41185029Spjd#include <string.h>
42219089Spjd#include <mnttab.h>
43168404Spjd
44168404Spjdstatic void
45168404Spjdbuild_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
46168404Spjd    size_t len)
47168404Spjd{
48168404Spjd	int i;
49168404Spjd
50168404Spjd	if (*iovlen < 0)
51168404Spjd		return;
52168404Spjd	i = *iovlen;
53168404Spjd	*iov = realloc(*iov, sizeof(**iov) * (i + 2));
54168404Spjd	if (*iov == NULL) {
55168404Spjd		*iovlen = -1;
56168404Spjd		return;
57168404Spjd	}
58168404Spjd	(*iov)[i].iov_base = strdup(name);
59168404Spjd	(*iov)[i].iov_len = strlen(name) + 1;
60168404Spjd	i++;
61168404Spjd	(*iov)[i].iov_base = val;
62168404Spjd	if (len == (size_t)-1) {
63168404Spjd		if (val != NULL)
64168404Spjd			len = strlen(val) + 1;
65168404Spjd		else
66168404Spjd			len = 0;
67168404Spjd	}
68168404Spjd	(*iov)[i].iov_len = (int)len;
69168404Spjd	*iovlen = ++i;
70168404Spjd}
71168404Spjd
72168404Spjdint
73168404Spjdzmount(const char *spec, const char *dir, int mflag, char *fstype,
74168404Spjd    char *dataptr, int datalen, char *optptr, int optlen)
75168404Spjd{
76168404Spjd	struct iovec *iov;
77326327Sasomers	char *optstr, *os, *p, *tofree;
78168404Spjd	int iovlen, rv;
79168404Spjd
80168404Spjd	assert(spec != NULL);
81168404Spjd	assert(dir != NULL);
82219089Spjd	assert(mflag == 0 || mflag == MS_RDONLY);
83168404Spjd	assert(fstype != NULL);
84168404Spjd	assert(strcmp(fstype, MNTTYPE_ZFS) == 0);
85168404Spjd	assert(dataptr == NULL);
86168404Spjd	assert(datalen == 0);
87168404Spjd	assert(optptr != NULL);
88168404Spjd	assert(optlen > 0);
89168404Spjd
90326327Sasomers	tofree = optstr = strdup(optptr);
91185029Spjd	assert(optstr != NULL);
92168404Spjd
93168404Spjd	iov = NULL;
94168404Spjd	iovlen = 0;
95219089Spjd	if (mflag & MS_RDONLY)
96219089Spjd		build_iovec(&iov, &iovlen, "ro", NULL, 0);
97168404Spjd	build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1);
98168404Spjd	build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, dir),
99168404Spjd	    (size_t)-1);
100168404Spjd	build_iovec(&iov, &iovlen, "from", __DECONST(char *, spec), (size_t)-1);
101326327Sasomers	while ((p = strsep(&optstr, ",/")) != NULL)
102326327Sasomers		build_iovec(&iov, &iovlen, p, NULL, (size_t)-1);
103168404Spjd	rv = nmount(iov, iovlen, 0);
104326327Sasomers	free(tofree);
105168404Spjd	return (rv);
106168404Spjd}
107