1 #include "ratfs.h" 2 3 #define SRVFILE "/srv/ratify" 4 #define MOUNTPOINT "/mail/ratify" 5 #define CTLFILE "/mail/lib/blocked" 6 #define CONFFILE "/mail/lib/smtpd.conf.ext" 7 8 typedef struct Filetree Filetree; 9 10 /* prototype file tree */ 11 struct Filetree 12 { 13 int level; 14 char *name; 15 ushort type; 16 int mode; 17 ulong qid; 18 }; 19 20 /* names of first-level directories - must be in order of level*/ 21 Filetree filetree[] = 22 { 23 0, "/", Directory, 0555|DMDIR, Qroot, 24 1, "allow", Addrdir, 0555|DMDIR, Qallow, 25 1, "delay", Addrdir, 0555|DMDIR, Qdelay, 26 1, "block", Addrdir, 0555|DMDIR, Qblock, 27 1, "dial", Addrdir, 0555|DMDIR, Qdial, 28 1, "deny", Addrdir, 0555|DMDIR, Qdeny, 29 1, "trusted", Trusted, 0777|DMDIR, Qtrusted, /* creation allowed */ 30 1, "ctl", Ctlfile, 0222, Qctl, 31 2, "ip", IPaddr, 0555|DMDIR, Qaddr, 32 2, "account", Acctaddr, 0555|DMDIR, Qaddr, 33 0, 0, 0, 0, 0, 34 35 }; 36 37 int debugfd = -1; 38 int trustedqid = Qtrustedfile; 39 char *ctlfile = CTLFILE; 40 char *conffile = CONFFILE; 41 42 #pragma varargck type "I" Cidraddr* 43 44 static int ipconv(Fmt*); 45 static void post(int, char*); 46 static void setroot(void); 47 48 void 49 usage(void) 50 { 51 fprint(2, "ratfs [-d] [-c conffile] [-f ctlfile] [-m mountpoint]\n"); 52 exits("usage"); 53 } 54 55 void 56 main(int argc, char *argv[]) 57 { 58 char *mountpoint = MOUNTPOINT; 59 int p[2]; 60 61 ARGBEGIN { 62 case 'c': 63 conffile = ARGF(); 64 break; 65 case 'd': 66 debugfd = 2; /* stderr*/ 67 break; 68 case 'f': 69 ctlfile = ARGF(); 70 break; 71 case 'm': 72 mountpoint = ARGF(); 73 break; 74 } ARGEND 75 if(argc != 0) 76 usage(); 77 78 fmtinstall('I', ipconv); 79 setroot(); 80 getconf(); 81 reload(); 82 83 /* get a pipe and mount it in /srv */ 84 if(pipe(p) < 0) 85 fatal("pipe failed: %r"); 86 srvfd = p[0]; 87 post(p[1], mountpoint); 88 89 /* start the 9fs protocol */ 90 switch(rfork(RFPROC|RFNAMEG|RFENVG|RFFDG|RFNOTEG|RFREND)){ 91 case -1: 92 fatal("fork: %r"); 93 case 0: 94 /* seal off standard input/output */ 95 close(0); 96 open("/dev/null", OREAD); 97 close(1); 98 open("/dev/null", OWRITE); 99 100 close(p[1]); 101 fmtinstall('F', fcallfmt); /* debugging */ 102 io(); 103 fprint(2, "ratfs dying\n"); 104 break; 105 default: 106 close(p[0]); 107 if(mount(p[1], -1, mountpoint, MREPL|MCREATE, "") < 0) 108 fatal("mount failed: %r"); 109 } 110 exits(0); 111 } 112 113 static void 114 setroot(void) 115 { 116 Filetree *fp; 117 Node *np; 118 int qid; 119 120 root = 0; 121 qid = Qaddr; 122 for(fp = filetree; fp->name; fp++) { 123 switch(fp->level) { 124 case 0: /* root */ 125 case 1: /* second level directory */ 126 newnode(root, fp->name, fp->type, fp->mode, fp->qid); 127 break; 128 case 2: /* lay down the Ipaddr and Acctaddr subdirectories */ 129 for (np = root->children; np; np = np->sibs){ 130 if(np->d.type == Addrdir) 131 newnode(np, fp->name, fp->type, fp->mode, qid++); 132 } 133 break; 134 default: 135 fatal("bad filetree"); 136 } 137 } 138 dummy.d.type = Dummynode; 139 dummy.d.mode = 0444; 140 dummy.d.uid = "upas"; 141 dummy.d.gid = "upas"; 142 dummy.d.atime = dummy.d.mtime = time(0); 143 dummy.d.qid.path = Qdummy; /* for now */ 144 } 145 146 static void 147 post(int fd, char *mountpoint) 148 { 149 150 int f; 151 char buf[128]; 152 153 if(access(SRVFILE,0) >= 0){ 154 /* 155 * If we can open and mount the /srv node, 156 * another server is already running, so just exit. 157 */ 158 f = open(SRVFILE, ORDWR); 159 if(f >= 0 && mount(f, -1, mountpoint, MREPL|MCREATE, "") >= 0){ 160 unmount(0, mountpoint); 161 close(f); 162 exits(0); 163 } 164 remove(SRVFILE); 165 } 166 167 /* 168 * create the server node and post our pipe to it 169 */ 170 f = create(SRVFILE, OWRITE, 0666); 171 if(f < 0) 172 fatal("can't create %s", SRVFILE); 173 174 sprint(buf, "%d", fd); 175 if(write(f, buf, strlen(buf)) != strlen(buf)) 176 fatal("can't write %s", SRVFILE); 177 178 close(f); 179 } 180 181 /* 182 * print message and die 183 */ 184 void 185 fatal(char *fmt, ...) 186 { 187 va_list arg; 188 char buf[8*1024]; 189 190 va_start(arg, fmt); 191 vseprint(buf, buf + (sizeof(buf)-1) / sizeof(*buf), fmt, arg); 192 va_end(arg); 193 194 fprint(2, "%s: %s\n", argv0, buf); 195 exits(buf); 196 } 197 198 /* 199 * create a new directory node 200 */ 201 Node* 202 newnode(Node *parent, char *name, ushort type, int mode, ulong qid) 203 { 204 Node *np; 205 206 np = mallocz(sizeof(Node), 1); 207 if(np == 0) 208 fatal("out of memory"); 209 np->d.name = atom(name); 210 np->d.type = type; 211 np->d.mode = mode; 212 np->d.mtime = np->d.atime = time(0); 213 np->d.uid = atom("upas"); 214 np->d.gid = atom("upas"); 215 np->d.muid = atom("upas"); 216 if(np->d.mode&DMDIR) 217 np->d.qid.type = QTDIR; 218 np->d.qid.path = qid; 219 np->d.qid.vers = 0; 220 if(parent){ 221 np->parent = parent; 222 np->sibs = parent->children; 223 parent->children = np; 224 parent->count++; 225 } else { 226 /* the root node */ 227 root = np; 228 np->parent = np; 229 np->children = 0; 230 np->sibs = 0; 231 } 232 return np; 233 } 234 235 void 236 printnode(Node *np) 237 { 238 fprint(debugfd, "Node at %p: %s (%s %s)", np, np->d.name, np->d.uid, np->d.gid); 239 if(np->d.qid.type&QTDIR) 240 fprint(debugfd, " QTDIR"); 241 fprint(debugfd, "\n"); 242 fprint(debugfd,"\tQID: %llud.%lud Mode: %lo Type: %d\n", np->d.qid.path, 243 np->d.qid.vers, np->d.mode, np->d.type); 244 fprint(debugfd, "\tMod: %.15s Acc: %.15s Count: %d\n", ctime(np->d.mtime)+4, 245 ctime(np->d.atime)+4, np->count); 246 switch(np->d.type) 247 { 248 case Directory: 249 fprint(debugfd, "\tDirectory Child: %p", np->children); 250 break; 251 case Addrdir: 252 fprint(debugfd, "\tAddrdir Child: %p", np->children); 253 break; 254 case IPaddr: 255 fprint(debugfd, "\tIPaddr Base: %p Alloc: %d BaseQid %lud", np->addrs, 256 np->allocated, np->baseqid); 257 break; 258 case Acctaddr: 259 fprint(debugfd, "\tAcctaddr Base: %p Alloc: %d BaseQid %lud", np->addrs, 260 np->allocated, np->baseqid); 261 break; 262 case Trusted: 263 fprint(debugfd, "\tTrusted Child: %p", np->children); 264 break; 265 case Trustedperm: 266 fprint(debugfd, "\tPerm Trustedfile: %I", &np->ip); 267 break; 268 case Trustedtemp: 269 fprint(debugfd, "\tTemp Trustedfile: %I", &np->ip); 270 break; 271 case Ctlfile: 272 fprint(debugfd, "\tCtlfile"); 273 break; 274 case Dummynode: 275 fprint(debugfd, "\tDummynode"); 276 break; 277 default: 278 fprint(debugfd, "\tUnknown Node Type\n\n"); 279 return; 280 } 281 fprint(debugfd, " Parent %p Sib: %p\n\n", np->parent, np->sibs); 282 } 283 284 void 285 printfid(Fid *fp) 286 { 287 fprint(debugfd, "FID: %d (%s %s) Busy: %d Open: %d\n", fp->fid, fp->name, 288 fp->uid, fp->busy, fp->open); 289 printnode(fp->node); 290 } 291 292 void 293 printtree(Node *np) 294 { 295 printnode(np); 296 if(np->d.type == IPaddr 297 || np->d.type == Acctaddr 298 || np->d.type == Trustedperm 299 || np->d.type == Trustedtemp) 300 return; 301 for (np = np->children; np; np = np->sibs) 302 printtree(np); 303 } 304 305 static int 306 ipconv(Fmt *f) 307 { 308 Cidraddr *ip; 309 int i, j; 310 char *p; 311 312 ip = va_arg(f->args, Cidraddr*); 313 p = (char*)&ip->ipaddr; 314 i = 0; 315 for (j = ip->mask; j; j <<= 1) 316 i++; 317 return fmtprint(f, "%d.%d.%d.%d/%d", p[3]&0xff, p[2]&0xff, p[1]&0xff, p[0]&0xff, i); 318 } 319