13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier #define Extern extern 63e12c5d1SDavid du Colombier #include "exportfs.h" 73e12c5d1SDavid du Colombier 8*9a747e4fSDavid du Colombier char Ebadfid[] = "Bad fid"; 9*9a747e4fSDavid du Colombier char Enotdir[] = "Not a directory"; 10*9a747e4fSDavid du Colombier char Edupfid[] = "Fid already in use"; 11*9a747e4fSDavid du Colombier char Eopen[] = "Fid already opened"; 12*9a747e4fSDavid du Colombier char Exmnt[] = "Cannot .. past mount point"; 13*9a747e4fSDavid du Colombier char Emip[] = "Mount in progress"; 14*9a747e4fSDavid du Colombier char Enopsmt[] = "Out of pseudo mount points"; 15*9a747e4fSDavid du Colombier char Enomem[] = "No memory"; 16*9a747e4fSDavid du Colombier char Eversion[] = "Bad 9P2000 version"; 17*9a747e4fSDavid du Colombier 18*9a747e4fSDavid du Colombier ulong messagesize; 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier void 21*9a747e4fSDavid du Colombier Xversion(Fsrpc *t) 223e12c5d1SDavid du Colombier { 23*9a747e4fSDavid du Colombier Fcall rhdr; 243e12c5d1SDavid du Colombier 25*9a747e4fSDavid du Colombier if(t->work.msize > messagesize) 26*9a747e4fSDavid du Colombier t->work.msize = messagesize; 27*9a747e4fSDavid du Colombier messagesize = t->work.msize; 28*9a747e4fSDavid du Colombier if(strncmp(t->work.version, "9P2000", 6) != 0){ 29*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Eversion); 30*9a747e4fSDavid du Colombier return; 31*9a747e4fSDavid du Colombier } 32*9a747e4fSDavid du Colombier rhdr.version = "9P2000"; 33*9a747e4fSDavid du Colombier rhdr.msize = t->work.msize; 34*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 35*9a747e4fSDavid du Colombier t->busy = 0; 363e12c5d1SDavid du Colombier } 373e12c5d1SDavid du Colombier 383e12c5d1SDavid du Colombier void 39*9a747e4fSDavid du Colombier Xauth(Fsrpc *t) 403e12c5d1SDavid du Colombier { 41*9a747e4fSDavid du Colombier Fcall rhdr; 423e12c5d1SDavid du Colombier 43*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, "exportfs: no authentication required"); 44*9a747e4fSDavid du Colombier t->busy = 0; 453e12c5d1SDavid du Colombier } 463e12c5d1SDavid du Colombier 473e12c5d1SDavid du Colombier void 48*9a747e4fSDavid du Colombier Xflush(Fsrpc *t) 493e12c5d1SDavid du Colombier { 50*9a747e4fSDavid du Colombier Fsrpc *w, *e; 51*9a747e4fSDavid du Colombier Fcall rhdr; 523e12c5d1SDavid du Colombier 533e12c5d1SDavid du Colombier e = &Workq[Nr_workbufs]; 543e12c5d1SDavid du Colombier 55*9a747e4fSDavid du Colombier for(w = Workq; w < e; w++) { 56*9a747e4fSDavid du Colombier if(w->work.tag == t->work.oldtag) { 57*9a747e4fSDavid du Colombier DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint); 58*9a747e4fSDavid du Colombier if(w->busy && w->pid) { 59*9a747e4fSDavid du Colombier w->flushtag = t->work.tag; 60*9a747e4fSDavid du Colombier DEBUG(DFD, "\tset flushtag %d\n", t->work.tag); 61*9a747e4fSDavid du Colombier if(w->canint) 62*9a747e4fSDavid du Colombier postnote(PNPROC, w->pid, "flush"); 63*9a747e4fSDavid du Colombier t->busy = 0; 643e12c5d1SDavid du Colombier return; 653e12c5d1SDavid du Colombier } 663e12c5d1SDavid du Colombier } 673e12c5d1SDavid du Colombier } 683e12c5d1SDavid du Colombier 69*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 707dd7cddfSDavid du Colombier DEBUG(DFD, "\tflush reply\n"); 71*9a747e4fSDavid du Colombier t->busy = 0; 723e12c5d1SDavid du Colombier } 733e12c5d1SDavid du Colombier 743e12c5d1SDavid du Colombier void 75*9a747e4fSDavid du Colombier Xattach(Fsrpc *t) 763e12c5d1SDavid du Colombier { 77*9a747e4fSDavid du Colombier int i, nfd; 78*9a747e4fSDavid du Colombier Fcall rhdr; 793e12c5d1SDavid du Colombier Fid *f; 80*9a747e4fSDavid du Colombier char buf[128]; 813e12c5d1SDavid du Colombier 82*9a747e4fSDavid du Colombier f = newfid(t->work.fid); 833e12c5d1SDavid du Colombier if(f == 0) { 84*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid); 85*9a747e4fSDavid du Colombier t->busy = 0; 863e12c5d1SDavid du Colombier return; 873e12c5d1SDavid du Colombier } 883e12c5d1SDavid du Colombier 89*9a747e4fSDavid du Colombier if(srvfd >= 0){ 90*9a747e4fSDavid du Colombier if(psmpt == 0){ 91*9a747e4fSDavid du Colombier Nomount: 92*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Enopsmt); 93*9a747e4fSDavid du Colombier t->busy = 0; 94*9a747e4fSDavid du Colombier freefid(t->work.fid); 95*9a747e4fSDavid du Colombier return; 96*9a747e4fSDavid du Colombier } 97*9a747e4fSDavid du Colombier for(i=0; i<Npsmpt; i++) 98*9a747e4fSDavid du Colombier if(psmap[i] == 0) 99*9a747e4fSDavid du Colombier break; 100*9a747e4fSDavid du Colombier if(i >= Npsmpt) 101*9a747e4fSDavid du Colombier goto Nomount; 102*9a747e4fSDavid du Colombier sprint(buf, "%d", i); 103*9a747e4fSDavid du Colombier f->f = file(psmpt, buf); 104*9a747e4fSDavid du Colombier if(f->f == nil) 105*9a747e4fSDavid du Colombier goto Nomount; 106*9a747e4fSDavid du Colombier sprint(buf, "/mnt/exportfs/%d", i); 107*9a747e4fSDavid du Colombier nfd = dup(srvfd, -1); 108*9a747e4fSDavid du Colombier if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){ 109*9a747e4fSDavid du Colombier errstr(buf, sizeof buf); 110*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, buf); 111*9a747e4fSDavid du Colombier t->busy = 0; 112*9a747e4fSDavid du Colombier freefid(t->work.fid); 113*9a747e4fSDavid du Colombier close(nfd); 114*9a747e4fSDavid du Colombier return; 115*9a747e4fSDavid du Colombier } 116*9a747e4fSDavid du Colombier psmap[i] = 1; 117*9a747e4fSDavid du Colombier f->mid = i; 118*9a747e4fSDavid du Colombier }else{ 1193e12c5d1SDavid du Colombier f->f = root; 1207dd7cddfSDavid du Colombier f->f->ref++; 1213e12c5d1SDavid du Colombier } 1223e12c5d1SDavid du Colombier 123*9a747e4fSDavid du Colombier rhdr.qid = f->f->qid; 124*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 125*9a747e4fSDavid du Colombier t->busy = 0; 126*9a747e4fSDavid du Colombier } 127*9a747e4fSDavid du Colombier 128*9a747e4fSDavid du Colombier Fid* 129*9a747e4fSDavid du Colombier clonefid(Fid *f, int new) 1303e12c5d1SDavid du Colombier { 131*9a747e4fSDavid du Colombier Fid *n; 1323e12c5d1SDavid du Colombier 133*9a747e4fSDavid du Colombier n = newfid(new); 1343e12c5d1SDavid du Colombier if(n == 0) { 135*9a747e4fSDavid du Colombier n = getfid(new); 136219b2ee8SDavid du Colombier if(n == 0) 137219b2ee8SDavid du Colombier fatal("inconsistent fids"); 138219b2ee8SDavid du Colombier if(n->fid >= 0) 139219b2ee8SDavid du Colombier close(n->fid); 140*9a747e4fSDavid du Colombier freefid(new); 141*9a747e4fSDavid du Colombier n = newfid(new); 142219b2ee8SDavid du Colombier if(n == 0) 143219b2ee8SDavid du Colombier fatal("inconsistent fids2"); 1443e12c5d1SDavid du Colombier } 1453e12c5d1SDavid du Colombier n->f = f->f; 1467dd7cddfSDavid du Colombier n->f->ref++; 147*9a747e4fSDavid du Colombier return n; 1483e12c5d1SDavid du Colombier } 1493e12c5d1SDavid du Colombier 150*9a747e4fSDavid du Colombier void 151*9a747e4fSDavid du Colombier Xwalk(Fsrpc *t) 1523e12c5d1SDavid du Colombier { 153*9a747e4fSDavid du Colombier char err[ERRMAX], *e; 154*9a747e4fSDavid du Colombier Fcall rhdr; 155*9a747e4fSDavid du Colombier Fid *f, *nf; 156*9a747e4fSDavid du Colombier File *wf; 157*9a747e4fSDavid du Colombier int i; 1583e12c5d1SDavid du Colombier 159*9a747e4fSDavid du Colombier f = getfid(t->work.fid); 1603e12c5d1SDavid du Colombier if(f == 0) { 161*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid); 162*9a747e4fSDavid du Colombier t->busy = 0; 163*9a747e4fSDavid du Colombier return; 1643e12c5d1SDavid du Colombier } 1653e12c5d1SDavid du Colombier 166*9a747e4fSDavid du Colombier nf = nil; 167*9a747e4fSDavid du Colombier if(t->work.newfid != t->work.fid){ 168*9a747e4fSDavid du Colombier nf = clonefid(f, t->work.newfid); 169*9a747e4fSDavid du Colombier f = nf; 170*9a747e4fSDavid du Colombier } 171*9a747e4fSDavid du Colombier 172*9a747e4fSDavid du Colombier rhdr.nwqid = 0; 173*9a747e4fSDavid du Colombier e = nil; 174*9a747e4fSDavid du Colombier for(i=0; i<t->work.nwname; i++){ 175*9a747e4fSDavid du Colombier if(i == MAXWELEM){ 176*9a747e4fSDavid du Colombier e = "Too many path elements"; 177*9a747e4fSDavid du Colombier break; 178*9a747e4fSDavid du Colombier } 179*9a747e4fSDavid du Colombier 180*9a747e4fSDavid du Colombier if(strcmp(t->work.wname[i], "..") == 0) { 1817dd7cddfSDavid du Colombier if(f->f->parent == nil) { 182*9a747e4fSDavid du Colombier e = Exmnt; 183*9a747e4fSDavid du Colombier break; 1843e12c5d1SDavid du Colombier } 185*9a747e4fSDavid du Colombier wf = f->f->parent; 186*9a747e4fSDavid du Colombier wf->ref++; 187*9a747e4fSDavid du Colombier goto Accept; 1883e12c5d1SDavid du Colombier } 1893e12c5d1SDavid du Colombier 190*9a747e4fSDavid du Colombier wf = file(f->f, t->work.wname[i]); 191*9a747e4fSDavid du Colombier if(wf == 0){ 192*9a747e4fSDavid du Colombier errstr(err, sizeof err); 193*9a747e4fSDavid du Colombier e = err; 194*9a747e4fSDavid du Colombier break; 195*9a747e4fSDavid du Colombier } 196*9a747e4fSDavid du Colombier Accept: 197*9a747e4fSDavid du Colombier freefile(f->f); 198*9a747e4fSDavid du Colombier rhdr.wqid[rhdr.nwqid++] = wf->qid; 199*9a747e4fSDavid du Colombier f->f = wf; 200*9a747e4fSDavid du Colombier continue; 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier 203*9a747e4fSDavid du Colombier if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname)) 204*9a747e4fSDavid du Colombier freefid(t->work.newfid); 205*9a747e4fSDavid du Colombier if(rhdr.nwqid > 0) 206*9a747e4fSDavid du Colombier e = nil; 207*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, e); 208*9a747e4fSDavid du Colombier t->busy = 0; 2097dd7cddfSDavid du Colombier } 2107dd7cddfSDavid du Colombier 2117dd7cddfSDavid du Colombier void 212*9a747e4fSDavid du Colombier Xclunk(Fsrpc *t) 2137dd7cddfSDavid du Colombier { 214*9a747e4fSDavid du Colombier Fcall rhdr; 2153e12c5d1SDavid du Colombier Fid *f; 2163e12c5d1SDavid du Colombier 217*9a747e4fSDavid du Colombier f = getfid(t->work.fid); 2183e12c5d1SDavid du Colombier if(f == 0) { 219*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid); 220*9a747e4fSDavid du Colombier t->busy = 0; 2213e12c5d1SDavid du Colombier return; 2223e12c5d1SDavid du Colombier } 2233e12c5d1SDavid du Colombier 2243e12c5d1SDavid du Colombier if(f->fid >= 0) 2253e12c5d1SDavid du Colombier close(f->fid); 2263e12c5d1SDavid du Colombier 227*9a747e4fSDavid du Colombier freefid(t->work.fid); 228*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 229*9a747e4fSDavid du Colombier t->busy = 0; 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier void 233*9a747e4fSDavid du Colombier Xstat(Fsrpc *t) 2343e12c5d1SDavid du Colombier { 235*9a747e4fSDavid du Colombier char err[ERRMAX], *path; 236*9a747e4fSDavid du Colombier Fcall rhdr; 2373e12c5d1SDavid du Colombier Fid *f; 238*9a747e4fSDavid du Colombier Dir *d; 2393e12c5d1SDavid du Colombier int s; 240*9a747e4fSDavid du Colombier uchar *statbuf; 2413e12c5d1SDavid du Colombier 242*9a747e4fSDavid du Colombier f = getfid(t->work.fid); 2433e12c5d1SDavid du Colombier if(f == 0) { 244*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid); 245*9a747e4fSDavid du Colombier t->busy = 0; 2463e12c5d1SDavid du Colombier return; 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier if(f->fid >= 0) 249*9a747e4fSDavid du Colombier d = dirfstat(f->fid); 2503e12c5d1SDavid du Colombier else { 251*9a747e4fSDavid du Colombier path = makepath(f->f, ""); 252*9a747e4fSDavid du Colombier d = dirstat(path); 253*9a747e4fSDavid du Colombier free(path); 2543e12c5d1SDavid du Colombier } 2553e12c5d1SDavid du Colombier 256*9a747e4fSDavid du Colombier if(d == nil) { 257*9a747e4fSDavid du Colombier errstr(err, sizeof err); 258*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, err); 259*9a747e4fSDavid du Colombier t->busy = 0; 2603e12c5d1SDavid du Colombier return; 2613e12c5d1SDavid du Colombier } 262*9a747e4fSDavid du Colombier 263*9a747e4fSDavid du Colombier d->qid.path = f->f->qidt->uniqpath; 264*9a747e4fSDavid du Colombier s = sizeD2M(d); 265*9a747e4fSDavid du Colombier statbuf = emallocz(s); 266*9a747e4fSDavid du Colombier s = convD2M(d, statbuf, s); 267*9a747e4fSDavid du Colombier free(d); 268*9a747e4fSDavid du Colombier rhdr.nstat = s; 269*9a747e4fSDavid du Colombier rhdr.stat = statbuf; 270*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 271*9a747e4fSDavid du Colombier free(statbuf); 272*9a747e4fSDavid du Colombier t->busy = 0; 273*9a747e4fSDavid du Colombier } 274*9a747e4fSDavid du Colombier 275*9a747e4fSDavid du Colombier static int 276*9a747e4fSDavid du Colombier getiounit(int fd) 277*9a747e4fSDavid du Colombier { 278*9a747e4fSDavid du Colombier int n; 279*9a747e4fSDavid du Colombier 280*9a747e4fSDavid du Colombier n = iounit(fd); 281*9a747e4fSDavid du Colombier if(n > messagesize-IOHDRSZ) 282*9a747e4fSDavid du Colombier n = messagesize-IOHDRSZ; 283*9a747e4fSDavid du Colombier return n; 2843e12c5d1SDavid du Colombier } 2853e12c5d1SDavid du Colombier 2863e12c5d1SDavid du Colombier void 287*9a747e4fSDavid du Colombier Xcreate(Fsrpc *t) 2883e12c5d1SDavid du Colombier { 289*9a747e4fSDavid du Colombier char err[ERRMAX], *path; 290*9a747e4fSDavid du Colombier Fcall rhdr; 2913e12c5d1SDavid du Colombier Fid *f; 2923e12c5d1SDavid du Colombier File *nf; 2933e12c5d1SDavid du Colombier 294*9a747e4fSDavid du Colombier f = getfid(t->work.fid); 2953e12c5d1SDavid du Colombier if(f == 0) { 296*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid); 297*9a747e4fSDavid du Colombier t->busy = 0; 2983e12c5d1SDavid du Colombier return; 2993e12c5d1SDavid du Colombier } 3003e12c5d1SDavid du Colombier 3013e12c5d1SDavid du Colombier 302*9a747e4fSDavid du Colombier path = makepath(f->f, t->work.name); 303*9a747e4fSDavid du Colombier f->fid = create(path, t->work.mode, t->work.perm); 304*9a747e4fSDavid du Colombier free(path); 3053e12c5d1SDavid du Colombier if(f->fid < 0) { 306*9a747e4fSDavid du Colombier errstr(err, sizeof err); 307*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, err); 308*9a747e4fSDavid du Colombier t->busy = 0; 3093e12c5d1SDavid du Colombier return; 3103e12c5d1SDavid du Colombier } 3113e12c5d1SDavid du Colombier 312*9a747e4fSDavid du Colombier nf = file(f->f, t->work.name); 3133e12c5d1SDavid du Colombier if(nf == 0) { 314*9a747e4fSDavid du Colombier errstr(err, sizeof err); 315*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, err); 316*9a747e4fSDavid du Colombier t->busy = 0; 3173e12c5d1SDavid du Colombier return; 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier 320*9a747e4fSDavid du Colombier f->mode = t->work.mode; 3217dd7cddfSDavid du Colombier freefile(f->f); 3223e12c5d1SDavid du Colombier f->f = nf; 323*9a747e4fSDavid du Colombier rhdr.qid = f->f->qid; 324*9a747e4fSDavid du Colombier rhdr.iounit = getiounit(f->fid); 325*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 326*9a747e4fSDavid du Colombier t->busy = 0; 3273e12c5d1SDavid du Colombier } 3283e12c5d1SDavid du Colombier 3293e12c5d1SDavid du Colombier void 330*9a747e4fSDavid du Colombier Xremove(Fsrpc *t) 3313e12c5d1SDavid du Colombier { 332*9a747e4fSDavid du Colombier char err[ERRMAX], *path; 333*9a747e4fSDavid du Colombier Fcall rhdr; 3343e12c5d1SDavid du Colombier Fid *f; 3353e12c5d1SDavid du Colombier 336*9a747e4fSDavid du Colombier f = getfid(t->work.fid); 3373e12c5d1SDavid du Colombier if(f == 0) { 338*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid); 339*9a747e4fSDavid du Colombier t->busy = 0; 3403e12c5d1SDavid du Colombier return; 3413e12c5d1SDavid du Colombier } 3423e12c5d1SDavid du Colombier 343*9a747e4fSDavid du Colombier path = makepath(f->f, ""); 3447dd7cddfSDavid du Colombier DEBUG(DFD, "\tremove: %s\n", path); 3453e12c5d1SDavid du Colombier if(remove(path) < 0) { 346*9a747e4fSDavid du Colombier free(path); 347*9a747e4fSDavid du Colombier errstr(err, sizeof err); 348*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, err); 349*9a747e4fSDavid du Colombier t->busy = 0; 3503e12c5d1SDavid du Colombier return; 3513e12c5d1SDavid du Colombier } 352*9a747e4fSDavid du Colombier free(path); 3533e12c5d1SDavid du Colombier 3547dd7cddfSDavid du Colombier f->f->inval = 1; 3553e12c5d1SDavid du Colombier if(f->fid >= 0) 3563e12c5d1SDavid du Colombier close(f->fid); 357*9a747e4fSDavid du Colombier freefid(t->work.fid); 3583e12c5d1SDavid du Colombier 359*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 360*9a747e4fSDavid du Colombier t->busy = 0; 3613e12c5d1SDavid du Colombier } 3623e12c5d1SDavid du Colombier 3633e12c5d1SDavid du Colombier void 364*9a747e4fSDavid du Colombier Xwstat(Fsrpc *t) 3653e12c5d1SDavid du Colombier { 366*9a747e4fSDavid du Colombier char err[ERRMAX], *path; 367*9a747e4fSDavid du Colombier Fcall rhdr; 3683e12c5d1SDavid du Colombier Fid *f; 3693e12c5d1SDavid du Colombier int s; 370*9a747e4fSDavid du Colombier char *strings; 371*9a747e4fSDavid du Colombier Dir d; 3723e12c5d1SDavid du Colombier 373*9a747e4fSDavid du Colombier f = getfid(t->work.fid); 3743e12c5d1SDavid du Colombier if(f == 0) { 375*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, Ebadfid); 376*9a747e4fSDavid du Colombier t->busy = 0; 3773e12c5d1SDavid du Colombier return; 3783e12c5d1SDavid du Colombier } 379*9a747e4fSDavid du Colombier strings = emallocz(t->work.nstat); /* ample */ 380*9a747e4fSDavid du Colombier if(convM2D(t->work.stat, t->work.nstat, &d, strings) < 0){ 381*9a747e4fSDavid du Colombier rerrstr(err, sizeof err); 382*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, err); 383*9a747e4fSDavid du Colombier t->busy = 0; 384*9a747e4fSDavid du Colombier free(strings); 385*9a747e4fSDavid du Colombier return; 386*9a747e4fSDavid du Colombier } 387*9a747e4fSDavid du Colombier 3883e12c5d1SDavid du Colombier if(f->fid >= 0) 389*9a747e4fSDavid du Colombier s = dirfwstat(f->fid, &d); 3903e12c5d1SDavid du Colombier else { 391*9a747e4fSDavid du Colombier path = makepath(f->f, ""); 392*9a747e4fSDavid du Colombier s = dirwstat(path, &d); 393*9a747e4fSDavid du Colombier free(path); 3943e12c5d1SDavid du Colombier } 3953e12c5d1SDavid du Colombier if(s < 0) { 396*9a747e4fSDavid du Colombier rerrstr(err, sizeof err); 397*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, err); 3983e12c5d1SDavid du Colombier } 399219b2ee8SDavid du Colombier else { 400219b2ee8SDavid du Colombier /* wstat may really be rename */ 401*9a747e4fSDavid du Colombier if(strcmp(d.name, f->f->name)!=0){ 402*9a747e4fSDavid du Colombier free(f->f->name); 403*9a747e4fSDavid du Colombier f->f->name = estrdup(d.name); 404219b2ee8SDavid du Colombier } 405*9a747e4fSDavid du Colombier reply(&t->work, &rhdr, 0); 4063e12c5d1SDavid du Colombier } 407*9a747e4fSDavid du Colombier free(strings); 408*9a747e4fSDavid du Colombier t->busy = 0; 4093e12c5d1SDavid du Colombier } 4103e12c5d1SDavid du Colombier 4113e12c5d1SDavid du Colombier void 4123e12c5d1SDavid du Colombier slave(Fsrpc *f) 4133e12c5d1SDavid du Colombier { 4143e12c5d1SDavid du Colombier Proc *p; 415*9a747e4fSDavid du Colombier int pid; 4163e12c5d1SDavid du Colombier static int nproc; 4173e12c5d1SDavid du Colombier 4183e12c5d1SDavid du Colombier for(;;) { 4193e12c5d1SDavid du Colombier for(p = Proclist; p; p = p->next) { 4203e12c5d1SDavid du Colombier if(p->busy == 0) { 4213e12c5d1SDavid du Colombier f->pid = p->pid; 4223e12c5d1SDavid du Colombier p->busy = 1; 4233e12c5d1SDavid du Colombier pid = rendezvous(p->pid, (ulong)f); 4243e12c5d1SDavid du Colombier if(pid != p->pid) 4253e12c5d1SDavid du Colombier fatal("rendezvous sync fail"); 4263e12c5d1SDavid du Colombier return; 4273e12c5d1SDavid du Colombier } 4283e12c5d1SDavid du Colombier } 4293e12c5d1SDavid du Colombier 4303e12c5d1SDavid du Colombier if(++nproc > MAXPROC) 4313e12c5d1SDavid du Colombier fatal("too many procs"); 4323e12c5d1SDavid du Colombier 4333e12c5d1SDavid du Colombier pid = rfork(RFPROC|RFMEM); 4343e12c5d1SDavid du Colombier switch(pid) { 4353e12c5d1SDavid du Colombier case -1: 4363e12c5d1SDavid du Colombier fatal("rfork"); 4373e12c5d1SDavid du Colombier 4383e12c5d1SDavid du Colombier case 0: 4393e12c5d1SDavid du Colombier blockingslave(); 4403e12c5d1SDavid du Colombier fatal("slave"); 4413e12c5d1SDavid du Colombier 4423e12c5d1SDavid du Colombier default: 4433e12c5d1SDavid du Colombier p = malloc(sizeof(Proc)); 4443e12c5d1SDavid du Colombier if(p == 0) 4453e12c5d1SDavid du Colombier fatal("out of memory"); 4463e12c5d1SDavid du Colombier 4473e12c5d1SDavid du Colombier p->busy = 0; 4483e12c5d1SDavid du Colombier p->pid = pid; 4493e12c5d1SDavid du Colombier p->next = Proclist; 4503e12c5d1SDavid du Colombier Proclist = p; 4513e12c5d1SDavid du Colombier 4523e12c5d1SDavid du Colombier rendezvous(pid, (ulong)p); 4533e12c5d1SDavid du Colombier } 4543e12c5d1SDavid du Colombier } 4553e12c5d1SDavid du Colombier } 4563e12c5d1SDavid du Colombier 4573e12c5d1SDavid du Colombier void 4583e12c5d1SDavid du Colombier blockingslave(void) 4593e12c5d1SDavid du Colombier { 4603e12c5d1SDavid du Colombier Fsrpc *p; 461*9a747e4fSDavid du Colombier Fcall rhdr; 4623e12c5d1SDavid du Colombier Proc *m; 4633e12c5d1SDavid du Colombier int pid; 4643e12c5d1SDavid du Colombier 4653e12c5d1SDavid du Colombier notify(flushaction); 4663e12c5d1SDavid du Colombier 4673e12c5d1SDavid du Colombier pid = getpid(); 4683e12c5d1SDavid du Colombier 4693e12c5d1SDavid du Colombier m = (Proc*)rendezvous(pid, 0); 4703e12c5d1SDavid du Colombier 4713e12c5d1SDavid du Colombier for(;;) { 4723e12c5d1SDavid du Colombier p = (Fsrpc*)rendezvous(pid, pid); 4733e12c5d1SDavid du Colombier if((int)p == ~0) /* Interrupted */ 4743e12c5d1SDavid du Colombier continue; 4753e12c5d1SDavid du Colombier 4767dd7cddfSDavid du Colombier DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid); 4773e12c5d1SDavid du Colombier if(p->flushtag != NOTAG) 4783e12c5d1SDavid du Colombier goto flushme; 4793e12c5d1SDavid du Colombier 4803e12c5d1SDavid du Colombier switch(p->work.type) { 4813e12c5d1SDavid du Colombier case Tread: 4823e12c5d1SDavid du Colombier slaveread(p); 4833e12c5d1SDavid du Colombier break; 4843e12c5d1SDavid du Colombier 4853e12c5d1SDavid du Colombier case Twrite: 4863e12c5d1SDavid du Colombier slavewrite(p); 4873e12c5d1SDavid du Colombier break; 4883e12c5d1SDavid du Colombier 4893e12c5d1SDavid du Colombier case Topen: 4903e12c5d1SDavid du Colombier slaveopen(p); 4913e12c5d1SDavid du Colombier break; 4923e12c5d1SDavid du Colombier 4933e12c5d1SDavid du Colombier default: 494*9a747e4fSDavid du Colombier reply(&p->work, &rhdr, "exportfs: slave type error"); 4953e12c5d1SDavid du Colombier } 4963e12c5d1SDavid du Colombier if(p->flushtag != NOTAG) { 4973e12c5d1SDavid du Colombier flushme: 4983e12c5d1SDavid du Colombier p->work.type = Tflush; 4993e12c5d1SDavid du Colombier p->work.tag = p->flushtag; 500*9a747e4fSDavid du Colombier reply(&p->work, &rhdr, 0); 5013e12c5d1SDavid du Colombier } 5023e12c5d1SDavid du Colombier p->busy = 0; 5033e12c5d1SDavid du Colombier m->busy = 0; 5043e12c5d1SDavid du Colombier } 5053e12c5d1SDavid du Colombier } 5063e12c5d1SDavid du Colombier 507*9a747e4fSDavid du Colombier int 508*9a747e4fSDavid du Colombier openmount(int sfd) 509219b2ee8SDavid du Colombier { 510*9a747e4fSDavid du Colombier int p[2]; 511*9a747e4fSDavid du Colombier char *arg[10], fdbuf[20], mbuf[20]; 512219b2ee8SDavid du Colombier 513*9a747e4fSDavid du Colombier if(pipe(p) < 0) 514*9a747e4fSDavid du Colombier return -1; 515219b2ee8SDavid du Colombier 516*9a747e4fSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG)){ 517*9a747e4fSDavid du Colombier case -1: 518*9a747e4fSDavid du Colombier return -1; 519*9a747e4fSDavid du Colombier 520*9a747e4fSDavid du Colombier default: 521*9a747e4fSDavid du Colombier close(sfd); 522*9a747e4fSDavid du Colombier close(p[0]); 523*9a747e4fSDavid du Colombier return p[1]; 524*9a747e4fSDavid du Colombier 525*9a747e4fSDavid du Colombier case 0: 526219b2ee8SDavid du Colombier break; 527219b2ee8SDavid du Colombier } 528219b2ee8SDavid du Colombier 529*9a747e4fSDavid du Colombier close(p[1]); 530219b2ee8SDavid du Colombier 531*9a747e4fSDavid du Colombier arg[0] = "exportfs"; 532*9a747e4fSDavid du Colombier snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd); 533*9a747e4fSDavid du Colombier arg[1] = fdbuf; 534*9a747e4fSDavid du Colombier snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ); 535*9a747e4fSDavid du Colombier arg[2] = mbuf; 536*9a747e4fSDavid du Colombier arg[3] = nil; 537219b2ee8SDavid du Colombier 538*9a747e4fSDavid du Colombier close(0); 539*9a747e4fSDavid du Colombier close(1); 540*9a747e4fSDavid du Colombier dup(p[0], 0); 541*9a747e4fSDavid du Colombier dup(p[0], 1); 542*9a747e4fSDavid du Colombier exec("/bin/exportfs", arg); 543*9a747e4fSDavid du Colombier _exits("whoops: exec failed"); 544*9a747e4fSDavid du Colombier return -1; 545219b2ee8SDavid du Colombier } 546219b2ee8SDavid du Colombier 5473e12c5d1SDavid du Colombier void 5483e12c5d1SDavid du Colombier slaveopen(Fsrpc *p) 5493e12c5d1SDavid du Colombier { 550*9a747e4fSDavid du Colombier char err[ERRMAX], *path; 551*9a747e4fSDavid du Colombier Fcall *work, rhdr; 5523e12c5d1SDavid du Colombier Fid *f; 553*9a747e4fSDavid du Colombier Dir *d; 5543e12c5d1SDavid du Colombier 5553e12c5d1SDavid du Colombier work = &p->work; 5563e12c5d1SDavid du Colombier 5573e12c5d1SDavid du Colombier f = getfid(work->fid); 5583e12c5d1SDavid du Colombier if(f == 0) { 559*9a747e4fSDavid du Colombier reply(work, &rhdr, Ebadfid); 5603e12c5d1SDavid du Colombier return; 5613e12c5d1SDavid du Colombier } 5623e12c5d1SDavid du Colombier if(f->fid >= 0) { 5633e12c5d1SDavid du Colombier close(f->fid); 5643e12c5d1SDavid du Colombier f->fid = -1; 5653e12c5d1SDavid du Colombier } 5663e12c5d1SDavid du Colombier 567*9a747e4fSDavid du Colombier path = makepath(f->f, ""); 5687dd7cddfSDavid du Colombier DEBUG(DFD, "\topen: %s %d\n", path, work->mode); 5693e12c5d1SDavid du Colombier 5703e12c5d1SDavid du Colombier p->canint = 1; 571*9a747e4fSDavid du Colombier if(p->flushtag != NOTAG){ 572*9a747e4fSDavid du Colombier free(path); 5733e12c5d1SDavid du Colombier return; 574*9a747e4fSDavid du Colombier } 5753e12c5d1SDavid du Colombier /* There is a race here I ignore because there are no locks */ 5763e12c5d1SDavid du Colombier f->fid = open(path, work->mode); 577*9a747e4fSDavid du Colombier free(path); 5783e12c5d1SDavid du Colombier p->canint = 0; 579*9a747e4fSDavid du Colombier if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) { 580*9a747e4fSDavid du Colombier Error: 581*9a747e4fSDavid du Colombier errstr(err, sizeof err); 582*9a747e4fSDavid du Colombier reply(work, &rhdr, err); 5833e12c5d1SDavid du Colombier return; 5843e12c5d1SDavid du Colombier } 585*9a747e4fSDavid du Colombier f->f->qid = d->qid; 586*9a747e4fSDavid du Colombier free(d); 587*9a747e4fSDavid du Colombier if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */ 588*9a747e4fSDavid du Colombier f->fid = openmount(f->fid); 589*9a747e4fSDavid du Colombier if(f->fid < 0) 590*9a747e4fSDavid du Colombier goto Error; 591*9a747e4fSDavid du Colombier } 5923e12c5d1SDavid du Colombier 5937dd7cddfSDavid du Colombier DEBUG(DFD, "\topen: fd %d\n", f->fid); 5943e12c5d1SDavid du Colombier f->mode = work->mode; 595*9a747e4fSDavid du Colombier rhdr.iounit = getiounit(f->fid); 596*9a747e4fSDavid du Colombier rhdr.qid = f->f->qid; 597*9a747e4fSDavid du Colombier reply(work, &rhdr, 0); 5983e12c5d1SDavid du Colombier } 5993e12c5d1SDavid du Colombier 6003e12c5d1SDavid du Colombier void 6013e12c5d1SDavid du Colombier slaveread(Fsrpc *p) 6023e12c5d1SDavid du Colombier { 6033e12c5d1SDavid du Colombier Fid *f; 6043e12c5d1SDavid du Colombier int n, r; 605*9a747e4fSDavid du Colombier Fcall *work, rhdr; 606*9a747e4fSDavid du Colombier char *data, err[ERRMAX]; 6073e12c5d1SDavid du Colombier 6083e12c5d1SDavid du Colombier work = &p->work; 6093e12c5d1SDavid du Colombier 6103e12c5d1SDavid du Colombier f = getfid(work->fid); 6113e12c5d1SDavid du Colombier if(f == 0) { 612*9a747e4fSDavid du Colombier reply(work, &rhdr, Ebadfid); 6133e12c5d1SDavid du Colombier return; 6143e12c5d1SDavid du Colombier } 6153e12c5d1SDavid du Colombier 616*9a747e4fSDavid du Colombier n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; 6173e12c5d1SDavid du Colombier p->canint = 1; 6183e12c5d1SDavid du Colombier if(p->flushtag != NOTAG) 6193e12c5d1SDavid du Colombier return; 620*9a747e4fSDavid du Colombier data = malloc(n); 621*9a747e4fSDavid du Colombier if(data == nil) 622*9a747e4fSDavid du Colombier fatal(Enomem); 623*9a747e4fSDavid du Colombier 624*9a747e4fSDavid du Colombier /* can't just call pread, since directories must update the offset */ 625*9a747e4fSDavid du Colombier r = pread(f->fid, data, n, work->offset); 6263e12c5d1SDavid du Colombier p->canint = 0; 6273e12c5d1SDavid du Colombier if(r < 0) { 628*9a747e4fSDavid du Colombier free(data); 629*9a747e4fSDavid du Colombier errstr(err, sizeof err); 630*9a747e4fSDavid du Colombier reply(work, &rhdr, err); 6313e12c5d1SDavid du Colombier return; 6323e12c5d1SDavid du Colombier } 6333e12c5d1SDavid du Colombier 6347dd7cddfSDavid du Colombier DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r); 6353e12c5d1SDavid du Colombier 636*9a747e4fSDavid du Colombier rhdr.data = data; 637*9a747e4fSDavid du Colombier rhdr.count = r; 638*9a747e4fSDavid du Colombier reply(work, &rhdr, 0); 639*9a747e4fSDavid du Colombier free(data); 6403e12c5d1SDavid du Colombier } 6413e12c5d1SDavid du Colombier 6423e12c5d1SDavid du Colombier void 6433e12c5d1SDavid du Colombier slavewrite(Fsrpc *p) 6443e12c5d1SDavid du Colombier { 645*9a747e4fSDavid du Colombier char err[ERRMAX]; 646*9a747e4fSDavid du Colombier Fcall *work, rhdr; 6473e12c5d1SDavid du Colombier Fid *f; 6483e12c5d1SDavid du Colombier int n; 6493e12c5d1SDavid du Colombier 6503e12c5d1SDavid du Colombier work = &p->work; 6513e12c5d1SDavid du Colombier 6523e12c5d1SDavid du Colombier f = getfid(work->fid); 6533e12c5d1SDavid du Colombier if(f == 0) { 654*9a747e4fSDavid du Colombier reply(work, &rhdr, Ebadfid); 6553e12c5d1SDavid du Colombier return; 6563e12c5d1SDavid du Colombier } 6573e12c5d1SDavid du Colombier 658*9a747e4fSDavid du Colombier n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; 6593e12c5d1SDavid du Colombier p->canint = 1; 6603e12c5d1SDavid du Colombier if(p->flushtag != NOTAG) 6613e12c5d1SDavid du Colombier return; 662*9a747e4fSDavid du Colombier n = pwrite(f->fid, work->data, n, work->offset); 6633e12c5d1SDavid du Colombier p->canint = 0; 6643e12c5d1SDavid du Colombier if(n < 0) { 665*9a747e4fSDavid du Colombier errstr(err, sizeof err); 666*9a747e4fSDavid du Colombier reply(work, &rhdr, err); 6673e12c5d1SDavid du Colombier return; 6683e12c5d1SDavid du Colombier } 6693e12c5d1SDavid du Colombier 6707dd7cddfSDavid du Colombier DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid); 6713e12c5d1SDavid du Colombier 672*9a747e4fSDavid du Colombier rhdr.count = n; 673*9a747e4fSDavid du Colombier reply(work, &rhdr, 0); 6743e12c5d1SDavid du Colombier } 6753e12c5d1SDavid du Colombier 6763e12c5d1SDavid du Colombier void 6773e12c5d1SDavid du Colombier reopen(Fid *f) 6783e12c5d1SDavid du Colombier { 6793e12c5d1SDavid du Colombier USED(f); 6803e12c5d1SDavid du Colombier fatal("reopen"); 6813e12c5d1SDavid du Colombier } 6823e12c5d1SDavid du Colombier 6833e12c5d1SDavid du Colombier void 6843e12c5d1SDavid du Colombier flushaction(void *a, char *cause) 6853e12c5d1SDavid du Colombier { 6863e12c5d1SDavid du Colombier USED(a); 6873e12c5d1SDavid du Colombier if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) { 6883e12c5d1SDavid du Colombier fprint(2, "exportsrv: note: %s\n", cause); 6893e12c5d1SDavid du Colombier exits("noted"); 6903e12c5d1SDavid du Colombier } 6913e12c5d1SDavid du Colombier if(strncmp(cause, "kill", 4) == 0) 6923e12c5d1SDavid du Colombier noted(NDFLT); 6933e12c5d1SDavid du Colombier 6943e12c5d1SDavid du Colombier noted(NCONT); 6953e12c5d1SDavid du Colombier } 696