13e12c5d1SDavid du Colombier /* 23e12c5d1SDavid du Colombier * exportfs - Export a plan 9 name space across a network 33e12c5d1SDavid du Colombier */ 43e12c5d1SDavid du Colombier #include <u.h> 53e12c5d1SDavid du Colombier #include <libc.h> 63e12c5d1SDavid du Colombier #include <auth.h> 7219b2ee8SDavid du Colombier #include <fcall.h> 8*9a747e4fSDavid du Colombier #include <libsec.h> 93e12c5d1SDavid du Colombier #define Extern 103e12c5d1SDavid du Colombier #include "exportfs.h" 113e12c5d1SDavid du Colombier 12*9a747e4fSDavid du Colombier #define QIDPATH ((1LL<<48)-1) 13*9a747e4fSDavid du Colombier vlong newqid = 0; 14*9a747e4fSDavid du Colombier 15*9a747e4fSDavid du Colombier enum { 16*9a747e4fSDavid du Colombier Encnone, 17*9a747e4fSDavid du Colombier Encssl, 18*9a747e4fSDavid du Colombier Enctls, 19*9a747e4fSDavid du Colombier }; 207dd7cddfSDavid du Colombier 213e12c5d1SDavid du Colombier void (*fcalls[])(Fsrpc*) = 223e12c5d1SDavid du Colombier { 23*9a747e4fSDavid du Colombier [Tversion] Xversion, 24*9a747e4fSDavid du Colombier [Tauth] Xauth, 253e12c5d1SDavid du Colombier [Tflush] Xflush, 263e12c5d1SDavid du Colombier [Tattach] Xattach, 273e12c5d1SDavid du Colombier [Twalk] Xwalk, 283e12c5d1SDavid du Colombier [Topen] slave, 293e12c5d1SDavid du Colombier [Tcreate] Xcreate, 303e12c5d1SDavid du Colombier [Tclunk] Xclunk, 313e12c5d1SDavid du Colombier [Tread] slave, 323e12c5d1SDavid du Colombier [Twrite] slave, 333e12c5d1SDavid du Colombier [Tremove] Xremove, 343e12c5d1SDavid du Colombier [Tstat] Xstat, 353e12c5d1SDavid du Colombier [Twstat] Xwstat, 363e12c5d1SDavid du Colombier }; 373e12c5d1SDavid du Colombier 387dd7cddfSDavid du Colombier /* accounting and debugging counters */ 397dd7cddfSDavid du Colombier int filecnt; 407dd7cddfSDavid du Colombier int freecnt; 417dd7cddfSDavid du Colombier int qidcnt; 427dd7cddfSDavid du Colombier int qfreecnt; 437dd7cddfSDavid du Colombier int ncollision; 447dd7cddfSDavid du Colombier 457dd7cddfSDavid du Colombier int netfd; 46*9a747e4fSDavid du Colombier int srvfd = -1; 47*9a747e4fSDavid du Colombier int nonone = 1; 48*9a747e4fSDavid du Colombier char *filterp; 49*9a747e4fSDavid du Colombier char *ealgs = "rc4_256 sha1"; 50*9a747e4fSDavid du Colombier char *aanfilter = "/bin/aan"; 51*9a747e4fSDavid du Colombier int encproto = Encnone; 52*9a747e4fSDavid du Colombier static void mksecret(char *, uchar *); 53*9a747e4fSDavid du Colombier static int localread9pmsg(int, void *, uint, ulong *); 54*9a747e4fSDavid du Colombier static char *anstring = "il!*!0"; 55*9a747e4fSDavid du Colombier int filter(int, char *); 56219b2ee8SDavid du Colombier 57219b2ee8SDavid du Colombier void 58219b2ee8SDavid du Colombier usage(void) 59219b2ee8SDavid du Colombier { 60*9a747e4fSDavid du Colombier fprint(2, "usage: %s [-ads] [-f dbgfile] [-m msize] [-r root] [-S srvfile] [-e 'crypt hash'] [-A announce-string]\n", argv0); 61219b2ee8SDavid du Colombier fatal("usage"); 62219b2ee8SDavid du Colombier } 63219b2ee8SDavid du Colombier 643e12c5d1SDavid du Colombier void 653e12c5d1SDavid du Colombier main(int argc, char **argv) 663e12c5d1SDavid du Colombier { 67*9a747e4fSDavid du Colombier char buf[ERRMAX], ebuf[ERRMAX]; 683e12c5d1SDavid du Colombier Fsrpc *r; 6980ee5cbfSDavid du Colombier int n; 70*9a747e4fSDavid du Colombier char *dbfile, *srv, *file; 71*9a747e4fSDavid du Colombier AuthInfo *ai; 72*9a747e4fSDavid du Colombier ulong initial; 733e12c5d1SDavid du Colombier 743e12c5d1SDavid du Colombier dbfile = "/tmp/exportdb"; 7580ee5cbfSDavid du Colombier srv = nil; 76*9a747e4fSDavid du Colombier srvfd = -1; 773e12c5d1SDavid du Colombier 78*9a747e4fSDavid du Colombier ai = nil; 793e12c5d1SDavid du Colombier ARGBEGIN{ 803e12c5d1SDavid du Colombier case 'a': 81*9a747e4fSDavid du Colombier /* 82*9a747e4fSDavid du Colombier * We use p9any so we don't have to visit this code again, with the 83*9a747e4fSDavid du Colombier * cost that this code is incompatible with the old world, which 84*9a747e4fSDavid du Colombier * requires p9sk2. (The two differ in who talks first, so compatibility 85*9a747e4fSDavid du Colombier * is awkward.) 86*9a747e4fSDavid du Colombier */ 87*9a747e4fSDavid du Colombier ai = auth_proxy(0, auth_getkey, "proto=p9any role=server"); 88*9a747e4fSDavid du Colombier if(ai == nil) 89*9a747e4fSDavid du Colombier fatal("auth_proxy: %r"); 90*9a747e4fSDavid du Colombier if(nonone && strcmp(ai->cuid, "none") == 0) 91*9a747e4fSDavid du Colombier fatal("exportfs by none disallowed"); 92*9a747e4fSDavid du Colombier if(auth_chuid(ai, nil) < 0) 93*9a747e4fSDavid du Colombier fatal("auth_chuid: %r"); 94*9a747e4fSDavid du Colombier if(newns(ai->cuid, 0) < 0) 95219b2ee8SDavid du Colombier fatal("newns"); 963e12c5d1SDavid du Colombier putenv("service", "exportfs"); 973e12c5d1SDavid du Colombier break; 983e12c5d1SDavid du Colombier 99*9a747e4fSDavid du Colombier case 'e': 100*9a747e4fSDavid du Colombier ealgs = ARGF(); 101*9a747e4fSDavid du Colombier if(ealgs == nil) 102*9a747e4fSDavid du Colombier usage(); 103*9a747e4fSDavid du Colombier if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) 104*9a747e4fSDavid du Colombier ealgs = nil; 105*9a747e4fSDavid du Colombier break; 106*9a747e4fSDavid du Colombier 107*9a747e4fSDavid du Colombier case 'S': 108*9a747e4fSDavid du Colombier if(srvfd != -1) 109*9a747e4fSDavid du Colombier usage(); 110*9a747e4fSDavid du Colombier file = EARGF(usage()); 111*9a747e4fSDavid du Colombier if((srvfd = open(file, ORDWR)) < 0) 112*9a747e4fSDavid du Colombier sysfatal("open '%s': %r", file); 113*9a747e4fSDavid du Colombier break; 114*9a747e4fSDavid du Colombier 1153e12c5d1SDavid du Colombier case 'd': 1163e12c5d1SDavid du Colombier dbg++; 1173e12c5d1SDavid du Colombier break; 1183e12c5d1SDavid du Colombier 1193e12c5d1SDavid du Colombier case 'f': 12080ee5cbfSDavid du Colombier dbfile = EARGF(usage()); 1213e12c5d1SDavid du Colombier break; 1223e12c5d1SDavid du Colombier 1237dd7cddfSDavid du Colombier case 'F': 124*9a747e4fSDavid du Colombier /* accepted but ignored, for backwards compatibility */ 125*9a747e4fSDavid du Colombier break; 126*9a747e4fSDavid du Colombier 127*9a747e4fSDavid du Colombier case 'm': 128*9a747e4fSDavid du Colombier messagesize = strtoul(EARGF(usage()), nil, 0); 1297dd7cddfSDavid du Colombier break; 1307dd7cddfSDavid du Colombier 13180ee5cbfSDavid du Colombier case 'r': 13280ee5cbfSDavid du Colombier srv = EARGF(usage()); 13380ee5cbfSDavid du Colombier break; 13480ee5cbfSDavid du Colombier 135bd389b36SDavid du Colombier case 's': 13680ee5cbfSDavid du Colombier srv = "/"; 137bd389b36SDavid du Colombier break; 138219b2ee8SDavid du Colombier 139*9a747e4fSDavid du Colombier case 'A': 140*9a747e4fSDavid du Colombier anstring = EARGF(usage()); 141*9a747e4fSDavid du Colombier break; 142*9a747e4fSDavid du Colombier 143219b2ee8SDavid du Colombier default: 144219b2ee8SDavid du Colombier usage(); 1453e12c5d1SDavid du Colombier }ARGEND 1463e12c5d1SDavid du Colombier USED(argc, argv); 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier if(dbg) { 1493e12c5d1SDavid du Colombier n = create(dbfile, OWRITE|OTRUNC, 0666); 1507dd7cddfSDavid du Colombier dup(n, DFD); 1513e12c5d1SDavid du Colombier close(n); 1523e12c5d1SDavid du Colombier } 1533e12c5d1SDavid du Colombier 154*9a747e4fSDavid du Colombier if(srvfd >= 0 && srv){ 155*9a747e4fSDavid du Colombier fprint(2, "exportfs: -S cannot be used with -r or -s\n"); 156*9a747e4fSDavid du Colombier usage(); 157*9a747e4fSDavid du Colombier } 158*9a747e4fSDavid du Colombier 1597dd7cddfSDavid du Colombier DEBUG(DFD, "exportfs: started\n"); 160219b2ee8SDavid du Colombier 1613e12c5d1SDavid du Colombier rfork(RFNOTEG); 1623e12c5d1SDavid du Colombier 163*9a747e4fSDavid du Colombier if(messagesize == 0){ 164*9a747e4fSDavid du Colombier messagesize = iounit(netfd); 165*9a747e4fSDavid du Colombier if(messagesize == 0) 166*9a747e4fSDavid du Colombier messagesize = 8192+IOHDRSZ; 167*9a747e4fSDavid du Colombier } 1683e12c5d1SDavid du Colombier 169*9a747e4fSDavid du Colombier Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); 170*9a747e4fSDavid du Colombier // for(i=0; i<Nr_workbufs; i++) 171*9a747e4fSDavid du Colombier // Workq[i].buf = emallocz(messagesize); 172*9a747e4fSDavid du Colombier fhash = emallocz(sizeof(Fid*)*FHASHSIZE); 1733e12c5d1SDavid du Colombier 174*9a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 1753e12c5d1SDavid du Colombier 1763e12c5d1SDavid du Colombier /* 177219b2ee8SDavid du Colombier * Get tree to serve from network connection, 178219b2ee8SDavid du Colombier * check we can get there and ack the connection 1793e12c5d1SDavid du Colombier */ 180*9a747e4fSDavid du Colombier if(srvfd != -1) { 181*9a747e4fSDavid du Colombier /* do nothing */ 182*9a747e4fSDavid du Colombier } 183*9a747e4fSDavid du Colombier else if(srv) { 18480ee5cbfSDavid du Colombier chdir(srv); 18580ee5cbfSDavid du Colombier DEBUG(DFD, "invoked as server for %s", srv); 186*9a747e4fSDavid du Colombier strncpy(buf, srv, sizeof buf); 187219b2ee8SDavid du Colombier } 188bd389b36SDavid du Colombier else { 189bd389b36SDavid du Colombier buf[0] = 0; 190*9a747e4fSDavid du Colombier n = read(0, buf, sizeof(buf)-1); 191bd389b36SDavid du Colombier if(n < 0) { 192*9a747e4fSDavid du Colombier errstr(buf, sizeof buf); 193bd389b36SDavid du Colombier fprint(0, "read(0): %s", buf); 1947dd7cddfSDavid du Colombier DEBUG(DFD, "read(0): %s", buf); 1953e12c5d1SDavid du Colombier exits(buf); 1963e12c5d1SDavid du Colombier } 197219b2ee8SDavid du Colombier buf[n] = 0; 198bd389b36SDavid du Colombier if(chdir(buf) < 0) { 199*9a747e4fSDavid du Colombier errstr(ebuf, sizeof ebuf); 200bd389b36SDavid du Colombier fprint(0, "chdir(%d:\"%s\"): %s", n, buf, ebuf); 2017dd7cddfSDavid du Colombier DEBUG(DFD, "chdir(%d:\"%s\"): %s", n, buf, ebuf); 202bd389b36SDavid du Colombier exits(ebuf); 203bd389b36SDavid du Colombier } 204bd389b36SDavid du Colombier } 2053e12c5d1SDavid du Colombier 2067dd7cddfSDavid du Colombier DEBUG(DFD, "initing root\n"); 2073e12c5d1SDavid du Colombier initroot(); 2083e12c5d1SDavid du Colombier 2097dd7cddfSDavid du Colombier DEBUG(DFD, "exportfs: %s\n", buf); 2103e12c5d1SDavid du Colombier 211*9a747e4fSDavid du Colombier if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2) 2123e12c5d1SDavid du Colombier fatal("open ack write"); 2133e12c5d1SDavid du Colombier 214*9a747e4fSDavid du Colombier if ((n = readn(netfd, &initial, sizeof(ulong))) < 0) 215*9a747e4fSDavid du Colombier fatal("can't read initial string: %r\n"); 216*9a747e4fSDavid du Colombier assert(n == sizeof(ulong)); 217*9a747e4fSDavid du Colombier 218*9a747e4fSDavid du Colombier if (!strncmp((char *)&initial, "impo", sizeof(ulong))) { 219*9a747e4fSDavid du Colombier char buf[128], *p, *args[3]; 220*9a747e4fSDavid du Colombier 221*9a747e4fSDavid du Colombier // New import. Read import's parameters... 222*9a747e4fSDavid du Colombier initial = 0; 223*9a747e4fSDavid du Colombier 224*9a747e4fSDavid du Colombier p = buf; 225*9a747e4fSDavid du Colombier while (p - buf < sizeof buf) { 226*9a747e4fSDavid du Colombier if ((n = read(netfd, p, 1)) < 0) 227*9a747e4fSDavid du Colombier fatal("can't read impo arguments: %r\n"); 228*9a747e4fSDavid du Colombier 229*9a747e4fSDavid du Colombier if (n == 0) 230*9a747e4fSDavid du Colombier fatal("connection closed while reading arguments\n"); 231*9a747e4fSDavid du Colombier 232*9a747e4fSDavid du Colombier if (*p == '\n') 233*9a747e4fSDavid du Colombier *p = '\0'; 234*9a747e4fSDavid du Colombier if (*p++ == '\0') 235*9a747e4fSDavid du Colombier break; 236*9a747e4fSDavid du Colombier } 237*9a747e4fSDavid du Colombier 238*9a747e4fSDavid du Colombier if (tokenize(buf, args, nelem(args)) != 2) 239*9a747e4fSDavid du Colombier fatal("impo arguments invalid: impo%s...\n", buf); 240*9a747e4fSDavid du Colombier 241*9a747e4fSDavid du Colombier if (!strcmp(args[0], "aan")) 242*9a747e4fSDavid du Colombier filterp = aanfilter; 243*9a747e4fSDavid du Colombier else if (strcmp(args[0], "nofilter")) 244*9a747e4fSDavid du Colombier fatal("import filter argument unsupported: %s\n", args[0]); 245*9a747e4fSDavid du Colombier 246*9a747e4fSDavid du Colombier if (!strcmp(args[1], "ssl")) 247*9a747e4fSDavid du Colombier encproto = Encssl; 248*9a747e4fSDavid du Colombier else if (!strcmp(args[1], "tls")) 249*9a747e4fSDavid du Colombier encproto = Enctls; 250*9a747e4fSDavid du Colombier else if (strcmp(args[1], "clear")) 251*9a747e4fSDavid du Colombier fatal("import encryption proto unsupported: %s\n", args[1]); 252*9a747e4fSDavid du Colombier 253*9a747e4fSDavid du Colombier if (encproto == Enctls) 254*9a747e4fSDavid du Colombier sysfatal("%s: tls has not yet been implemented\n", argv[0]); 255*9a747e4fSDavid du Colombier } 256*9a747e4fSDavid du Colombier 257*9a747e4fSDavid du Colombier if (encproto != Encnone && ealgs && ai) { 258*9a747e4fSDavid du Colombier uchar key[16]; 259*9a747e4fSDavid du Colombier uchar digest[SHA1dlen]; 260*9a747e4fSDavid du Colombier char fromclientsecret[21]; 261*9a747e4fSDavid du Colombier char fromserversecret[21]; 262*9a747e4fSDavid du Colombier int i; 263*9a747e4fSDavid du Colombier 264*9a747e4fSDavid du Colombier memmove(key+4, ai->secret, ai->nsecret); 265*9a747e4fSDavid du Colombier 266*9a747e4fSDavid du Colombier /* exchange random numbers */ 267*9a747e4fSDavid du Colombier srand(truerand()); 268*9a747e4fSDavid du Colombier for(i = 0; i < 4; i++) 269*9a747e4fSDavid du Colombier key[i+12] = rand(); 270*9a747e4fSDavid du Colombier 271*9a747e4fSDavid du Colombier if (initial) 272*9a747e4fSDavid du Colombier fatal("Protocol botch: old import\n"); 273*9a747e4fSDavid du Colombier if(readn(netfd, key, 4) != 4) 274*9a747e4fSDavid du Colombier fatal("can't read key part; %r\n"); 275*9a747e4fSDavid du Colombier 276*9a747e4fSDavid du Colombier if(write(netfd, key+12, 4) != 4) 277*9a747e4fSDavid du Colombier fatal("can't write key part; %r\n"); 278*9a747e4fSDavid du Colombier 279*9a747e4fSDavid du Colombier /* scramble into two secrets */ 280*9a747e4fSDavid du Colombier sha1(key, sizeof(key), digest, nil); 281*9a747e4fSDavid du Colombier mksecret(fromclientsecret, digest); 282*9a747e4fSDavid du Colombier mksecret(fromserversecret, digest+10); 283*9a747e4fSDavid du Colombier 284*9a747e4fSDavid du Colombier if (filterp) 285*9a747e4fSDavid du Colombier netfd = filter(netfd, filterp); 286*9a747e4fSDavid du Colombier 287*9a747e4fSDavid du Colombier switch (encproto) { 288*9a747e4fSDavid du Colombier case Encssl: 289*9a747e4fSDavid du Colombier netfd = pushssl(netfd, ealgs, fromserversecret, 290*9a747e4fSDavid du Colombier fromclientsecret, nil); 291*9a747e4fSDavid du Colombier break; 292*9a747e4fSDavid du Colombier case Enctls: 293*9a747e4fSDavid du Colombier default: 294*9a747e4fSDavid du Colombier fatal("Unsupported encryption protocol\n"); 295*9a747e4fSDavid du Colombier } 296*9a747e4fSDavid du Colombier 297*9a747e4fSDavid du Colombier if(netfd < 0) 298*9a747e4fSDavid du Colombier fatal("can't establish ssl connection: %r"); 299*9a747e4fSDavid du Colombier } 300*9a747e4fSDavid du Colombier else if (filterp) { 301*9a747e4fSDavid du Colombier if (initial) 302*9a747e4fSDavid du Colombier fatal("Protocol botch: don't know how to deal with this\n"); 303*9a747e4fSDavid du Colombier netfd = filter(netfd, filterp); 304*9a747e4fSDavid du Colombier } 3057dd7cddfSDavid du Colombier 3067dd7cddfSDavid du Colombier /* 3073e12c5d1SDavid du Colombier * Start serving file requests from the network 3083e12c5d1SDavid du Colombier */ 3093e12c5d1SDavid du Colombier for(;;) { 3103e12c5d1SDavid du Colombier r = getsbuf(); 3113e12c5d1SDavid du Colombier if(r == 0) 3123e12c5d1SDavid du Colombier fatal("Out of service buffers"); 3133e12c5d1SDavid du Colombier 314*9a747e4fSDavid du Colombier n = localread9pmsg(netfd, r->buf, messagesize, &initial); 315*9a747e4fSDavid du Colombier if(n <= 0) 316*9a747e4fSDavid du Colombier fatal(nil); 3173e12c5d1SDavid du Colombier 318*9a747e4fSDavid du Colombier if(convM2S(r->buf, n, &r->work) == 0) 319*9a747e4fSDavid du Colombier fatal("convM2S format error"); 3203e12c5d1SDavid du Colombier 3217dd7cddfSDavid du Colombier DEBUG(DFD, "%F\n", &r->work); 3223e12c5d1SDavid du Colombier (fcalls[r->work.type])(r); 3233e12c5d1SDavid du Colombier } 3243e12c5d1SDavid du Colombier } 3253e12c5d1SDavid du Colombier 326*9a747e4fSDavid du Colombier // WARNING: Replace this with the original version as soon as all 327*9a747e4fSDavid du Colombier // _old_ imports have been replaced with negotiating imports. Also 328*9a747e4fSDavid du Colombier // cpu relies on this (which needs to be fixed!) -- pb. 329*9a747e4fSDavid du Colombier static int 330*9a747e4fSDavid du Colombier localread9pmsg(int fd, void *abuf, uint n, ulong *initial) 331*9a747e4fSDavid du Colombier { 332*9a747e4fSDavid du Colombier int m, len; 333*9a747e4fSDavid du Colombier uchar *buf; 334*9a747e4fSDavid du Colombier 335*9a747e4fSDavid du Colombier buf = abuf; 336*9a747e4fSDavid du Colombier 337*9a747e4fSDavid du Colombier /* read count */ 338*9a747e4fSDavid du Colombier assert(BIT32SZ == sizeof(ulong)); 339*9a747e4fSDavid du Colombier if (*initial) { 340*9a747e4fSDavid du Colombier memcpy(buf, initial, BIT32SZ); 341*9a747e4fSDavid du Colombier *initial = 0; 342*9a747e4fSDavid du Colombier } 343*9a747e4fSDavid du Colombier else { 344*9a747e4fSDavid du Colombier m = readn(fd, buf, BIT32SZ); 345*9a747e4fSDavid du Colombier if(m != BIT32SZ){ 346*9a747e4fSDavid du Colombier if(m < 0) 347*9a747e4fSDavid du Colombier return -1; 348*9a747e4fSDavid du Colombier return 0; 349*9a747e4fSDavid du Colombier } 350*9a747e4fSDavid du Colombier } 351*9a747e4fSDavid du Colombier 352*9a747e4fSDavid du Colombier len = GBIT32(buf); 353*9a747e4fSDavid du Colombier if(len <= BIT32SZ || len > n){ 354*9a747e4fSDavid du Colombier werrstr("bad length in 9P2000 message header"); 355*9a747e4fSDavid du Colombier return -1; 356*9a747e4fSDavid du Colombier } 357*9a747e4fSDavid du Colombier len -= BIT32SZ; 358*9a747e4fSDavid du Colombier m = readn(fd, buf+BIT32SZ, len); 359*9a747e4fSDavid du Colombier if(m < len) 360*9a747e4fSDavid du Colombier return 0; 361*9a747e4fSDavid du Colombier return BIT32SZ+m; 362*9a747e4fSDavid du Colombier } 3633e12c5d1SDavid du Colombier void 3643e12c5d1SDavid du Colombier reply(Fcall *r, Fcall *t, char *err) 3653e12c5d1SDavid du Colombier { 366*9a747e4fSDavid du Colombier uchar *data; 3673e12c5d1SDavid du Colombier int n; 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier t->tag = r->tag; 3703e12c5d1SDavid du Colombier t->fid = r->fid; 3713e12c5d1SDavid du Colombier if(err) { 3723e12c5d1SDavid du Colombier t->type = Rerror; 373*9a747e4fSDavid du Colombier t->ename = err; 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier else 3763e12c5d1SDavid du Colombier t->type = r->type + 1; 3773e12c5d1SDavid du Colombier 3787dd7cddfSDavid du Colombier DEBUG(DFD, "\t%F\n", t); 3793e12c5d1SDavid du Colombier 380*9a747e4fSDavid du Colombier data = malloc(messagesize); /* not mallocz; no need to clear */ 381*9a747e4fSDavid du Colombier if(data == nil) 382*9a747e4fSDavid du Colombier fatal(Enomem); 383*9a747e4fSDavid du Colombier n = convS2M(t, data, messagesize); 384*9a747e4fSDavid du Colombier if(write(netfd, data, n)!=n) 385*9a747e4fSDavid du Colombier {syslog(0, "exportfs", "short write: %r"); 3863e12c5d1SDavid du Colombier fatal("mount write"); 3873e12c5d1SDavid du Colombier } 388*9a747e4fSDavid du Colombier free(data); 389*9a747e4fSDavid du Colombier } 3903e12c5d1SDavid du Colombier 3913e12c5d1SDavid du Colombier Fid * 3923e12c5d1SDavid du Colombier getfid(int nr) 3933e12c5d1SDavid du Colombier { 3943e12c5d1SDavid du Colombier Fid *f; 3953e12c5d1SDavid du Colombier 3963e12c5d1SDavid du Colombier for(f = fidhash(nr); f; f = f->next) 3973e12c5d1SDavid du Colombier if(f->nr == nr) 3983e12c5d1SDavid du Colombier return f; 3993e12c5d1SDavid du Colombier 4003e12c5d1SDavid du Colombier return 0; 4013e12c5d1SDavid du Colombier } 4023e12c5d1SDavid du Colombier 4033e12c5d1SDavid du Colombier int 4043e12c5d1SDavid du Colombier freefid(int nr) 4053e12c5d1SDavid du Colombier { 4063e12c5d1SDavid du Colombier Fid *f, **l; 407219b2ee8SDavid du Colombier char buf[128]; 4083e12c5d1SDavid du Colombier 4093e12c5d1SDavid du Colombier l = &fidhash(nr); 4103e12c5d1SDavid du Colombier for(f = *l; f; f = f->next) { 4113e12c5d1SDavid du Colombier if(f->nr == nr) { 412219b2ee8SDavid du Colombier if(f->mid) { 413219b2ee8SDavid du Colombier sprint(buf, "/mnt/exportfs/%d", f->mid); 414219b2ee8SDavid du Colombier unmount(0, buf); 415219b2ee8SDavid du Colombier psmap[f->mid] = 0; 416219b2ee8SDavid du Colombier } 417*9a747e4fSDavid du Colombier if(f->f) { 4187dd7cddfSDavid du Colombier freefile(f->f); 4197dd7cddfSDavid du Colombier f->f = nil; 420*9a747e4fSDavid du Colombier } 4213e12c5d1SDavid du Colombier *l = f->next; 4223e12c5d1SDavid du Colombier f->next = fidfree; 4233e12c5d1SDavid du Colombier fidfree = f; 4243e12c5d1SDavid du Colombier return 1; 4253e12c5d1SDavid du Colombier } 4263e12c5d1SDavid du Colombier l = &f->next; 4273e12c5d1SDavid du Colombier } 4283e12c5d1SDavid du Colombier 4293e12c5d1SDavid du Colombier return 0; 4303e12c5d1SDavid du Colombier } 4313e12c5d1SDavid du Colombier 4323e12c5d1SDavid du Colombier Fid * 4333e12c5d1SDavid du Colombier newfid(int nr) 4343e12c5d1SDavid du Colombier { 4353e12c5d1SDavid du Colombier Fid *new, **l; 4363e12c5d1SDavid du Colombier int i; 4373e12c5d1SDavid du Colombier 4383e12c5d1SDavid du Colombier l = &fidhash(nr); 4393e12c5d1SDavid du Colombier for(new = *l; new; new = new->next) 4403e12c5d1SDavid du Colombier if(new->nr == nr) 4413e12c5d1SDavid du Colombier return 0; 4423e12c5d1SDavid du Colombier 4433e12c5d1SDavid du Colombier if(fidfree == 0) { 444*9a747e4fSDavid du Colombier fidfree = emallocz(sizeof(Fid) * Fidchunk); 4453e12c5d1SDavid du Colombier 4463e12c5d1SDavid du Colombier for(i = 0; i < Fidchunk-1; i++) 4473e12c5d1SDavid du Colombier fidfree[i].next = &fidfree[i+1]; 4483e12c5d1SDavid du Colombier 4493e12c5d1SDavid du Colombier fidfree[Fidchunk-1].next = 0; 4503e12c5d1SDavid du Colombier } 4513e12c5d1SDavid du Colombier 4523e12c5d1SDavid du Colombier new = fidfree; 4533e12c5d1SDavid du Colombier fidfree = new->next; 4543e12c5d1SDavid du Colombier 4553e12c5d1SDavid du Colombier memset(new, 0, sizeof(Fid)); 4563e12c5d1SDavid du Colombier new->next = *l; 4573e12c5d1SDavid du Colombier *l = new; 4583e12c5d1SDavid du Colombier new->nr = nr; 4593e12c5d1SDavid du Colombier new->fid = -1; 460219b2ee8SDavid du Colombier new->mid = 0; 4613e12c5d1SDavid du Colombier 4623e12c5d1SDavid du Colombier return new; 4633e12c5d1SDavid du Colombier } 4643e12c5d1SDavid du Colombier 4653e12c5d1SDavid du Colombier Fsrpc * 4663e12c5d1SDavid du Colombier getsbuf(void) 4673e12c5d1SDavid du Colombier { 4683e12c5d1SDavid du Colombier static int ap; 4697dd7cddfSDavid du Colombier int look, rounds; 4703e12c5d1SDavid du Colombier Fsrpc *wb; 471*9a747e4fSDavid du Colombier int small_instead_of_fast = 1; 472*9a747e4fSDavid du Colombier 473*9a747e4fSDavid du Colombier if(small_instead_of_fast) 474*9a747e4fSDavid du Colombier ap = 0; /* so we always start looking at the beginning and reuse buffers */ 4753e12c5d1SDavid du Colombier 4767dd7cddfSDavid du Colombier for(rounds = 0; rounds < 10; rounds++) { 4773e12c5d1SDavid du Colombier for(look = 0; look < Nr_workbufs; look++) { 4783e12c5d1SDavid du Colombier if(++ap == Nr_workbufs) 4793e12c5d1SDavid du Colombier ap = 0; 4803e12c5d1SDavid du Colombier if(Workq[ap].busy == 0) 4813e12c5d1SDavid du Colombier break; 4823e12c5d1SDavid du Colombier } 4833e12c5d1SDavid du Colombier 4847dd7cddfSDavid du Colombier if(look == Nr_workbufs){ 4857dd7cddfSDavid du Colombier sleep(10 * rounds); 4867dd7cddfSDavid du Colombier continue; 4877dd7cddfSDavid du Colombier } 4883e12c5d1SDavid du Colombier 4893e12c5d1SDavid du Colombier wb = &Workq[ap]; 4903e12c5d1SDavid du Colombier wb->pid = 0; 4913e12c5d1SDavid du Colombier wb->canint = 0; 4923e12c5d1SDavid du Colombier wb->flushtag = NOTAG; 4933e12c5d1SDavid du Colombier wb->busy = 1; 494*9a747e4fSDavid du Colombier if(wb->buf == nil) /* allocate buffers dynamically to keep size down */ 495*9a747e4fSDavid du Colombier wb->buf = emallocz(messagesize); 4963e12c5d1SDavid du Colombier return wb; 4973e12c5d1SDavid du Colombier } 4987dd7cddfSDavid du Colombier fatal("No more work buffers"); 4997dd7cddfSDavid du Colombier return nil; 5007dd7cddfSDavid du Colombier } 5013e12c5d1SDavid du Colombier 5027dd7cddfSDavid du Colombier void 5037dd7cddfSDavid du Colombier freefile(File *f) 5043e12c5d1SDavid du Colombier { 5057dd7cddfSDavid du Colombier File *parent, *child; 5063e12c5d1SDavid du Colombier 5077dd7cddfSDavid du Colombier Loop: 5087dd7cddfSDavid du Colombier f->ref--; 5097dd7cddfSDavid du Colombier if(f->ref > 0) 5107dd7cddfSDavid du Colombier return; 5117dd7cddfSDavid du Colombier freecnt++; 5127dd7cddfSDavid du Colombier if(f->ref < 0) abort(); 5137dd7cddfSDavid du Colombier DEBUG(DFD, "free %s\n", f->name); 5147dd7cddfSDavid du Colombier /* delete from parent */ 5157dd7cddfSDavid du Colombier parent = f->parent; 5167dd7cddfSDavid du Colombier if(parent->child == f) 5177dd7cddfSDavid du Colombier parent->child = f->childlist; 5187dd7cddfSDavid du Colombier else{ 5197dd7cddfSDavid du Colombier for(child=parent->child; child->childlist!=f; child=child->childlist) 5207dd7cddfSDavid du Colombier if(child->childlist == nil) 5217dd7cddfSDavid du Colombier fatal("bad child list"); 5227dd7cddfSDavid du Colombier child->childlist = f->childlist; 5237dd7cddfSDavid du Colombier } 5247dd7cddfSDavid du Colombier freeqid(f->qidt); 525*9a747e4fSDavid du Colombier free(f->name); 526*9a747e4fSDavid du Colombier f->name = nil; 5277dd7cddfSDavid du Colombier free(f); 5287dd7cddfSDavid du Colombier f = parent; 5297dd7cddfSDavid du Colombier if(f != nil) 5307dd7cddfSDavid du Colombier goto Loop; 5313e12c5d1SDavid du Colombier } 5323e12c5d1SDavid du Colombier 5333e12c5d1SDavid du Colombier File * 5343e12c5d1SDavid du Colombier file(File *parent, char *name) 5353e12c5d1SDavid du Colombier { 536*9a747e4fSDavid du Colombier Dir *dir; 537*9a747e4fSDavid du Colombier char *path; 5387dd7cddfSDavid du Colombier File *f; 5393e12c5d1SDavid du Colombier 5407dd7cddfSDavid du Colombier DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); 5413e12c5d1SDavid du Colombier 542*9a747e4fSDavid du Colombier path = makepath(parent, name); 543*9a747e4fSDavid du Colombier dir = dirstat(path); 544*9a747e4fSDavid du Colombier free(path); 545*9a747e4fSDavid du Colombier if(dir == nil) 5467dd7cddfSDavid du Colombier return nil; 5473e12c5d1SDavid du Colombier 5487dd7cddfSDavid du Colombier for(f = parent->child; f; f = f->childlist) 5497dd7cddfSDavid du Colombier if(strcmp(name, f->name) == 0) 5507dd7cddfSDavid du Colombier break; 5517dd7cddfSDavid du Colombier 5527dd7cddfSDavid du Colombier if(f == nil){ 553*9a747e4fSDavid du Colombier f = emallocz(sizeof(File)); 554*9a747e4fSDavid du Colombier f->name = estrdup(name); 5553e12c5d1SDavid du Colombier 5567dd7cddfSDavid du Colombier f->parent = parent; 5577dd7cddfSDavid du Colombier f->childlist = parent->child; 5587dd7cddfSDavid du Colombier parent->child = f; 5597dd7cddfSDavid du Colombier parent->ref++; 5607dd7cddfSDavid du Colombier f->ref = 0; 5617dd7cddfSDavid du Colombier filecnt++; 5627dd7cddfSDavid du Colombier } 5637dd7cddfSDavid du Colombier f->ref++; 564*9a747e4fSDavid du Colombier f->qid.type = dir->qid.type; 565*9a747e4fSDavid du Colombier f->qid.vers = dir->qid.vers; 566*9a747e4fSDavid du Colombier f->qidt = uniqueqid(dir); 5677dd7cddfSDavid du Colombier f->qid.path = f->qidt->uniqpath; 5683e12c5d1SDavid du Colombier 5697dd7cddfSDavid du Colombier f->inval = 0; 5703e12c5d1SDavid du Colombier 571*9a747e4fSDavid du Colombier free(dir); 5727dd7cddfSDavid du Colombier 5737dd7cddfSDavid du Colombier return f; 5743e12c5d1SDavid du Colombier } 5753e12c5d1SDavid du Colombier 5763e12c5d1SDavid du Colombier void 5773e12c5d1SDavid du Colombier initroot(void) 5783e12c5d1SDavid du Colombier { 579*9a747e4fSDavid du Colombier Dir *dir; 5803e12c5d1SDavid du Colombier 581*9a747e4fSDavid du Colombier root = emallocz(sizeof(File)); 582*9a747e4fSDavid du Colombier root->name = estrdup("."); 5833e12c5d1SDavid du Colombier 584*9a747e4fSDavid du Colombier dir = dirstat(root->name); 585*9a747e4fSDavid du Colombier if(dir == nil) 5863e12c5d1SDavid du Colombier fatal("root stat"); 5873e12c5d1SDavid du Colombier 5887dd7cddfSDavid du Colombier root->ref = 1; 589*9a747e4fSDavid du Colombier root->qid.vers = dir->qid.vers; 590*9a747e4fSDavid du Colombier root->qidt = uniqueqid(dir); 5917dd7cddfSDavid du Colombier root->qid.path = root->qidt->uniqpath; 592*9a747e4fSDavid du Colombier root->qid.type = QTDIR; 593*9a747e4fSDavid du Colombier free(dir); 594219b2ee8SDavid du Colombier 595*9a747e4fSDavid du Colombier psmpt = emallocz(sizeof(File)); 596*9a747e4fSDavid du Colombier psmpt->name = estrdup("/"); 597219b2ee8SDavid du Colombier 598*9a747e4fSDavid du Colombier dir = dirstat(psmpt->name); 599*9a747e4fSDavid du Colombier if(dir == nil) 600219b2ee8SDavid du Colombier return; 601219b2ee8SDavid du Colombier 6027dd7cddfSDavid du Colombier psmpt->ref = 1; 603*9a747e4fSDavid du Colombier psmpt->qid.vers = dir->qid.vers; 604*9a747e4fSDavid du Colombier psmpt->qidt = uniqueqid(dir); 6057dd7cddfSDavid du Colombier psmpt->qid.path = psmpt->qidt->uniqpath; 606*9a747e4fSDavid du Colombier free(dir); 607219b2ee8SDavid du Colombier 608219b2ee8SDavid du Colombier psmpt = file(psmpt, "mnt"); 609219b2ee8SDavid du Colombier if(psmpt == 0) 610219b2ee8SDavid du Colombier return; 611219b2ee8SDavid du Colombier psmpt = file(psmpt, "exportfs"); 6123e12c5d1SDavid du Colombier } 6133e12c5d1SDavid du Colombier 614*9a747e4fSDavid du Colombier char* 615*9a747e4fSDavid du Colombier makepath(File *p, char *name) 6163e12c5d1SDavid du Colombier { 617*9a747e4fSDavid du Colombier int i, n; 618*9a747e4fSDavid du Colombier char *c, *s, *path, *seg[256]; 6193e12c5d1SDavid du Colombier 6203e12c5d1SDavid du Colombier seg[0] = name; 621*9a747e4fSDavid du Colombier n = strlen(name)+2; 622*9a747e4fSDavid du Colombier for(i = 1; i < 256 && p; i++, p = p->parent){ 6233e12c5d1SDavid du Colombier seg[i] = p->name; 624*9a747e4fSDavid du Colombier n += strlen(p->name)+1; 625*9a747e4fSDavid du Colombier } 626*9a747e4fSDavid du Colombier path = malloc(n); 627*9a747e4fSDavid du Colombier if(path == nil) 628*9a747e4fSDavid du Colombier fatal("out of memory"); 629*9a747e4fSDavid du Colombier s = path; 6303e12c5d1SDavid du Colombier 6313e12c5d1SDavid du Colombier while(i--) { 6323e12c5d1SDavid du Colombier for(c = seg[i]; *c; c++) 6333e12c5d1SDavid du Colombier *s++ = *c; 6343e12c5d1SDavid du Colombier *s++ = '/'; 6353e12c5d1SDavid du Colombier } 6363e12c5d1SDavid du Colombier while(s[-1] == '/') 6373e12c5d1SDavid du Colombier s--; 6383e12c5d1SDavid du Colombier *s = '\0'; 639*9a747e4fSDavid du Colombier 640*9a747e4fSDavid du Colombier return path; 6413e12c5d1SDavid du Colombier } 6423e12c5d1SDavid du Colombier 6437dd7cddfSDavid du Colombier int 644*9a747e4fSDavid du Colombier qidhash(vlong path) 6457dd7cddfSDavid du Colombier { 6467dd7cddfSDavid du Colombier int h, n; 6477dd7cddfSDavid du Colombier 6487dd7cddfSDavid du Colombier h = 0; 649*9a747e4fSDavid du Colombier for(n=0; n<64; n+=Nqidbits){ 6507dd7cddfSDavid du Colombier h ^= path; 6517dd7cddfSDavid du Colombier path >>= Nqidbits; 6527dd7cddfSDavid du Colombier } 6537dd7cddfSDavid du Colombier return h & (Nqidtab-1); 6547dd7cddfSDavid du Colombier } 6557dd7cddfSDavid du Colombier 6567dd7cddfSDavid du Colombier void 6577dd7cddfSDavid du Colombier freeqid(Qidtab *q) 6587dd7cddfSDavid du Colombier { 6597dd7cddfSDavid du Colombier ulong h; 6607dd7cddfSDavid du Colombier Qidtab *l; 6617dd7cddfSDavid du Colombier 6627dd7cddfSDavid du Colombier q->ref--; 6637dd7cddfSDavid du Colombier if(q->ref > 0) 6647dd7cddfSDavid du Colombier return; 6657dd7cddfSDavid du Colombier qfreecnt++; 6667dd7cddfSDavid du Colombier h = qidhash(q->path); 6677dd7cddfSDavid du Colombier if(qidtab[h] == q) 6687dd7cddfSDavid du Colombier qidtab[h] = q->next; 6697dd7cddfSDavid du Colombier else{ 6707dd7cddfSDavid du Colombier for(l=qidtab[h]; l->next!=q; l=l->next) 6717dd7cddfSDavid du Colombier if(l->next == nil) 6727dd7cddfSDavid du Colombier fatal("bad qid list"); 6737dd7cddfSDavid du Colombier l->next = q->next; 6747dd7cddfSDavid du Colombier } 6757dd7cddfSDavid du Colombier free(q); 6767dd7cddfSDavid du Colombier } 6777dd7cddfSDavid du Colombier 6787dd7cddfSDavid du Colombier Qidtab* 6797dd7cddfSDavid du Colombier qidlookup(Dir *d) 6807dd7cddfSDavid du Colombier { 6817dd7cddfSDavid du Colombier ulong h; 6827dd7cddfSDavid du Colombier Qidtab *q; 6837dd7cddfSDavid du Colombier 6847dd7cddfSDavid du Colombier h = qidhash(d->qid.path); 6857dd7cddfSDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next) 6867dd7cddfSDavid du Colombier if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) 6877dd7cddfSDavid du Colombier return q; 6887dd7cddfSDavid du Colombier return nil; 6897dd7cddfSDavid du Colombier } 6907dd7cddfSDavid du Colombier 6917dd7cddfSDavid du Colombier int 692*9a747e4fSDavid du Colombier qidexists(vlong path) 6937dd7cddfSDavid du Colombier { 6947dd7cddfSDavid du Colombier int h; 6957dd7cddfSDavid du Colombier Qidtab *q; 6967dd7cddfSDavid du Colombier 6977dd7cddfSDavid du Colombier for(h=0; h<Nqidtab; h++) 6987dd7cddfSDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next) 6997dd7cddfSDavid du Colombier if(q->uniqpath == path) 7007dd7cddfSDavid du Colombier return 1; 7017dd7cddfSDavid du Colombier return 0; 7027dd7cddfSDavid du Colombier } 7037dd7cddfSDavid du Colombier 7047dd7cddfSDavid du Colombier Qidtab* 7057dd7cddfSDavid du Colombier uniqueqid(Dir *d) 7067dd7cddfSDavid du Colombier { 707*9a747e4fSDavid du Colombier ulong h; 708*9a747e4fSDavid du Colombier vlong path; 7097dd7cddfSDavid du Colombier Qidtab *q; 7107dd7cddfSDavid du Colombier 7117dd7cddfSDavid du Colombier q = qidlookup(d); 7127dd7cddfSDavid du Colombier if(q != nil){ 7137dd7cddfSDavid du Colombier q->ref++; 7147dd7cddfSDavid du Colombier return q; 7157dd7cddfSDavid du Colombier } 7167dd7cddfSDavid du Colombier path = d->qid.path; 7177dd7cddfSDavid du Colombier while(qidexists(path)){ 718*9a747e4fSDavid du Colombier DEBUG(DFD, "collision on %s\n", d->name); 7197dd7cddfSDavid du Colombier /* collision: find a new one */ 7207dd7cddfSDavid du Colombier ncollision++; 721*9a747e4fSDavid du Colombier path &= QIDPATH; 722*9a747e4fSDavid du Colombier ++newqid; 723*9a747e4fSDavid du Colombier if(newqid >= (1<<16)){ 724*9a747e4fSDavid du Colombier DEBUG(DFD, "collision wraparound\n"); 725*9a747e4fSDavid du Colombier newqid = 1; 726*9a747e4fSDavid du Colombier } 727*9a747e4fSDavid du Colombier path |= newqid<<48; 728*9a747e4fSDavid du Colombier DEBUG(DFD, "assign qid %.16llux\n", path); 7297dd7cddfSDavid du Colombier } 7307dd7cddfSDavid du Colombier q = mallocz(sizeof(Qidtab), 1); 7317dd7cddfSDavid du Colombier if(q == nil) 7327dd7cddfSDavid du Colombier fatal("no memory for qid table"); 7337dd7cddfSDavid du Colombier qidcnt++; 7347dd7cddfSDavid du Colombier q->ref = 1; 7357dd7cddfSDavid du Colombier q->type = d->type; 7367dd7cddfSDavid du Colombier q->dev = d->dev; 7377dd7cddfSDavid du Colombier q->path = d->qid.path; 7387dd7cddfSDavid du Colombier q->uniqpath = path; 7397dd7cddfSDavid du Colombier h = qidhash(d->qid.path); 7407dd7cddfSDavid du Colombier q->next = qidtab[h]; 7417dd7cddfSDavid du Colombier qidtab[h] = q; 7427dd7cddfSDavid du Colombier return q; 7437dd7cddfSDavid du Colombier } 7447dd7cddfSDavid du Colombier 7453e12c5d1SDavid du Colombier void 746*9a747e4fSDavid du Colombier fatal(char *s, ...) 7473e12c5d1SDavid du Colombier { 748*9a747e4fSDavid du Colombier char buf[ERRMAX]; 749*9a747e4fSDavid du Colombier va_list arg; 7503e12c5d1SDavid du Colombier Proc *m; 7513e12c5d1SDavid du Colombier 752*9a747e4fSDavid du Colombier if (s) { 753*9a747e4fSDavid du Colombier va_start(arg, s); 754*9a747e4fSDavid du Colombier vsnprint(buf, ERRMAX, s, arg); 755*9a747e4fSDavid du Colombier va_end(arg); 756*9a747e4fSDavid du Colombier } 7573e12c5d1SDavid du Colombier 7583e12c5d1SDavid du Colombier /* Clear away the slave children */ 7593e12c5d1SDavid du Colombier for(m = Proclist; m; m = m->next) 760219b2ee8SDavid du Colombier postnote(PNPROC, m->pid, "kill"); 7613e12c5d1SDavid du Colombier 7627dd7cddfSDavid du Colombier DEBUG(DFD, "%s\n", buf); 763*9a747e4fSDavid du Colombier if (s) 764*9a747e4fSDavid du Colombier sysfatal(buf); 765*9a747e4fSDavid du Colombier else 766*9a747e4fSDavid du Colombier exits(nil); 767*9a747e4fSDavid du Colombier } 768*9a747e4fSDavid du Colombier 769*9a747e4fSDavid du Colombier void* 770*9a747e4fSDavid du Colombier emallocz(uint n) 771*9a747e4fSDavid du Colombier { 772*9a747e4fSDavid du Colombier void *p; 773*9a747e4fSDavid du Colombier 774*9a747e4fSDavid du Colombier p = mallocz(n, 1); 775*9a747e4fSDavid du Colombier if(p == nil) 776*9a747e4fSDavid du Colombier fatal(Enomem); 777*9a747e4fSDavid du Colombier return p; 778*9a747e4fSDavid du Colombier } 779*9a747e4fSDavid du Colombier 780*9a747e4fSDavid du Colombier char* 781*9a747e4fSDavid du Colombier estrdup(char *s) 782*9a747e4fSDavid du Colombier { 783*9a747e4fSDavid du Colombier char *t; 784*9a747e4fSDavid du Colombier 785*9a747e4fSDavid du Colombier t = strdup(s); 786*9a747e4fSDavid du Colombier if(t == nil) 787*9a747e4fSDavid du Colombier fatal(Enomem); 788*9a747e4fSDavid du Colombier return t; 7893e12c5d1SDavid du Colombier } 7903e12c5d1SDavid du Colombier 7917dd7cddfSDavid du Colombier /* Network on fd1, mount driver on fd0 */ 7927dd7cddfSDavid du Colombier int 793*9a747e4fSDavid du Colombier filter(int fd, char *cmd) 7943e12c5d1SDavid du Colombier { 795*9a747e4fSDavid du Colombier int p[2], lfd, len, nb, argc; 796*9a747e4fSDavid du Colombier char newport[128], buf[128], devdir[40], *s, *file, *argv[16]; 797*9a747e4fSDavid du Colombier 798*9a747e4fSDavid du Colombier // Get a free port and post it to the client. 799*9a747e4fSDavid du Colombier if (announce(anstring, devdir) < 0) 800*9a747e4fSDavid du Colombier sysfatal("filter: Cannot announce %s: %r\n", anstring); 801*9a747e4fSDavid du Colombier 802*9a747e4fSDavid du Colombier snprint(buf, sizeof(buf), "%s/local", devdir); 803*9a747e4fSDavid du Colombier buf[sizeof buf - 1] = '\0'; 804*9a747e4fSDavid du Colombier if ((lfd = open(buf, OREAD)) < 0) 805*9a747e4fSDavid du Colombier sysfatal("filter: Cannot open %s: %r\n", buf); 806*9a747e4fSDavid du Colombier if ((len = read(lfd, newport, sizeof newport - 1)) < 0) 807*9a747e4fSDavid du Colombier sysfatal("filter: Cannot read %s: %r\n", buf); 808*9a747e4fSDavid du Colombier close(lfd); 809*9a747e4fSDavid du Colombier newport[len] = '\0'; 810*9a747e4fSDavid du Colombier 811*9a747e4fSDavid du Colombier if ((s = strchr(newport, '\n')) != nil) 812*9a747e4fSDavid du Colombier *s = '\0'; 813*9a747e4fSDavid du Colombier 814*9a747e4fSDavid du Colombier if ((nb = write(fd, newport, len)) < 0) 815*9a747e4fSDavid du Colombier sysfatal("getport; cannot write port; %r"); 816*9a747e4fSDavid du Colombier assert(nb == len); 817*9a747e4fSDavid du Colombier 818*9a747e4fSDavid du Colombier argc = tokenize(cmd, argv, nelem(argv)-2); 819*9a747e4fSDavid du Colombier if (argc == 0) 820*9a747e4fSDavid du Colombier sysfatal("filter: empty command"); 821*9a747e4fSDavid du Colombier argv[argc++] = buf; 822*9a747e4fSDavid du Colombier argv[argc] = nil; 823*9a747e4fSDavid du Colombier file = argv[0]; 824*9a747e4fSDavid du Colombier if (s = strrchr(argv[0], '/')) 825*9a747e4fSDavid du Colombier argv[0] = s+1; 8263e12c5d1SDavid du Colombier 8277dd7cddfSDavid du Colombier if(pipe(p) < 0) 8287dd7cddfSDavid du Colombier fatal("pipe"); 8297dd7cddfSDavid du Colombier 8307dd7cddfSDavid du Colombier switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { 8317dd7cddfSDavid du Colombier case -1: 8327dd7cddfSDavid du Colombier fatal("rfork record module"); 8337dd7cddfSDavid du Colombier case 0: 834*9a747e4fSDavid du Colombier if (dup(p[0], 1) < 0) 835*9a747e4fSDavid du Colombier fatal("filter: Cannot dup to 1; %r\n"); 836*9a747e4fSDavid du Colombier if (dup(p[0], 0) < 0) 837*9a747e4fSDavid du Colombier fatal("filter: Cannot dup to 0; %r\n"); 8387dd7cddfSDavid du Colombier close(p[0]); 8397dd7cddfSDavid du Colombier close(p[1]); 840*9a747e4fSDavid du Colombier exec(file, argv); 8417dd7cddfSDavid du Colombier fatal("exec record module"); 8427dd7cddfSDavid du Colombier default: 8437dd7cddfSDavid du Colombier close(fd); 8447dd7cddfSDavid du Colombier close(p[0]); 8453e12c5d1SDavid du Colombier } 8467dd7cddfSDavid du Colombier return p[1]; 8473e12c5d1SDavid du Colombier } 848*9a747e4fSDavid du Colombier 849*9a747e4fSDavid du Colombier static void 850*9a747e4fSDavid du Colombier mksecret(char *t, uchar *f) 851*9a747e4fSDavid du Colombier { 852*9a747e4fSDavid du Colombier sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 853*9a747e4fSDavid du Colombier f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); 854*9a747e4fSDavid du Colombier } 855