1 /* $NetBSD: mount.c,v 1.4 2013/04/22 13:28:28 yamt Exp $ */ 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: mount.c,v 1.4 2013/04/22 13:28:28 yamt Exp $"); 32 #endif /* not lint */ 33 34 #include <err.h> 35 #include <errno.h> 36 #include <locale.h> 37 #include <mntopts.h> 38 #include <paths.h> 39 #include <puffs.h> 40 #include <stdbool.h> 41 #include <stdlib.h> 42 #include <unistd.h> 43 #include <util.h> 44 45 #include "pgfs.h" 46 #include "pgfs_db.h" 47 48 #define PGFS_MNT_ALT_DUMMY 1 49 #define PGFS_MNT_ALT_DEBUG 2 50 51 static char * 52 xstrcpy(const char *str) 53 { 54 char *n; 55 size_t len; 56 57 if (str == NULL) { 58 return NULL; 59 } 60 len = strlen(str); 61 n = emalloc(len + 1); 62 memcpy(n, str, len + 1); 63 return n; 64 } 65 66 int 67 main(int argc, char *argv[]) 68 { 69 extern char *optarg; 70 extern int optind; 71 mntoptparse_t mp; 72 struct puffs_usermount *pu; 73 struct puffs_ops *pops; 74 int mntflags; 75 int altmntflags; 76 int ch; 77 int error; 78 const char *dbname = NULL; 79 const char *dbuser = NULL; 80 static const struct mntopt mopts[] = { 81 MOPT_STDOPTS, 82 MOPT_SYNC, 83 { .m_option = "dbname", .m_inverse = 0, 84 .m_flag = PGFS_MNT_ALT_DUMMY, .m_altloc = 1, }, 85 { .m_option = "dbuser", .m_inverse = 0, 86 .m_flag = PGFS_MNT_ALT_DUMMY, .m_altloc = 1, }, 87 { .m_option = "debug", .m_inverse = 0, 88 .m_flag = PGFS_MNT_ALT_DEBUG, .m_altloc = 1, }, 89 { .m_option = "nconn", .m_inverse = 0, 90 .m_flag = PGFS_MNT_ALT_DUMMY, .m_altloc = 1, }, 91 MOPT_NULL, 92 }; 93 uint32_t pflags = PUFFS_KFLAG_IAONDEMAND; 94 unsigned int nconn = 8; 95 bool debug = false; 96 bool dosync; 97 98 setlocale(LC_ALL, ""); 99 100 mntflags = 0; 101 altmntflags = 0; 102 while ((ch = getopt(argc, argv, "o:")) != -1) { 103 long v; 104 105 switch (ch) { 106 case 'o': 107 mp = getmntopts(optarg, mopts, &mntflags, 108 &altmntflags); 109 if (mp == NULL) { 110 err(EXIT_FAILURE, "getmntopts"); 111 } 112 getmnt_silent = 1; /* XXX silly api */ 113 dbname = xstrcpy(getmntoptstr(mp, "dbname")); 114 dbuser = xstrcpy(getmntoptstr(mp, "dbuser")); 115 v = getmntoptnum(mp, "nconn"); 116 getmnt_silent = 0; 117 if (v != -1) { 118 nconn = v; 119 } 120 if ((altmntflags & PGFS_MNT_ALT_DEBUG) != 0) { 121 debug = true; 122 } 123 freemntopts(mp); 124 break; 125 } 126 } 127 argc -= optind; 128 argv += optind; 129 130 PUFFSOP_INIT(pops); 131 PUFFSOP_SETFSNOP(pops, unmount); 132 PUFFSOP_SETFSNOP(pops, sync); 133 PUFFSOP_SET(pops, pgfs, fs, statvfs); 134 PUFFSOP_SET(pops, pgfs, node, readdir); 135 PUFFSOP_SET(pops, pgfs, node, getattr); 136 PUFFSOP_SET(pops, pgfs, node, lookup); 137 PUFFSOP_SET(pops, pgfs, node, mkdir); 138 PUFFSOP_SET(pops, pgfs, node, create); 139 PUFFSOP_SET(pops, pgfs, node, read); 140 PUFFSOP_SET(pops, pgfs, node, write); 141 PUFFSOP_SET(pops, pgfs, node, link); 142 PUFFSOP_SET(pops, pgfs, node, remove); 143 PUFFSOP_SET(pops, pgfs, node, rmdir); 144 PUFFSOP_SET(pops, pgfs, node, inactive); 145 PUFFSOP_SET(pops, pgfs, node, setattr); 146 PUFFSOP_SET(pops, pgfs, node, rename); 147 PUFFSOP_SET(pops, pgfs, node, symlink); 148 PUFFSOP_SET(pops, pgfs, node, readlink); 149 PUFFSOP_SET(pops, pgfs, node, access); 150 dosync = (mntflags & MNT_SYNCHRONOUS) != 0; 151 if (!dosync) { 152 PUFFSOP_SET(pops, pgfs, node, fsync); 153 } 154 if (debug) { 155 pflags |= PUFFS_FLAG_OPDUMP; 156 } 157 pu = puffs_init(pops, _PATH_PUFFS, "pgfs", NULL, pflags); 158 if (pu == NULL) { 159 err(EXIT_FAILURE, "puffs_init"); 160 } 161 error = pgfs_connectdb(pu, dbname, dbuser, debug, dosync, nconn); 162 free(__UNCONST(dbname)); 163 free(__UNCONST(dbuser)); 164 if (error != 0) { 165 errno = error; 166 err(EXIT_FAILURE, "pgfs_connectdb"); 167 } 168 if (!debug) { 169 if (puffs_daemon(pu, 1, 1)) { 170 err(EXIT_FAILURE, "puffs_daemon"); 171 } 172 } 173 if (puffs_mount(pu, argv[1], mntflags, pgfs_root_cookie()) == -1) { 174 err(EXIT_FAILURE, "puffs_mount"); 175 } 176 if (!debug) { 177 char tmpl[] = "/tmp/pgfs.XXXXXXXX"; 178 const char *path; 179 int fd; 180 int ret; 181 182 path = mkdtemp(tmpl); 183 if (path == NULL) { 184 err(EXIT_FAILURE, "mkdtemp"); 185 } 186 fd = open(path, O_RDONLY | O_DIRECTORY); 187 if (fd == -1) { 188 err(EXIT_FAILURE, "open %s", path); 189 } 190 ret = rmdir(path); 191 if (ret != 0) { 192 err(EXIT_FAILURE, "rmdir %s", path); 193 } 194 ret = fchroot(fd); 195 if (ret != 0) { 196 err(EXIT_FAILURE, "fchroot"); 197 } 198 ret = close(fd); 199 if (ret != 0) { 200 err(EXIT_FAILURE, "close"); 201 } 202 } 203 if (puffs_mainloop(pu) == -1) { 204 err(EXIT_FAILURE, "puffs_mainloop"); 205 } 206 exit(EXIT_SUCCESS); 207 } 208