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