1/*	$NetBSD$	*/
2
3/*-
4 * Copyright (c)2010,2011 YAMAMOTO Takashi,
5 * 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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30#ifndef lint
31__RCSID("$NetBSD$");
32#endif /* not lint */
33
34#include <err.h>
35#include <errno.h>
36#include <mntopts.h>
37#include <paths.h>
38#include <puffs.h>
39#include <stdbool.h>
40#include <stdlib.h>
41#include <unistd.h>
42
43#include "pgfs.h"
44#include "pgfs_db.h"
45
46#define	PGFS_MNT_ALT_DUMMY	1
47#define	PGFS_MNT_ALT_DEBUG	2
48
49int
50main(int argc, char *argv[])
51{
52	extern char *optarg;
53	extern int optind;
54	mntoptparse_t mp;
55	struct puffs_usermount *pu;
56	struct puffs_ops *pops;
57	int mntflags;
58	int altmntflags;
59	int ch;
60	int error;
61	const char *dbname = NULL;
62	const char *dbuser = NULL;
63	static const struct mntopt mopts[] = {
64		MOPT_STDOPTS,
65		MOPT_SYNC,
66		{ .m_option = "dbname", .m_inverse = 0,
67		  .m_flag = PGFS_MNT_ALT_DUMMY, .m_altloc = 1, },
68		{ .m_option = "dbuser", .m_inverse = 0,
69		  .m_flag = PGFS_MNT_ALT_DUMMY, .m_altloc = 1, },
70		{ .m_option = "debug", .m_inverse = 0,
71		  .m_flag = PGFS_MNT_ALT_DEBUG, .m_altloc = 1, },
72		{ .m_option = "nconn", .m_inverse = 0,
73		  .m_flag = PGFS_MNT_ALT_DUMMY, .m_altloc = 1, },
74		MOPT_NULL,
75	};
76	uint32_t pflags = PUFFS_KFLAG_NOCACHE_NAME|PUFFS_KFLAG_WTCACHE;
77	unsigned int nconn = 8;
78	bool debug = false;
79	bool dosync;
80
81	mntflags = 0;
82	altmntflags = 0;
83	while ((ch = getopt(argc, argv, "o:")) != -1) {
84		long v;
85
86		switch (ch) {
87		case 'o':
88			mp = getmntopts(optarg, mopts, &mntflags,
89			    &altmntflags);
90			if (mp == NULL) {
91				err(EXIT_FAILURE, "getmntopts");
92			}
93			getmnt_silent = 1; /* XXX silly api */
94			dbname = getmntoptstr(mp, "dbname");
95			dbuser = getmntoptstr(mp, "dbuser");
96			v = getmntoptnum(mp, "nconn");
97			getmnt_silent = 0;
98			if (v != -1) {
99				nconn = v;
100			}
101			if ((altmntflags & PGFS_MNT_ALT_DEBUG) != 0) {
102				debug = true;
103			}
104			freemntopts(mp);
105			break;
106		}
107	}
108	argc -= optind;
109	argv += optind;
110
111	PUFFSOP_INIT(pops);
112	PUFFSOP_SETFSNOP(pops, unmount);
113	PUFFSOP_SETFSNOP(pops, sync);
114	PUFFSOP_SET(pops, pgfs, fs, statvfs);
115	PUFFSOP_SET(pops, pgfs, node, readdir);
116	PUFFSOP_SET(pops, pgfs, node, getattr);
117	PUFFSOP_SET(pops, pgfs, node, lookup);
118	PUFFSOP_SET(pops, pgfs, node, mkdir);
119	PUFFSOP_SET(pops, pgfs, node, create);
120	PUFFSOP_SET(pops, pgfs, node, read);
121	PUFFSOP_SET(pops, pgfs, node, write);
122	PUFFSOP_SET(pops, pgfs, node, link);
123	PUFFSOP_SET(pops, pgfs, node, remove);
124	PUFFSOP_SET(pops, pgfs, node, rmdir);
125	PUFFSOP_SET(pops, pgfs, node, inactive);
126	PUFFSOP_SET(pops, pgfs, node, setattr);
127	PUFFSOP_SET(pops, pgfs, node, rename);
128	PUFFSOP_SET(pops, pgfs, node, symlink);
129	PUFFSOP_SET(pops, pgfs, node, readlink);
130	PUFFSOP_SET(pops, pgfs, node, access);
131	dosync = (mntflags & MNT_SYNCHRONOUS) != 0;
132	if (!dosync) {
133		PUFFSOP_SET(pops, pgfs, node, fsync);
134	}
135	if (debug) {
136		pflags |= PUFFS_FLAG_OPDUMP;
137	}
138	pu = puffs_init(pops, _PATH_PUFFS, "pgfs", NULL, pflags);
139	if (pu == NULL) {
140		err(EXIT_FAILURE, "puffs_init");
141	}
142	error = pgfs_connectdb(pu, dbname, dbuser, debug, dosync, nconn);
143	if (error != 0) {
144		errno = error;
145		err(EXIT_FAILURE, "pgfs_connectdb");
146	}
147	if (!debug) {
148		if (puffs_daemon(pu, 1, 1)) {
149			err(EXIT_FAILURE, "puffs_daemon");
150		}
151	}
152	if (puffs_mount(pu, argv[1], mntflags, pgfs_root_cookie()) == -1) {
153		err(EXIT_FAILURE, "puffs_mount");
154	}
155	if (!debug) {
156		char tmpl[] = "/tmp/pgfs.XXXXXXXX";
157		const char *path;
158		int fd;
159		int ret;
160
161		path = mkdtemp(tmpl);
162		if (path == NULL) {
163			err(EXIT_FAILURE, "mkdtemp");
164		}
165		fd = open(path, O_RDONLY | O_DIRECTORY);
166		if (fd == -1) {
167			err(EXIT_FAILURE, "open %s", path);
168		}
169		ret = rmdir(path);
170		if (ret != 0) {
171			err(EXIT_FAILURE, "rmdir %s", path);
172		}
173		ret = fchroot(fd);
174		if (ret != 0) {
175			err(EXIT_FAILURE, "fchroot");
176		}
177		ret = close(fd);
178		if (ret != 0) {
179			err(EXIT_FAILURE, "close");
180		}
181	}
182	if (puffs_mainloop(pu) == -1) {
183		err(EXIT_FAILURE, "puffs_mainloop");
184	}
185	exit(EXIT_SUCCESS);
186}
187