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> 89a747e4fSDavid du Colombier #include <libsec.h> 93e12c5d1SDavid du Colombier #define Extern 103e12c5d1SDavid du Colombier #include "exportfs.h" 113e12c5d1SDavid du Colombier 129a747e4fSDavid du Colombier #define QIDPATH ((1LL<<48)-1) 139a747e4fSDavid du Colombier vlong newqid = 0; 149a747e4fSDavid du Colombier 159a747e4fSDavid du Colombier enum { 169a747e4fSDavid du Colombier Encnone, 179a747e4fSDavid du Colombier Encssl, 189a747e4fSDavid du Colombier Enctls, 199a747e4fSDavid du Colombier }; 207dd7cddfSDavid du Colombier 213e12c5d1SDavid du Colombier void (*fcalls[])(Fsrpc*) = 223e12c5d1SDavid du Colombier { 239a747e4fSDavid du Colombier [Tversion] Xversion, 249a747e4fSDavid 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; 469a747e4fSDavid du Colombier int srvfd = -1; 479a747e4fSDavid du Colombier int nonone = 1; 489a747e4fSDavid du Colombier char *filterp; 499a747e4fSDavid du Colombier char *ealgs = "rc4_256 sha1"; 509a747e4fSDavid du Colombier char *aanfilter = "/bin/aan"; 519a747e4fSDavid du Colombier int encproto = Encnone; 5224b9ac62SDavid du Colombier int readonly; 53a960ed1cSDavid du Colombier 549a747e4fSDavid du Colombier static void mksecret(char *, uchar *); 559a747e4fSDavid du Colombier static int localread9pmsg(int, void *, uint, ulong *); 56dc5a79c1SDavid du Colombier static char *anstring = "tcp!*!0"; 579a747e4fSDavid du Colombier int filter(int, char *); 58219b2ee8SDavid du Colombier 59219b2ee8SDavid du Colombier void 60219b2ee8SDavid du Colombier usage(void) 61219b2ee8SDavid du Colombier { 62d6adc60eSDavid du Colombier fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] [-S srvfile] [-e 'crypt hash'] [-P exclusion-file] [-A announce-string] [-B address]\n", argv0); 63219b2ee8SDavid du Colombier fatal("usage"); 64219b2ee8SDavid du Colombier } 65219b2ee8SDavid du Colombier 663e12c5d1SDavid du Colombier void 673e12c5d1SDavid du Colombier main(int argc, char **argv) 683e12c5d1SDavid du Colombier { 6983a6036fSDavid du Colombier char buf[ERRMAX], ebuf[ERRMAX], *srvfdfile; 703e12c5d1SDavid du Colombier Fsrpc *r; 7183a6036fSDavid du Colombier int doauth, n, fd; 7283a6036fSDavid du Colombier char *dbfile, *srv, *na, *nsfile, *keyspec; 739a747e4fSDavid du Colombier AuthInfo *ai; 749a747e4fSDavid du Colombier ulong initial; 753e12c5d1SDavid du Colombier 763e12c5d1SDavid du Colombier dbfile = "/tmp/exportdb"; 7780ee5cbfSDavid du Colombier srv = nil; 789a747e4fSDavid du Colombier srvfd = -1; 7983a6036fSDavid du Colombier srvfdfile = nil; 80e0d6d19cSDavid du Colombier na = nil; 81e0d6d19cSDavid du Colombier nsfile = nil; 82da51d93aSDavid du Colombier keyspec = ""; 8383a6036fSDavid du Colombier doauth = 0; 843e12c5d1SDavid du Colombier 859a747e4fSDavid du Colombier ai = nil; 863e12c5d1SDavid du Colombier ARGBEGIN{ 873e12c5d1SDavid du Colombier case 'a': 8883a6036fSDavid du Colombier doauth = 1; 893e12c5d1SDavid du Colombier break; 903e12c5d1SDavid du Colombier 91759d2aa8SDavid du Colombier case 'd': 92759d2aa8SDavid du Colombier dbg++; 93da51d93aSDavid du Colombier break; 94da51d93aSDavid du Colombier 959a747e4fSDavid du Colombier case 'e': 9683a6036fSDavid du Colombier ealgs = EARGF(usage()); 979a747e4fSDavid du Colombier if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) 989a747e4fSDavid du Colombier ealgs = nil; 999a747e4fSDavid du Colombier break; 1009a747e4fSDavid du Colombier 1013e12c5d1SDavid du Colombier case 'f': 10280ee5cbfSDavid du Colombier dbfile = EARGF(usage()); 1033e12c5d1SDavid du Colombier break; 1043e12c5d1SDavid du Colombier 105759d2aa8SDavid du Colombier case 'k': 106759d2aa8SDavid du Colombier keyspec = EARGF(usage()); 1079a747e4fSDavid du Colombier break; 1089a747e4fSDavid du Colombier 1099a747e4fSDavid du Colombier case 'm': 1109a747e4fSDavid du Colombier messagesize = strtoul(EARGF(usage()), nil, 0); 1117dd7cddfSDavid du Colombier break; 1127dd7cddfSDavid du Colombier 11324b9ac62SDavid du Colombier case 'n': 11424b9ac62SDavid du Colombier nonone = 0; 11524b9ac62SDavid du Colombier break; 11624b9ac62SDavid du Colombier 11780ee5cbfSDavid du Colombier case 'r': 11880ee5cbfSDavid du Colombier srv = EARGF(usage()); 11980ee5cbfSDavid du Colombier break; 12080ee5cbfSDavid du Colombier 121bd389b36SDavid du Colombier case 's': 12280ee5cbfSDavid du Colombier srv = "/"; 123bd389b36SDavid du Colombier break; 124219b2ee8SDavid du Colombier 1259a747e4fSDavid du Colombier case 'A': 1269a747e4fSDavid du Colombier anstring = EARGF(usage()); 1279a747e4fSDavid du Colombier break; 1289a747e4fSDavid du Colombier 129759d2aa8SDavid du Colombier case 'B': 130759d2aa8SDavid du Colombier na = EARGF(usage()); 131759d2aa8SDavid du Colombier break; 132759d2aa8SDavid du Colombier 133759d2aa8SDavid du Colombier case 'F': 134759d2aa8SDavid du Colombier /* accepted but ignored, for backwards compatibility */ 135759d2aa8SDavid du Colombier break; 136759d2aa8SDavid du Colombier 137759d2aa8SDavid du Colombier case 'N': 138759d2aa8SDavid du Colombier nsfile = EARGF(usage()); 139759d2aa8SDavid du Colombier break; 140759d2aa8SDavid du Colombier 141759d2aa8SDavid du Colombier case 'P': 142759d2aa8SDavid du Colombier patternfile = EARGF(usage()); 143759d2aa8SDavid du Colombier break; 144759d2aa8SDavid du Colombier 14524b9ac62SDavid du Colombier case 'R': 14624b9ac62SDavid du Colombier readonly = 1; 14724b9ac62SDavid du Colombier break; 14824b9ac62SDavid du Colombier 149759d2aa8SDavid du Colombier case 'S': 150759d2aa8SDavid du Colombier if(srvfdfile) 151759d2aa8SDavid du Colombier usage(); 152759d2aa8SDavid du Colombier srvfdfile = EARGF(usage()); 15324b9ac62SDavid du Colombier break; 15424b9ac62SDavid du Colombier 155219b2ee8SDavid du Colombier default: 156219b2ee8SDavid du Colombier usage(); 1573e12c5d1SDavid du Colombier }ARGEND 1583e12c5d1SDavid du Colombier USED(argc, argv); 1593e12c5d1SDavid du Colombier 16083a6036fSDavid du Colombier if(doauth){ 16183a6036fSDavid du Colombier /* 16283a6036fSDavid du Colombier * We use p9any so we don't have to visit this code again, with the 16383a6036fSDavid du Colombier * cost that this code is incompatible with the old world, which 16483a6036fSDavid du Colombier * requires p9sk2. (The two differ in who talks first, so compatibility 16583a6036fSDavid du Colombier * is awkward.) 16683a6036fSDavid du Colombier */ 16783a6036fSDavid du Colombier ai = auth_proxy(0, auth_getkey, "proto=p9any role=server %s", keyspec); 16883a6036fSDavid du Colombier if(ai == nil) 16983a6036fSDavid du Colombier fatal("auth_proxy: %r"); 17083a6036fSDavid du Colombier if(nonone && strcmp(ai->cuid, "none") == 0) 17183a6036fSDavid du Colombier fatal("exportfs by none disallowed"); 17283a6036fSDavid du Colombier if(auth_chuid(ai, nsfile) < 0) 17383a6036fSDavid du Colombier fatal("auth_chuid: %r"); 17483a6036fSDavid du Colombier putenv("service", "exportfs"); 17583a6036fSDavid du Colombier } 17683a6036fSDavid du Colombier 17783a6036fSDavid du Colombier if(srvfdfile){ 17883a6036fSDavid du Colombier if((srvfd = open(srvfdfile, ORDWR)) < 0) 17983a6036fSDavid du Colombier sysfatal("open '%s': %r", srvfdfile); 18083a6036fSDavid du Colombier } 18183a6036fSDavid du Colombier 18224b9ac62SDavid du Colombier if(na){ 18324b9ac62SDavid du Colombier if(srv == nil) 18424b9ac62SDavid du Colombier sysfatal("-B requires -s"); 18524b9ac62SDavid du Colombier 18624b9ac62SDavid du Colombier if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0) 18724b9ac62SDavid du Colombier sysfatal("can't dial %s: %r", na); 18824b9ac62SDavid du Colombier 189da51d93aSDavid du Colombier ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); 19024b9ac62SDavid du Colombier if(ai == nil) 19124b9ac62SDavid du Colombier sysfatal("%r: %s", na); 19224b9ac62SDavid du Colombier 19324b9ac62SDavid du Colombier dup(fd, 0); 19424b9ac62SDavid du Colombier dup(fd, 1); 19524b9ac62SDavid du Colombier close(fd); 19624b9ac62SDavid du Colombier } 19724b9ac62SDavid du Colombier 198a960ed1cSDavid du Colombier exclusions(); 199a960ed1cSDavid du Colombier 2003e12c5d1SDavid du Colombier if(dbg) { 2013e12c5d1SDavid du Colombier n = create(dbfile, OWRITE|OTRUNC, 0666); 2027dd7cddfSDavid du Colombier dup(n, DFD); 2033e12c5d1SDavid du Colombier close(n); 2043e12c5d1SDavid du Colombier } 2053e12c5d1SDavid du Colombier 2069a747e4fSDavid du Colombier if(srvfd >= 0 && srv){ 2079a747e4fSDavid du Colombier fprint(2, "exportfs: -S cannot be used with -r or -s\n"); 2089a747e4fSDavid du Colombier usage(); 2099a747e4fSDavid du Colombier } 2109a747e4fSDavid du Colombier 2117dd7cddfSDavid du Colombier DEBUG(DFD, "exportfs: started\n"); 212219b2ee8SDavid du Colombier 2133e12c5d1SDavid du Colombier rfork(RFNOTEG); 2143e12c5d1SDavid du Colombier 2159a747e4fSDavid du Colombier if(messagesize == 0){ 2169a747e4fSDavid du Colombier messagesize = iounit(netfd); 2179a747e4fSDavid du Colombier if(messagesize == 0) 2189a747e4fSDavid du Colombier messagesize = 8192+IOHDRSZ; 2199a747e4fSDavid du Colombier } 2203e12c5d1SDavid du Colombier 2219a747e4fSDavid du Colombier Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); 2229a747e4fSDavid du Colombier // for(i=0; i<Nr_workbufs; i++) 2239a747e4fSDavid du Colombier // Workq[i].buf = emallocz(messagesize); 2249a747e4fSDavid du Colombier fhash = emallocz(sizeof(Fid*)*FHASHSIZE); 2253e12c5d1SDavid du Colombier 2269a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 2273e12c5d1SDavid du Colombier 2283e12c5d1SDavid du Colombier /* 229219b2ee8SDavid du Colombier * Get tree to serve from network connection, 230219b2ee8SDavid du Colombier * check we can get there and ack the connection 2313e12c5d1SDavid du Colombier */ 2329a747e4fSDavid du Colombier if(srvfd != -1) { 2339a747e4fSDavid du Colombier /* do nothing */ 2349a747e4fSDavid du Colombier } 2359a747e4fSDavid du Colombier else if(srv) { 23680ee5cbfSDavid du Colombier chdir(srv); 23780ee5cbfSDavid du Colombier DEBUG(DFD, "invoked as server for %s", srv); 2389a747e4fSDavid du Colombier strncpy(buf, srv, sizeof buf); 239219b2ee8SDavid du Colombier } 240bd389b36SDavid du Colombier else { 241bd389b36SDavid du Colombier buf[0] = 0; 2429a747e4fSDavid du Colombier n = read(0, buf, sizeof(buf)-1); 243bd389b36SDavid du Colombier if(n < 0) { 2449a747e4fSDavid du Colombier errstr(buf, sizeof buf); 245bd389b36SDavid du Colombier fprint(0, "read(0): %s", buf); 2467dd7cddfSDavid du Colombier DEBUG(DFD, "read(0): %s", buf); 2473e12c5d1SDavid du Colombier exits(buf); 2483e12c5d1SDavid du Colombier } 249219b2ee8SDavid du Colombier buf[n] = 0; 250bd389b36SDavid du Colombier if(chdir(buf) < 0) { 2519a747e4fSDavid du Colombier errstr(ebuf, sizeof ebuf); 252bd389b36SDavid du Colombier fprint(0, "chdir(%d:\"%s\"): %s", n, buf, ebuf); 2537dd7cddfSDavid du Colombier DEBUG(DFD, "chdir(%d:\"%s\"): %s", n, buf, ebuf); 254bd389b36SDavid du Colombier exits(ebuf); 255bd389b36SDavid du Colombier } 256bd389b36SDavid du Colombier } 2573e12c5d1SDavid du Colombier 25824b9ac62SDavid du Colombier DEBUG(DFD, "\niniting root\n"); 2593e12c5d1SDavid du Colombier initroot(); 2603e12c5d1SDavid du Colombier 2617dd7cddfSDavid du Colombier DEBUG(DFD, "exportfs: %s\n", buf); 2623e12c5d1SDavid du Colombier 2639a747e4fSDavid du Colombier if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2) 2643e12c5d1SDavid du Colombier fatal("open ack write"); 2653e12c5d1SDavid du Colombier 2666a9fc400SDavid du Colombier if (readn(netfd, &initial, sizeof(ulong)) < sizeof(ulong)) 2679a747e4fSDavid du Colombier fatal("can't read initial string: %r\n"); 2689a747e4fSDavid du Colombier 269*29e26a97SDavid du Colombier if (strncmp((char *)&initial, "impo", sizeof(ulong)) == 0) { 2709a747e4fSDavid du Colombier char buf[128], *p, *args[3]; 2719a747e4fSDavid du Colombier 272*29e26a97SDavid du Colombier /* New import. Read import's parameters... */ 2739a747e4fSDavid du Colombier initial = 0; 2749a747e4fSDavid du Colombier 2759a747e4fSDavid du Colombier p = buf; 2769a747e4fSDavid du Colombier while (p - buf < sizeof buf) { 2779a747e4fSDavid du Colombier if ((n = read(netfd, p, 1)) < 0) 2789a747e4fSDavid du Colombier fatal("can't read impo arguments: %r\n"); 2799a747e4fSDavid du Colombier 2809a747e4fSDavid du Colombier if (n == 0) 2819a747e4fSDavid du Colombier fatal("connection closed while reading arguments\n"); 2829a747e4fSDavid du Colombier 2839a747e4fSDavid du Colombier if (*p == '\n') 2849a747e4fSDavid du Colombier *p = '\0'; 2859a747e4fSDavid du Colombier if (*p++ == '\0') 2869a747e4fSDavid du Colombier break; 2879a747e4fSDavid du Colombier } 2889a747e4fSDavid du Colombier 2899a747e4fSDavid du Colombier if (tokenize(buf, args, nelem(args)) != 2) 2909a747e4fSDavid du Colombier fatal("impo arguments invalid: impo%s...\n", buf); 2919a747e4fSDavid du Colombier 292*29e26a97SDavid du Colombier if (strcmp(args[0], "aan") == 0) 2939a747e4fSDavid du Colombier filterp = aanfilter; 294*29e26a97SDavid du Colombier else if (strcmp(args[0], "nofilter") != 0) 2959a747e4fSDavid du Colombier fatal("import filter argument unsupported: %s\n", args[0]); 2969a747e4fSDavid du Colombier 297*29e26a97SDavid du Colombier if (strcmp(args[1], "ssl") == 0) 2989a747e4fSDavid du Colombier encproto = Encssl; 299*29e26a97SDavid du Colombier else if (strcmp(args[1], "tls") == 0) 3009a747e4fSDavid du Colombier encproto = Enctls; 301*29e26a97SDavid du Colombier else if (strcmp(args[1], "clear") != 0) 3029a747e4fSDavid du Colombier fatal("import encryption proto unsupported: %s\n", args[1]); 3039a747e4fSDavid du Colombier 3049a747e4fSDavid du Colombier if (encproto == Enctls) 3059a747e4fSDavid du Colombier sysfatal("%s: tls has not yet been implemented\n", argv[0]); 3069a747e4fSDavid du Colombier } 3079a747e4fSDavid du Colombier 3089a747e4fSDavid du Colombier if (encproto != Encnone && ealgs && ai) { 3099a747e4fSDavid du Colombier uchar key[16]; 3109a747e4fSDavid du Colombier uchar digest[SHA1dlen]; 3119a747e4fSDavid du Colombier char fromclientsecret[21]; 3129a747e4fSDavid du Colombier char fromserversecret[21]; 3139a747e4fSDavid du Colombier int i; 3149a747e4fSDavid du Colombier 3159a747e4fSDavid du Colombier memmove(key+4, ai->secret, ai->nsecret); 3169a747e4fSDavid du Colombier 3179a747e4fSDavid du Colombier /* exchange random numbers */ 3189a747e4fSDavid du Colombier srand(truerand()); 3199a747e4fSDavid du Colombier for(i = 0; i < 4; i++) 3209a747e4fSDavid du Colombier key[i+12] = rand(); 3219a747e4fSDavid du Colombier 3229a747e4fSDavid du Colombier if (initial) 3239a747e4fSDavid du Colombier fatal("Protocol botch: old import\n"); 3249a747e4fSDavid du Colombier if(readn(netfd, key, 4) != 4) 3259a747e4fSDavid du Colombier fatal("can't read key part; %r\n"); 3269a747e4fSDavid du Colombier 3279a747e4fSDavid du Colombier if(write(netfd, key+12, 4) != 4) 3289a747e4fSDavid du Colombier fatal("can't write key part; %r\n"); 3299a747e4fSDavid du Colombier 3309a747e4fSDavid du Colombier /* scramble into two secrets */ 3319a747e4fSDavid du Colombier sha1(key, sizeof(key), digest, nil); 3329a747e4fSDavid du Colombier mksecret(fromclientsecret, digest); 3339a747e4fSDavid du Colombier mksecret(fromserversecret, digest+10); 3349a747e4fSDavid du Colombier 3359a747e4fSDavid du Colombier if (filterp) 3369a747e4fSDavid du Colombier netfd = filter(netfd, filterp); 3379a747e4fSDavid du Colombier 3389a747e4fSDavid du Colombier switch (encproto) { 3399a747e4fSDavid du Colombier case Encssl: 3409a747e4fSDavid du Colombier netfd = pushssl(netfd, ealgs, fromserversecret, 3419a747e4fSDavid du Colombier fromclientsecret, nil); 3429a747e4fSDavid du Colombier break; 3439a747e4fSDavid du Colombier case Enctls: 3449a747e4fSDavid du Colombier default: 3459a747e4fSDavid du Colombier fatal("Unsupported encryption protocol\n"); 3469a747e4fSDavid du Colombier } 3479a747e4fSDavid du Colombier 3489a747e4fSDavid du Colombier if(netfd < 0) 3499a747e4fSDavid du Colombier fatal("can't establish ssl connection: %r"); 3509a747e4fSDavid du Colombier } 3519a747e4fSDavid du Colombier else if (filterp) { 3529a747e4fSDavid du Colombier if (initial) 3539a747e4fSDavid du Colombier fatal("Protocol botch: don't know how to deal with this\n"); 3549a747e4fSDavid du Colombier netfd = filter(netfd, filterp); 3559a747e4fSDavid du Colombier } 3567dd7cddfSDavid du Colombier 3577dd7cddfSDavid du Colombier /* 3583e12c5d1SDavid du Colombier * Start serving file requests from the network 3593e12c5d1SDavid du Colombier */ 3603e12c5d1SDavid du Colombier for(;;) { 3613e12c5d1SDavid du Colombier r = getsbuf(); 3623e12c5d1SDavid du Colombier if(r == 0) 3633e12c5d1SDavid du Colombier fatal("Out of service buffers"); 3643e12c5d1SDavid du Colombier 3659a747e4fSDavid du Colombier n = localread9pmsg(netfd, r->buf, messagesize, &initial); 3669a747e4fSDavid du Colombier if(n <= 0) 3679a747e4fSDavid du Colombier fatal(nil); 3683e12c5d1SDavid du Colombier 3699a747e4fSDavid du Colombier if(convM2S(r->buf, n, &r->work) == 0) 3709a747e4fSDavid du Colombier fatal("convM2S format error"); 3713e12c5d1SDavid du Colombier 3727dd7cddfSDavid du Colombier DEBUG(DFD, "%F\n", &r->work); 3733e12c5d1SDavid du Colombier (fcalls[r->work.type])(r); 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier } 3763e12c5d1SDavid du Colombier 377*29e26a97SDavid du Colombier /* 378*29e26a97SDavid du Colombier * WARNING: Replace this with the original version as soon as all 379*29e26a97SDavid du Colombier * _old_ imports have been replaced with negotiating imports. Also 380*29e26a97SDavid du Colombier * cpu relies on this (which needs to be fixed!) -- pb. 381*29e26a97SDavid du Colombier */ 3829a747e4fSDavid du Colombier static int 3839a747e4fSDavid du Colombier localread9pmsg(int fd, void *abuf, uint n, ulong *initial) 3849a747e4fSDavid du Colombier { 3859a747e4fSDavid du Colombier int m, len; 3869a747e4fSDavid du Colombier uchar *buf; 3879a747e4fSDavid du Colombier 3889a747e4fSDavid du Colombier buf = abuf; 3899a747e4fSDavid du Colombier 3909a747e4fSDavid du Colombier /* read count */ 3919a747e4fSDavid du Colombier assert(BIT32SZ == sizeof(ulong)); 3929a747e4fSDavid du Colombier if (*initial) { 3939a747e4fSDavid du Colombier memcpy(buf, initial, BIT32SZ); 3949a747e4fSDavid du Colombier *initial = 0; 3959a747e4fSDavid du Colombier } 3969a747e4fSDavid du Colombier else { 3979a747e4fSDavid du Colombier m = readn(fd, buf, BIT32SZ); 3989a747e4fSDavid du Colombier if(m != BIT32SZ){ 3999a747e4fSDavid du Colombier if(m < 0) 4009a747e4fSDavid du Colombier return -1; 4019a747e4fSDavid du Colombier return 0; 4029a747e4fSDavid du Colombier } 4039a747e4fSDavid du Colombier } 4049a747e4fSDavid du Colombier 4059a747e4fSDavid du Colombier len = GBIT32(buf); 4069a747e4fSDavid du Colombier if(len <= BIT32SZ || len > n){ 4079a747e4fSDavid du Colombier werrstr("bad length in 9P2000 message header"); 4089a747e4fSDavid du Colombier return -1; 4099a747e4fSDavid du Colombier } 4109a747e4fSDavid du Colombier len -= BIT32SZ; 4119a747e4fSDavid du Colombier m = readn(fd, buf+BIT32SZ, len); 4129a747e4fSDavid du Colombier if(m < len) 4139a747e4fSDavid du Colombier return 0; 4149a747e4fSDavid du Colombier return BIT32SZ+m; 4159a747e4fSDavid du Colombier } 4163e12c5d1SDavid du Colombier void 4173e12c5d1SDavid du Colombier reply(Fcall *r, Fcall *t, char *err) 4183e12c5d1SDavid du Colombier { 4199a747e4fSDavid du Colombier uchar *data; 4203e12c5d1SDavid du Colombier int n; 4213e12c5d1SDavid du Colombier 4223e12c5d1SDavid du Colombier t->tag = r->tag; 4233e12c5d1SDavid du Colombier t->fid = r->fid; 4243e12c5d1SDavid du Colombier if(err) { 4253e12c5d1SDavid du Colombier t->type = Rerror; 4269a747e4fSDavid du Colombier t->ename = err; 4273e12c5d1SDavid du Colombier } 4283e12c5d1SDavid du Colombier else 4293e12c5d1SDavid du Colombier t->type = r->type + 1; 4303e12c5d1SDavid du Colombier 4317dd7cddfSDavid du Colombier DEBUG(DFD, "\t%F\n", t); 4323e12c5d1SDavid du Colombier 4339a747e4fSDavid du Colombier data = malloc(messagesize); /* not mallocz; no need to clear */ 4349a747e4fSDavid du Colombier if(data == nil) 4359a747e4fSDavid du Colombier fatal(Enomem); 4369a747e4fSDavid du Colombier n = convS2M(t, data, messagesize); 4379a747e4fSDavid du Colombier if(write(netfd, data, n)!=n) 4389a747e4fSDavid du Colombier {syslog(0, "exportfs", "short write: %r"); 4393e12c5d1SDavid du Colombier fatal("mount write"); 4403e12c5d1SDavid du Colombier } 4419a747e4fSDavid du Colombier free(data); 4429a747e4fSDavid du Colombier } 4433e12c5d1SDavid du Colombier 4443e12c5d1SDavid du Colombier Fid * 4453e12c5d1SDavid du Colombier getfid(int nr) 4463e12c5d1SDavid du Colombier { 4473e12c5d1SDavid du Colombier Fid *f; 4483e12c5d1SDavid du Colombier 4493e12c5d1SDavid du Colombier for(f = fidhash(nr); f; f = f->next) 4503e12c5d1SDavid du Colombier if(f->nr == nr) 4513e12c5d1SDavid du Colombier return f; 4523e12c5d1SDavid du Colombier 4533e12c5d1SDavid du Colombier return 0; 4543e12c5d1SDavid du Colombier } 4553e12c5d1SDavid du Colombier 4563e12c5d1SDavid du Colombier int 4573e12c5d1SDavid du Colombier freefid(int nr) 4583e12c5d1SDavid du Colombier { 4593e12c5d1SDavid du Colombier Fid *f, **l; 460219b2ee8SDavid du Colombier char buf[128]; 4613e12c5d1SDavid du Colombier 4623e12c5d1SDavid du Colombier l = &fidhash(nr); 4633e12c5d1SDavid du Colombier for(f = *l; f; f = f->next) { 4643e12c5d1SDavid du Colombier if(f->nr == nr) { 465219b2ee8SDavid du Colombier if(f->mid) { 466219b2ee8SDavid du Colombier sprint(buf, "/mnt/exportfs/%d", f->mid); 467219b2ee8SDavid du Colombier unmount(0, buf); 468219b2ee8SDavid du Colombier psmap[f->mid] = 0; 469219b2ee8SDavid du Colombier } 4709a747e4fSDavid du Colombier if(f->f) { 4717dd7cddfSDavid du Colombier freefile(f->f); 4727dd7cddfSDavid du Colombier f->f = nil; 4739a747e4fSDavid du Colombier } 474a960ed1cSDavid du Colombier if(f->dir){ 475a960ed1cSDavid du Colombier free(f->dir); 476a960ed1cSDavid du Colombier f->dir = nil; 477a960ed1cSDavid du Colombier } 4783e12c5d1SDavid du Colombier *l = f->next; 4793e12c5d1SDavid du Colombier f->next = fidfree; 4803e12c5d1SDavid du Colombier fidfree = f; 4813e12c5d1SDavid du Colombier return 1; 4823e12c5d1SDavid du Colombier } 4833e12c5d1SDavid du Colombier l = &f->next; 4843e12c5d1SDavid du Colombier } 4853e12c5d1SDavid du Colombier 4863e12c5d1SDavid du Colombier return 0; 4873e12c5d1SDavid du Colombier } 4883e12c5d1SDavid du Colombier 4893e12c5d1SDavid du Colombier Fid * 4903e12c5d1SDavid du Colombier newfid(int nr) 4913e12c5d1SDavid du Colombier { 4923e12c5d1SDavid du Colombier Fid *new, **l; 4933e12c5d1SDavid du Colombier int i; 4943e12c5d1SDavid du Colombier 4953e12c5d1SDavid du Colombier l = &fidhash(nr); 4963e12c5d1SDavid du Colombier for(new = *l; new; new = new->next) 4973e12c5d1SDavid du Colombier if(new->nr == nr) 4983e12c5d1SDavid du Colombier return 0; 4993e12c5d1SDavid du Colombier 5003e12c5d1SDavid du Colombier if(fidfree == 0) { 5019a747e4fSDavid du Colombier fidfree = emallocz(sizeof(Fid) * Fidchunk); 5023e12c5d1SDavid du Colombier 5033e12c5d1SDavid du Colombier for(i = 0; i < Fidchunk-1; i++) 5043e12c5d1SDavid du Colombier fidfree[i].next = &fidfree[i+1]; 5053e12c5d1SDavid du Colombier 5063e12c5d1SDavid du Colombier fidfree[Fidchunk-1].next = 0; 5073e12c5d1SDavid du Colombier } 5083e12c5d1SDavid du Colombier 5093e12c5d1SDavid du Colombier new = fidfree; 5103e12c5d1SDavid du Colombier fidfree = new->next; 5113e12c5d1SDavid du Colombier 5123e12c5d1SDavid du Colombier memset(new, 0, sizeof(Fid)); 5133e12c5d1SDavid du Colombier new->next = *l; 5143e12c5d1SDavid du Colombier *l = new; 5153e12c5d1SDavid du Colombier new->nr = nr; 5163e12c5d1SDavid du Colombier new->fid = -1; 517219b2ee8SDavid du Colombier new->mid = 0; 5183e12c5d1SDavid du Colombier 5193e12c5d1SDavid du Colombier return new; 5203e12c5d1SDavid du Colombier } 5213e12c5d1SDavid du Colombier 5223e12c5d1SDavid du Colombier Fsrpc * 5233e12c5d1SDavid du Colombier getsbuf(void) 5243e12c5d1SDavid du Colombier { 5253e12c5d1SDavid du Colombier static int ap; 5267dd7cddfSDavid du Colombier int look, rounds; 5273e12c5d1SDavid du Colombier Fsrpc *wb; 5289a747e4fSDavid du Colombier int small_instead_of_fast = 1; 5299a747e4fSDavid du Colombier 5309a747e4fSDavid du Colombier if(small_instead_of_fast) 5319a747e4fSDavid du Colombier ap = 0; /* so we always start looking at the beginning and reuse buffers */ 5323e12c5d1SDavid du Colombier 5337dd7cddfSDavid du Colombier for(rounds = 0; rounds < 10; rounds++) { 5343e12c5d1SDavid du Colombier for(look = 0; look < Nr_workbufs; look++) { 5353e12c5d1SDavid du Colombier if(++ap == Nr_workbufs) 5363e12c5d1SDavid du Colombier ap = 0; 5373e12c5d1SDavid du Colombier if(Workq[ap].busy == 0) 5383e12c5d1SDavid du Colombier break; 5393e12c5d1SDavid du Colombier } 5403e12c5d1SDavid du Colombier 5417dd7cddfSDavid du Colombier if(look == Nr_workbufs){ 5427dd7cddfSDavid du Colombier sleep(10 * rounds); 5437dd7cddfSDavid du Colombier continue; 5447dd7cddfSDavid du Colombier } 5453e12c5d1SDavid du Colombier 5463e12c5d1SDavid du Colombier wb = &Workq[ap]; 5473e12c5d1SDavid du Colombier wb->pid = 0; 5483e12c5d1SDavid du Colombier wb->canint = 0; 5493e12c5d1SDavid du Colombier wb->flushtag = NOTAG; 5503e12c5d1SDavid du Colombier wb->busy = 1; 5519a747e4fSDavid du Colombier if(wb->buf == nil) /* allocate buffers dynamically to keep size down */ 5529a747e4fSDavid du Colombier wb->buf = emallocz(messagesize); 5533e12c5d1SDavid du Colombier return wb; 5543e12c5d1SDavid du Colombier } 5557dd7cddfSDavid du Colombier fatal("No more work buffers"); 5567dd7cddfSDavid du Colombier return nil; 5577dd7cddfSDavid du Colombier } 5583e12c5d1SDavid du Colombier 5597dd7cddfSDavid du Colombier void 5607dd7cddfSDavid du Colombier freefile(File *f) 5613e12c5d1SDavid du Colombier { 5627dd7cddfSDavid du Colombier File *parent, *child; 5633e12c5d1SDavid du Colombier 5647dd7cddfSDavid du Colombier Loop: 5657dd7cddfSDavid du Colombier f->ref--; 5667dd7cddfSDavid du Colombier if(f->ref > 0) 5677dd7cddfSDavid du Colombier return; 5687dd7cddfSDavid du Colombier freecnt++; 5697dd7cddfSDavid du Colombier if(f->ref < 0) abort(); 5707dd7cddfSDavid du Colombier DEBUG(DFD, "free %s\n", f->name); 5717dd7cddfSDavid du Colombier /* delete from parent */ 5727dd7cddfSDavid du Colombier parent = f->parent; 5737dd7cddfSDavid du Colombier if(parent->child == f) 5747dd7cddfSDavid du Colombier parent->child = f->childlist; 5757dd7cddfSDavid du Colombier else{ 5767dd7cddfSDavid du Colombier for(child=parent->child; child->childlist!=f; child=child->childlist) 5777dd7cddfSDavid du Colombier if(child->childlist == nil) 5787dd7cddfSDavid du Colombier fatal("bad child list"); 5797dd7cddfSDavid du Colombier child->childlist = f->childlist; 5807dd7cddfSDavid du Colombier } 5817dd7cddfSDavid du Colombier freeqid(f->qidt); 5829a747e4fSDavid du Colombier free(f->name); 5839a747e4fSDavid du Colombier f->name = nil; 5847dd7cddfSDavid du Colombier free(f); 5857dd7cddfSDavid du Colombier f = parent; 5867dd7cddfSDavid du Colombier if(f != nil) 5877dd7cddfSDavid du Colombier goto Loop; 5883e12c5d1SDavid du Colombier } 5893e12c5d1SDavid du Colombier 5903e12c5d1SDavid du Colombier File * 5913e12c5d1SDavid du Colombier file(File *parent, char *name) 5923e12c5d1SDavid du Colombier { 5939a747e4fSDavid du Colombier Dir *dir; 5949a747e4fSDavid du Colombier char *path; 5957dd7cddfSDavid du Colombier File *f; 5963e12c5d1SDavid du Colombier 5977dd7cddfSDavid du Colombier DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); 5983e12c5d1SDavid du Colombier 5999a747e4fSDavid du Colombier path = makepath(parent, name); 600a960ed1cSDavid du Colombier if(patternfile != nil && excludefile(path)){ 601a960ed1cSDavid du Colombier free(path); 602a960ed1cSDavid du Colombier return nil; 603a960ed1cSDavid du Colombier } 6049a747e4fSDavid du Colombier dir = dirstat(path); 6059a747e4fSDavid du Colombier free(path); 6069a747e4fSDavid du Colombier if(dir == nil) 6077dd7cddfSDavid du Colombier return nil; 6083e12c5d1SDavid du Colombier 6097dd7cddfSDavid du Colombier for(f = parent->child; f; f = f->childlist) 6107dd7cddfSDavid du Colombier if(strcmp(name, f->name) == 0) 6117dd7cddfSDavid du Colombier break; 6127dd7cddfSDavid du Colombier 6137dd7cddfSDavid du Colombier if(f == nil){ 6149a747e4fSDavid du Colombier f = emallocz(sizeof(File)); 6159a747e4fSDavid du Colombier f->name = estrdup(name); 6163e12c5d1SDavid du Colombier 6177dd7cddfSDavid du Colombier f->parent = parent; 6187dd7cddfSDavid du Colombier f->childlist = parent->child; 6197dd7cddfSDavid du Colombier parent->child = f; 6207dd7cddfSDavid du Colombier parent->ref++; 6217dd7cddfSDavid du Colombier f->ref = 0; 6227dd7cddfSDavid du Colombier filecnt++; 6237dd7cddfSDavid du Colombier } 6247dd7cddfSDavid du Colombier f->ref++; 6259a747e4fSDavid du Colombier f->qid.type = dir->qid.type; 6269a747e4fSDavid du Colombier f->qid.vers = dir->qid.vers; 6279a747e4fSDavid du Colombier f->qidt = uniqueqid(dir); 6287dd7cddfSDavid du Colombier f->qid.path = f->qidt->uniqpath; 6293e12c5d1SDavid du Colombier 6307dd7cddfSDavid du Colombier f->inval = 0; 6313e12c5d1SDavid du Colombier 6329a747e4fSDavid du Colombier free(dir); 6337dd7cddfSDavid du Colombier 6347dd7cddfSDavid du Colombier return f; 6353e12c5d1SDavid du Colombier } 6363e12c5d1SDavid du Colombier 6373e12c5d1SDavid du Colombier void 6383e12c5d1SDavid du Colombier initroot(void) 6393e12c5d1SDavid du Colombier { 6409a747e4fSDavid du Colombier Dir *dir; 6413e12c5d1SDavid du Colombier 6429a747e4fSDavid du Colombier root = emallocz(sizeof(File)); 6439a747e4fSDavid du Colombier root->name = estrdup("."); 6443e12c5d1SDavid du Colombier 6459a747e4fSDavid du Colombier dir = dirstat(root->name); 6469a747e4fSDavid du Colombier if(dir == nil) 6473e12c5d1SDavid du Colombier fatal("root stat"); 6483e12c5d1SDavid du Colombier 6497dd7cddfSDavid du Colombier root->ref = 1; 6509a747e4fSDavid du Colombier root->qid.vers = dir->qid.vers; 6519a747e4fSDavid du Colombier root->qidt = uniqueqid(dir); 6527dd7cddfSDavid du Colombier root->qid.path = root->qidt->uniqpath; 6539a747e4fSDavid du Colombier root->qid.type = QTDIR; 6549a747e4fSDavid du Colombier free(dir); 655219b2ee8SDavid du Colombier 6569a747e4fSDavid du Colombier psmpt = emallocz(sizeof(File)); 6579a747e4fSDavid du Colombier psmpt->name = estrdup("/"); 658219b2ee8SDavid du Colombier 6599a747e4fSDavid du Colombier dir = dirstat(psmpt->name); 6609a747e4fSDavid du Colombier if(dir == nil) 661219b2ee8SDavid du Colombier return; 662219b2ee8SDavid du Colombier 6637dd7cddfSDavid du Colombier psmpt->ref = 1; 6649a747e4fSDavid du Colombier psmpt->qid.vers = dir->qid.vers; 6659a747e4fSDavid du Colombier psmpt->qidt = uniqueqid(dir); 6667dd7cddfSDavid du Colombier psmpt->qid.path = psmpt->qidt->uniqpath; 6679a747e4fSDavid du Colombier free(dir); 668219b2ee8SDavid du Colombier 669219b2ee8SDavid du Colombier psmpt = file(psmpt, "mnt"); 670219b2ee8SDavid du Colombier if(psmpt == 0) 671219b2ee8SDavid du Colombier return; 672219b2ee8SDavid du Colombier psmpt = file(psmpt, "exportfs"); 6733e12c5d1SDavid du Colombier } 6743e12c5d1SDavid du Colombier 6759a747e4fSDavid du Colombier char* 6769a747e4fSDavid du Colombier makepath(File *p, char *name) 6773e12c5d1SDavid du Colombier { 6789a747e4fSDavid du Colombier int i, n; 6799a747e4fSDavid du Colombier char *c, *s, *path, *seg[256]; 6803e12c5d1SDavid du Colombier 6813e12c5d1SDavid du Colombier seg[0] = name; 6829a747e4fSDavid du Colombier n = strlen(name)+2; 6839a747e4fSDavid du Colombier for(i = 1; i < 256 && p; i++, p = p->parent){ 6843e12c5d1SDavid du Colombier seg[i] = p->name; 6859a747e4fSDavid du Colombier n += strlen(p->name)+1; 6869a747e4fSDavid du Colombier } 6879a747e4fSDavid du Colombier path = malloc(n); 6889a747e4fSDavid du Colombier if(path == nil) 6899a747e4fSDavid du Colombier fatal("out of memory"); 6909a747e4fSDavid du Colombier s = path; 6913e12c5d1SDavid du Colombier 6923e12c5d1SDavid du Colombier while(i--) { 6933e12c5d1SDavid du Colombier for(c = seg[i]; *c; c++) 6943e12c5d1SDavid du Colombier *s++ = *c; 6953e12c5d1SDavid du Colombier *s++ = '/'; 6963e12c5d1SDavid du Colombier } 6973e12c5d1SDavid du Colombier while(s[-1] == '/') 6983e12c5d1SDavid du Colombier s--; 6993e12c5d1SDavid du Colombier *s = '\0'; 7009a747e4fSDavid du Colombier 7019a747e4fSDavid du Colombier return path; 7023e12c5d1SDavid du Colombier } 7033e12c5d1SDavid du Colombier 7047dd7cddfSDavid du Colombier int 7059a747e4fSDavid du Colombier qidhash(vlong path) 7067dd7cddfSDavid du Colombier { 7077dd7cddfSDavid du Colombier int h, n; 7087dd7cddfSDavid du Colombier 7097dd7cddfSDavid du Colombier h = 0; 7109a747e4fSDavid du Colombier for(n=0; n<64; n+=Nqidbits){ 7117dd7cddfSDavid du Colombier h ^= path; 7127dd7cddfSDavid du Colombier path >>= Nqidbits; 7137dd7cddfSDavid du Colombier } 7147dd7cddfSDavid du Colombier return h & (Nqidtab-1); 7157dd7cddfSDavid du Colombier } 7167dd7cddfSDavid du Colombier 7177dd7cddfSDavid du Colombier void 7187dd7cddfSDavid du Colombier freeqid(Qidtab *q) 7197dd7cddfSDavid du Colombier { 7207dd7cddfSDavid du Colombier ulong h; 7217dd7cddfSDavid du Colombier Qidtab *l; 7227dd7cddfSDavid du Colombier 7237dd7cddfSDavid du Colombier q->ref--; 7247dd7cddfSDavid du Colombier if(q->ref > 0) 7257dd7cddfSDavid du Colombier return; 7267dd7cddfSDavid du Colombier qfreecnt++; 7277dd7cddfSDavid du Colombier h = qidhash(q->path); 7287dd7cddfSDavid du Colombier if(qidtab[h] == q) 7297dd7cddfSDavid du Colombier qidtab[h] = q->next; 7307dd7cddfSDavid du Colombier else{ 7317dd7cddfSDavid du Colombier for(l=qidtab[h]; l->next!=q; l=l->next) 7327dd7cddfSDavid du Colombier if(l->next == nil) 7337dd7cddfSDavid du Colombier fatal("bad qid list"); 7347dd7cddfSDavid du Colombier l->next = q->next; 7357dd7cddfSDavid du Colombier } 7367dd7cddfSDavid du Colombier free(q); 7377dd7cddfSDavid du Colombier } 7387dd7cddfSDavid du Colombier 7397dd7cddfSDavid du Colombier Qidtab* 7407dd7cddfSDavid du Colombier qidlookup(Dir *d) 7417dd7cddfSDavid du Colombier { 7427dd7cddfSDavid du Colombier ulong h; 7437dd7cddfSDavid du Colombier Qidtab *q; 7447dd7cddfSDavid du Colombier 7457dd7cddfSDavid du Colombier h = qidhash(d->qid.path); 7467dd7cddfSDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next) 7477dd7cddfSDavid du Colombier if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) 7487dd7cddfSDavid du Colombier return q; 7497dd7cddfSDavid du Colombier return nil; 7507dd7cddfSDavid du Colombier } 7517dd7cddfSDavid du Colombier 7527dd7cddfSDavid du Colombier int 7539a747e4fSDavid du Colombier qidexists(vlong path) 7547dd7cddfSDavid du Colombier { 7557dd7cddfSDavid du Colombier int h; 7567dd7cddfSDavid du Colombier Qidtab *q; 7577dd7cddfSDavid du Colombier 7587dd7cddfSDavid du Colombier for(h=0; h<Nqidtab; h++) 7597dd7cddfSDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next) 7607dd7cddfSDavid du Colombier if(q->uniqpath == path) 7617dd7cddfSDavid du Colombier return 1; 7627dd7cddfSDavid du Colombier return 0; 7637dd7cddfSDavid du Colombier } 7647dd7cddfSDavid du Colombier 7657dd7cddfSDavid du Colombier Qidtab* 7667dd7cddfSDavid du Colombier uniqueqid(Dir *d) 7677dd7cddfSDavid du Colombier { 7689a747e4fSDavid du Colombier ulong h; 7699a747e4fSDavid du Colombier vlong path; 7707dd7cddfSDavid du Colombier Qidtab *q; 7717dd7cddfSDavid du Colombier 7727dd7cddfSDavid du Colombier q = qidlookup(d); 7737dd7cddfSDavid du Colombier if(q != nil){ 7747dd7cddfSDavid du Colombier q->ref++; 7757dd7cddfSDavid du Colombier return q; 7767dd7cddfSDavid du Colombier } 7777dd7cddfSDavid du Colombier path = d->qid.path; 7787dd7cddfSDavid du Colombier while(qidexists(path)){ 7799a747e4fSDavid du Colombier DEBUG(DFD, "collision on %s\n", d->name); 7807dd7cddfSDavid du Colombier /* collision: find a new one */ 7817dd7cddfSDavid du Colombier ncollision++; 7829a747e4fSDavid du Colombier path &= QIDPATH; 7839a747e4fSDavid du Colombier ++newqid; 7849a747e4fSDavid du Colombier if(newqid >= (1<<16)){ 7859a747e4fSDavid du Colombier DEBUG(DFD, "collision wraparound\n"); 7869a747e4fSDavid du Colombier newqid = 1; 7879a747e4fSDavid du Colombier } 7889a747e4fSDavid du Colombier path |= newqid<<48; 7899a747e4fSDavid du Colombier DEBUG(DFD, "assign qid %.16llux\n", path); 7907dd7cddfSDavid du Colombier } 7917dd7cddfSDavid du Colombier q = mallocz(sizeof(Qidtab), 1); 7927dd7cddfSDavid du Colombier if(q == nil) 7937dd7cddfSDavid du Colombier fatal("no memory for qid table"); 7947dd7cddfSDavid du Colombier qidcnt++; 7957dd7cddfSDavid du Colombier q->ref = 1; 7967dd7cddfSDavid du Colombier q->type = d->type; 7977dd7cddfSDavid du Colombier q->dev = d->dev; 7987dd7cddfSDavid du Colombier q->path = d->qid.path; 7997dd7cddfSDavid du Colombier q->uniqpath = path; 8007dd7cddfSDavid du Colombier h = qidhash(d->qid.path); 8017dd7cddfSDavid du Colombier q->next = qidtab[h]; 8027dd7cddfSDavid du Colombier qidtab[h] = q; 8037dd7cddfSDavid du Colombier return q; 8047dd7cddfSDavid du Colombier } 8057dd7cddfSDavid du Colombier 8063e12c5d1SDavid du Colombier void 8079a747e4fSDavid du Colombier fatal(char *s, ...) 8083e12c5d1SDavid du Colombier { 8099a747e4fSDavid du Colombier char buf[ERRMAX]; 8109a747e4fSDavid du Colombier va_list arg; 8113e12c5d1SDavid du Colombier Proc *m; 8123e12c5d1SDavid du Colombier 8139a747e4fSDavid du Colombier if (s) { 8149a747e4fSDavid du Colombier va_start(arg, s); 8159a747e4fSDavid du Colombier vsnprint(buf, ERRMAX, s, arg); 8169a747e4fSDavid du Colombier va_end(arg); 8179a747e4fSDavid du Colombier } 8183e12c5d1SDavid du Colombier 8193e12c5d1SDavid du Colombier /* Clear away the slave children */ 8203e12c5d1SDavid du Colombier for(m = Proclist; m; m = m->next) 821219b2ee8SDavid du Colombier postnote(PNPROC, m->pid, "kill"); 8223e12c5d1SDavid du Colombier 8237dd7cddfSDavid du Colombier DEBUG(DFD, "%s\n", buf); 8249a747e4fSDavid du Colombier if (s) 8259a747e4fSDavid du Colombier sysfatal(buf); 8269a747e4fSDavid du Colombier else 8279a747e4fSDavid du Colombier exits(nil); 8289a747e4fSDavid du Colombier } 8299a747e4fSDavid du Colombier 8309a747e4fSDavid du Colombier void* 8319a747e4fSDavid du Colombier emallocz(uint n) 8329a747e4fSDavid du Colombier { 8339a747e4fSDavid du Colombier void *p; 8349a747e4fSDavid du Colombier 8359a747e4fSDavid du Colombier p = mallocz(n, 1); 8369a747e4fSDavid du Colombier if(p == nil) 8379a747e4fSDavid du Colombier fatal(Enomem); 8389a747e4fSDavid du Colombier return p; 8399a747e4fSDavid du Colombier } 8409a747e4fSDavid du Colombier 8419a747e4fSDavid du Colombier char* 8429a747e4fSDavid du Colombier estrdup(char *s) 8439a747e4fSDavid du Colombier { 8449a747e4fSDavid du Colombier char *t; 8459a747e4fSDavid du Colombier 8469a747e4fSDavid du Colombier t = strdup(s); 8479a747e4fSDavid du Colombier if(t == nil) 8489a747e4fSDavid du Colombier fatal(Enomem); 8499a747e4fSDavid du Colombier return t; 8503e12c5d1SDavid du Colombier } 8513e12c5d1SDavid du Colombier 8527dd7cddfSDavid du Colombier /* Network on fd1, mount driver on fd0 */ 8537dd7cddfSDavid du Colombier int 8549a747e4fSDavid du Colombier filter(int fd, char *cmd) 8553e12c5d1SDavid du Colombier { 8569a747e4fSDavid du Colombier int p[2], lfd, len, nb, argc; 8579a747e4fSDavid du Colombier char newport[128], buf[128], devdir[40], *s, *file, *argv[16]; 8589a747e4fSDavid du Colombier 859*29e26a97SDavid du Colombier /* Get a free port and post it to the client. */ 8609a747e4fSDavid du Colombier if (announce(anstring, devdir) < 0) 8619a747e4fSDavid du Colombier sysfatal("filter: Cannot announce %s: %r\n", anstring); 8629a747e4fSDavid du Colombier 8639a747e4fSDavid du Colombier snprint(buf, sizeof(buf), "%s/local", devdir); 8649a747e4fSDavid du Colombier buf[sizeof buf - 1] = '\0'; 8659a747e4fSDavid du Colombier if ((lfd = open(buf, OREAD)) < 0) 8669a747e4fSDavid du Colombier sysfatal("filter: Cannot open %s: %r\n", buf); 8679a747e4fSDavid du Colombier if ((len = read(lfd, newport, sizeof newport - 1)) < 0) 8689a747e4fSDavid du Colombier sysfatal("filter: Cannot read %s: %r\n", buf); 8699a747e4fSDavid du Colombier close(lfd); 8709a747e4fSDavid du Colombier newport[len] = '\0'; 8719a747e4fSDavid du Colombier 8729a747e4fSDavid du Colombier if ((s = strchr(newport, '\n')) != nil) 8739a747e4fSDavid du Colombier *s = '\0'; 8749a747e4fSDavid du Colombier 8759a747e4fSDavid du Colombier if ((nb = write(fd, newport, len)) < 0) 8769a747e4fSDavid du Colombier sysfatal("getport; cannot write port; %r"); 8779a747e4fSDavid du Colombier assert(nb == len); 8789a747e4fSDavid du Colombier 8799a747e4fSDavid du Colombier argc = tokenize(cmd, argv, nelem(argv)-2); 8809a747e4fSDavid du Colombier if (argc == 0) 8819a747e4fSDavid du Colombier sysfatal("filter: empty command"); 8829a747e4fSDavid du Colombier argv[argc++] = buf; 8839a747e4fSDavid du Colombier argv[argc] = nil; 8849a747e4fSDavid du Colombier file = argv[0]; 8859a747e4fSDavid du Colombier if (s = strrchr(argv[0], '/')) 8869a747e4fSDavid du Colombier argv[0] = s+1; 8873e12c5d1SDavid du Colombier 8887dd7cddfSDavid du Colombier if(pipe(p) < 0) 8897dd7cddfSDavid du Colombier fatal("pipe"); 8907dd7cddfSDavid du Colombier 8917dd7cddfSDavid du Colombier switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { 8927dd7cddfSDavid du Colombier case -1: 8937dd7cddfSDavid du Colombier fatal("rfork record module"); 8947dd7cddfSDavid du Colombier case 0: 8959a747e4fSDavid du Colombier if (dup(p[0], 1) < 0) 8969a747e4fSDavid du Colombier fatal("filter: Cannot dup to 1; %r\n"); 8979a747e4fSDavid du Colombier if (dup(p[0], 0) < 0) 8989a747e4fSDavid du Colombier fatal("filter: Cannot dup to 0; %r\n"); 8997dd7cddfSDavid du Colombier close(p[0]); 9007dd7cddfSDavid du Colombier close(p[1]); 9019a747e4fSDavid du Colombier exec(file, argv); 9027dd7cddfSDavid du Colombier fatal("exec record module"); 9037dd7cddfSDavid du Colombier default: 9047dd7cddfSDavid du Colombier close(fd); 9057dd7cddfSDavid du Colombier close(p[0]); 9063e12c5d1SDavid du Colombier } 9077dd7cddfSDavid du Colombier return p[1]; 9083e12c5d1SDavid du Colombier } 9099a747e4fSDavid du Colombier 9109a747e4fSDavid du Colombier static void 9119a747e4fSDavid du Colombier mksecret(char *t, uchar *f) 9129a747e4fSDavid du Colombier { 9139a747e4fSDavid du Colombier sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 9149a747e4fSDavid du Colombier f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); 9159a747e4fSDavid du Colombier } 916