1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1992, 1993, 1994
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software donated to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/param.h>
36#include <sys/mount.h>
37#include <sys/stat.h>
38#include <sys/uio.h>
39
40#include <err.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <sysexits.h>
45#include <unistd.h>
46
47#include "mntopts.h"
48
49static void	usage(void) __dead2;
50
51static int
52stat_realpath(const char *path, char *resolved, struct stat *sbp)
53{
54	if (realpath(path, resolved) == NULL || stat(resolved, sbp) != 0)
55		return (1);
56	return (0);
57}
58
59int
60main(int argc, char *argv[])
61{
62	struct iovec *iov;
63	char *p, *val;
64	char mountpoint[MAXPATHLEN];
65	char target[MAXPATHLEN];
66	char errmsg[255];
67	int ch, iovlen;
68	char nullfs[] = "nullfs";
69	struct stat target_stat;
70	struct stat mountpoint_stat;
71
72	iov = NULL;
73	iovlen = 0;
74	errmsg[0] = '\0';
75	while ((ch = getopt(argc, argv, "o:")) != -1)
76		switch(ch) {
77		case 'o':
78			val = strdup("");
79			p = strchr(optarg, '=');
80			if (p != NULL) {
81				free(val);
82				*p = '\0';
83				val = p + 1;
84			}
85			build_iovec(&iov, &iovlen, optarg, val, (size_t)-1);
86			break;
87		case '?':
88		default:
89			usage();
90		}
91	argc -= optind;
92	argv += optind;
93
94	if (argc != 2)
95		usage();
96
97	/* resolve target and mountpoint with realpath(3) */
98	if (stat_realpath(argv[0], target, &target_stat) != 0)
99		err(EX_USAGE, "%s", target);
100	if (stat_realpath(argv[1], mountpoint, &mountpoint_stat) != 0)
101		err(EX_USAGE, "%s", mountpoint);
102	if (!S_ISDIR(target_stat.st_mode) && !S_ISREG(target_stat.st_mode))
103		errx(EX_USAGE, "%s: must be either a file or directory",
104		    target);
105	if ((target_stat.st_mode & S_IFMT) !=
106	    (mountpoint_stat.st_mode & S_IFMT))
107		errx(EX_USAGE,
108		    "%s: must be same type as %s (file or directory)",
109		    mountpoint, target);
110
111	build_iovec(&iov, &iovlen, "fstype", nullfs, (size_t)-1);
112	build_iovec(&iov, &iovlen, "fspath", mountpoint, (size_t)-1);
113	build_iovec(&iov, &iovlen, "target", target, (size_t)-1);
114	build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
115	if (nmount(iov, iovlen, 0) < 0) {
116		if (errmsg[0] != 0)
117			err(1, "%s: %s", mountpoint, errmsg);
118		else
119			err(1, "%s", mountpoint);
120	}
121	exit(0);
122}
123
124static void
125usage(void)
126{
127	(void)fprintf(stderr,
128		"usage: mount_nullfs [-o options] target mount-point\n");
129	exit(1);
130}
131