1*9a747e4fSDavid du Colombier #include "all.h" 2*9a747e4fSDavid du Colombier #include "9p1.h" 3*9a747e4fSDavid du Colombier 4*9a747e4fSDavid du Colombier /* 5*9a747e4fSDavid du Colombier * buggery to give false qid for 6*9a747e4fSDavid du Colombier * the top 2 levels of the dump fs 7*9a747e4fSDavid du Colombier */ 8*9a747e4fSDavid du Colombier void 9*9a747e4fSDavid du Colombier mkqid(Qid* qid, Dentry *d, int buggery) 10*9a747e4fSDavid du Colombier { 11*9a747e4fSDavid du Colombier int c; 12*9a747e4fSDavid du Colombier 13*9a747e4fSDavid du Colombier if(buggery && d->qid.path == QPROOT && (d->qid.path & QPDIR)){ 14*9a747e4fSDavid du Colombier c = d->name[0]; 15*9a747e4fSDavid du Colombier if(c >= '0' && c <= '9'){ 16*9a747e4fSDavid du Colombier qid->path = 3; 17*9a747e4fSDavid du Colombier qid->vers = d->qid.version; 18*9a747e4fSDavid du Colombier qid->type = QTDIR; 19*9a747e4fSDavid du Colombier 20*9a747e4fSDavid du Colombier c = (c-'0')*10 + (d->name[1]-'0'); 21*9a747e4fSDavid du Colombier if(c >= 1 && c <= 12) 22*9a747e4fSDavid du Colombier qid->path = 4; 23*9a747e4fSDavid du Colombier return; 24*9a747e4fSDavid du Colombier } 25*9a747e4fSDavid du Colombier } 26*9a747e4fSDavid du Colombier 27*9a747e4fSDavid du Colombier mkqid9p2(qid, &d->qid, d->mode); 28*9a747e4fSDavid du Colombier } 29*9a747e4fSDavid du Colombier 30*9a747e4fSDavid du Colombier int 31*9a747e4fSDavid du Colombier mkqidcmp(Qid* qid, Dentry *d) 32*9a747e4fSDavid du Colombier { 33*9a747e4fSDavid du Colombier Qid tmp; 34*9a747e4fSDavid du Colombier 35*9a747e4fSDavid du Colombier mkqid(&tmp, d, 1); 36*9a747e4fSDavid du Colombier if(qid->path==tmp.path && (qid->type&QTDIR)==(tmp.type&QTDIR)) 37*9a747e4fSDavid du Colombier return 0; 38*9a747e4fSDavid du Colombier return Eqid; 39*9a747e4fSDavid du Colombier } 40*9a747e4fSDavid du Colombier 41*9a747e4fSDavid du Colombier void 42*9a747e4fSDavid du Colombier f_nop(Chan *cp, Oldfcall *in, Oldfcall *ou) 43*9a747e4fSDavid du Colombier { 44*9a747e4fSDavid du Colombier 45*9a747e4fSDavid du Colombier USED(in); 46*9a747e4fSDavid du Colombier USED(ou); 47*9a747e4fSDavid du Colombier if(CHAT(cp)) 48*9a747e4fSDavid du Colombier print("c_nop %d\n", cp->chan); 49*9a747e4fSDavid du Colombier } 50*9a747e4fSDavid du Colombier 51*9a747e4fSDavid du Colombier void 52*9a747e4fSDavid du Colombier f_flush(Chan *cp, Oldfcall *in, Oldfcall *ou) 53*9a747e4fSDavid du Colombier { 54*9a747e4fSDavid du Colombier 55*9a747e4fSDavid du Colombier USED(in); 56*9a747e4fSDavid du Colombier USED(ou); 57*9a747e4fSDavid du Colombier if(CHAT(cp)) 58*9a747e4fSDavid du Colombier print("c_flush %d\n", cp->chan); 59*9a747e4fSDavid du Colombier runlock(&cp->reflock); 60*9a747e4fSDavid du Colombier wlock(&cp->reflock); 61*9a747e4fSDavid du Colombier wunlock(&cp->reflock); 62*9a747e4fSDavid du Colombier rlock(&cp->reflock); 63*9a747e4fSDavid du Colombier } 64*9a747e4fSDavid du Colombier 65*9a747e4fSDavid du Colombier void 66*9a747e4fSDavid du Colombier f_session(Chan *cp, Oldfcall *in, Oldfcall *ou) 67*9a747e4fSDavid du Colombier { 68*9a747e4fSDavid du Colombier if(CHAT(cp)) 69*9a747e4fSDavid du Colombier print("c_session %d\n", cp->chan); 70*9a747e4fSDavid du Colombier 71*9a747e4fSDavid du Colombier memmove(cp->rchal, in->chal, sizeof(cp->rchal)); 72*9a747e4fSDavid du Colombier mkchallenge(cp); 73*9a747e4fSDavid du Colombier memmove(ou->chal, cp->chal, sizeof(ou->chal)); 74*9a747e4fSDavid du Colombier if(wstatallow || cp == cons.srvchan) 75*9a747e4fSDavid du Colombier memset(ou->authid, 0, sizeof(ou->authid)); 76*9a747e4fSDavid du Colombier else 77*9a747e4fSDavid du Colombier memmove(ou->authid, nvr.authid, sizeof(ou->authid)); 78*9a747e4fSDavid du Colombier sprint(ou->authdom, "%s.%s", service, nvr.authdom); 79*9a747e4fSDavid du Colombier fileinit(cp); 80*9a747e4fSDavid du Colombier } 81*9a747e4fSDavid du Colombier 82*9a747e4fSDavid du Colombier void 83*9a747e4fSDavid du Colombier f_attach(Chan *cp, Oldfcall *in, Oldfcall *ou) 84*9a747e4fSDavid du Colombier { 85*9a747e4fSDavid du Colombier Iobuf *p; 86*9a747e4fSDavid du Colombier Dentry *d; 87*9a747e4fSDavid du Colombier File *f; 88*9a747e4fSDavid du Colombier int u; 89*9a747e4fSDavid du Colombier Filsys *fs; 90*9a747e4fSDavid du Colombier long raddr; 91*9a747e4fSDavid du Colombier 92*9a747e4fSDavid du Colombier if(CHAT(cp)) { 93*9a747e4fSDavid du Colombier print("c_attach %d\n", cp->chan); 94*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 95*9a747e4fSDavid du Colombier print(" uid = %s\n", in->uname); 96*9a747e4fSDavid du Colombier print(" arg = %s\n", in->aname); 97*9a747e4fSDavid du Colombier } 98*9a747e4fSDavid du Colombier 99*9a747e4fSDavid du Colombier ou->qid = QID9P1(0,0); 100*9a747e4fSDavid du Colombier ou->fid = in->fid; 101*9a747e4fSDavid du Colombier if(!in->aname[0]) /* default */ 102*9a747e4fSDavid du Colombier strncpy(in->aname, filesys[0].name, sizeof(in->aname)); 103*9a747e4fSDavid du Colombier p = 0; 104*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 1); 105*9a747e4fSDavid du Colombier if(!f) { 106*9a747e4fSDavid du Colombier ou->err = Efid; 107*9a747e4fSDavid du Colombier goto out; 108*9a747e4fSDavid du Colombier } 109*9a747e4fSDavid du Colombier u = -1; 110*9a747e4fSDavid du Colombier if(cp != cons.chan){ 111*9a747e4fSDavid du Colombier if(/*authorize(cp, in, ou) == 0 || */strcmp(in->uname, "adm") == 0){ 112*9a747e4fSDavid du Colombier ou->err = Eauth; 113*9a747e4fSDavid du Colombier goto out; 114*9a747e4fSDavid du Colombier } 115*9a747e4fSDavid du Colombier u = strtouid(in->uname); 116*9a747e4fSDavid du Colombier if(u < 0){ 117*9a747e4fSDavid du Colombier ou->err = Ebadu; 118*9a747e4fSDavid du Colombier goto out; 119*9a747e4fSDavid du Colombier } 120*9a747e4fSDavid du Colombier } 121*9a747e4fSDavid du Colombier 122*9a747e4fSDavid du Colombier fs = fsstr(in->aname); 123*9a747e4fSDavid du Colombier if(fs == 0) { 124*9a747e4fSDavid du Colombier ou->err = Ebadspc; 125*9a747e4fSDavid du Colombier goto out; 126*9a747e4fSDavid du Colombier } 127*9a747e4fSDavid du Colombier raddr = getraddr(fs->dev); 128*9a747e4fSDavid du Colombier p = getbuf(fs->dev, raddr, Bread); 129*9a747e4fSDavid du Colombier d = getdir(p, 0); 130*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPROOT) || !(d->mode & DALLOC)) { 131*9a747e4fSDavid du Colombier ou->err = Ealloc; 132*9a747e4fSDavid du Colombier goto out; 133*9a747e4fSDavid du Colombier } 134*9a747e4fSDavid du Colombier f->uid = u; 135*9a747e4fSDavid du Colombier if(iaccess(f, d, DREAD)) { 136*9a747e4fSDavid du Colombier ou->err = Eaccess; 137*9a747e4fSDavid du Colombier goto out; 138*9a747e4fSDavid du Colombier } 139*9a747e4fSDavid du Colombier accessdir(p, d, FREAD); 140*9a747e4fSDavid du Colombier mkqid(&f->qid, d, 1); 141*9a747e4fSDavid du Colombier f->fs = fs; 142*9a747e4fSDavid du Colombier f->addr = raddr; 143*9a747e4fSDavid du Colombier f->slot = 0; 144*9a747e4fSDavid du Colombier f->open = 0; 145*9a747e4fSDavid du Colombier freewp(f->wpath); 146*9a747e4fSDavid du Colombier f->wpath = 0; 147*9a747e4fSDavid du Colombier 148*9a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &f->qid); 149*9a747e4fSDavid du Colombier 150*9a747e4fSDavid du Colombier out: 151*9a747e4fSDavid du Colombier if(p) 152*9a747e4fSDavid du Colombier putbuf(p); 153*9a747e4fSDavid du Colombier if(f) { 154*9a747e4fSDavid du Colombier qunlock(f); 155*9a747e4fSDavid du Colombier if(ou->err) 156*9a747e4fSDavid du Colombier freefp(f); 157*9a747e4fSDavid du Colombier } 158*9a747e4fSDavid du Colombier } 159*9a747e4fSDavid du Colombier 160*9a747e4fSDavid du Colombier void 161*9a747e4fSDavid du Colombier f_clone(Chan *cp, Oldfcall *in, Oldfcall *ou) 162*9a747e4fSDavid du Colombier { 163*9a747e4fSDavid du Colombier File *f1, *f2; 164*9a747e4fSDavid du Colombier int fid, fid1; 165*9a747e4fSDavid du Colombier 166*9a747e4fSDavid du Colombier if(CHAT(cp)) { 167*9a747e4fSDavid du Colombier print("c_clone %d\n", cp->chan); 168*9a747e4fSDavid du Colombier print(" old fid = %d\n", in->fid); 169*9a747e4fSDavid du Colombier print(" new fid = %d\n", in->newfid); 170*9a747e4fSDavid du Colombier } 171*9a747e4fSDavid du Colombier 172*9a747e4fSDavid du Colombier fid = in->fid; 173*9a747e4fSDavid du Colombier fid1 = in->newfid; 174*9a747e4fSDavid du Colombier 175*9a747e4fSDavid du Colombier f1 = 0; 176*9a747e4fSDavid du Colombier f2 = 0; 177*9a747e4fSDavid du Colombier if(fid < fid1) { 178*9a747e4fSDavid du Colombier f1 = filep(cp, fid, 0); 179*9a747e4fSDavid du Colombier f2 = filep(cp, fid1, 1); 180*9a747e4fSDavid du Colombier } else 181*9a747e4fSDavid du Colombier if(fid1 < fid) { 182*9a747e4fSDavid du Colombier f2 = filep(cp, fid1, 1); 183*9a747e4fSDavid du Colombier f1 = filep(cp, fid, 0); 184*9a747e4fSDavid du Colombier } 185*9a747e4fSDavid du Colombier if(!f1 || !f2) { 186*9a747e4fSDavid du Colombier ou->err = Efid; 187*9a747e4fSDavid du Colombier goto out; 188*9a747e4fSDavid du Colombier } 189*9a747e4fSDavid du Colombier 190*9a747e4fSDavid du Colombier 191*9a747e4fSDavid du Colombier f2->fs = f1->fs; 192*9a747e4fSDavid du Colombier f2->addr = f1->addr; 193*9a747e4fSDavid du Colombier f2->open = f1->open & ~FREMOV; 194*9a747e4fSDavid du Colombier f2->uid = f1->uid; 195*9a747e4fSDavid du Colombier f2->slot = f1->slot; 196*9a747e4fSDavid du Colombier f2->qid = f1->qid; 197*9a747e4fSDavid du Colombier 198*9a747e4fSDavid du Colombier freewp(f2->wpath); 199*9a747e4fSDavid du Colombier f2->wpath = getwp(f1->wpath); 200*9a747e4fSDavid du Colombier 201*9a747e4fSDavid du Colombier out: 202*9a747e4fSDavid du Colombier ou->fid = fid; 203*9a747e4fSDavid du Colombier if(f1) 204*9a747e4fSDavid du Colombier qunlock(f1); 205*9a747e4fSDavid du Colombier if(f2) 206*9a747e4fSDavid du Colombier qunlock(f2); 207*9a747e4fSDavid du Colombier } 208*9a747e4fSDavid du Colombier 209*9a747e4fSDavid du Colombier void 210*9a747e4fSDavid du Colombier f_walk(Chan *cp, Oldfcall *in, Oldfcall *ou) 211*9a747e4fSDavid du Colombier { 212*9a747e4fSDavid du Colombier Iobuf *p, *p1; 213*9a747e4fSDavid du Colombier Dentry *d, *d1; 214*9a747e4fSDavid du Colombier File *f; 215*9a747e4fSDavid du Colombier Wpath *w, *ow; 216*9a747e4fSDavid du Colombier int slot; 217*9a747e4fSDavid du Colombier long addr; 218*9a747e4fSDavid du Colombier 219*9a747e4fSDavid du Colombier if(CHAT(cp)) { 220*9a747e4fSDavid du Colombier print("c_walk %d\n", cp->chan); 221*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 222*9a747e4fSDavid du Colombier print(" name = %s\n", in->name); 223*9a747e4fSDavid du Colombier } 224*9a747e4fSDavid du Colombier 225*9a747e4fSDavid du Colombier ou->fid = in->fid; 226*9a747e4fSDavid du Colombier ou->qid = QID9P1(0,0); 227*9a747e4fSDavid du Colombier p = 0; 228*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 229*9a747e4fSDavid du Colombier if(!f) { 230*9a747e4fSDavid du Colombier ou->err = Efid; 231*9a747e4fSDavid du Colombier goto out; 232*9a747e4fSDavid du Colombier } 233*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 234*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 235*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 236*9a747e4fSDavid du Colombier ou->err = Ealloc; 237*9a747e4fSDavid du Colombier goto out; 238*9a747e4fSDavid du Colombier } 239*9a747e4fSDavid du Colombier if(!(d->mode & DDIR)) { 240*9a747e4fSDavid du Colombier ou->err = Edir1; 241*9a747e4fSDavid du Colombier goto out; 242*9a747e4fSDavid du Colombier } 243*9a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d)) 244*9a747e4fSDavid du Colombier goto out; 245*9a747e4fSDavid du Colombier if(cp != cons.chan && iaccess(f, d, DEXEC)) { 246*9a747e4fSDavid du Colombier ou->err = Eaccess; 247*9a747e4fSDavid du Colombier goto out; 248*9a747e4fSDavid du Colombier } 249*9a747e4fSDavid du Colombier accessdir(p, d, FREAD); 250*9a747e4fSDavid du Colombier if(strcmp(in->name, ".") == 0) 251*9a747e4fSDavid du Colombier goto setdot; 252*9a747e4fSDavid du Colombier if(strcmp(in->name, "..") == 0) { 253*9a747e4fSDavid du Colombier if(f->wpath == 0) 254*9a747e4fSDavid du Colombier goto setdot; 255*9a747e4fSDavid du Colombier putbuf(p); 256*9a747e4fSDavid du Colombier p = 0; 257*9a747e4fSDavid du Colombier addr = f->wpath->addr; 258*9a747e4fSDavid du Colombier slot = f->wpath->slot; 259*9a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, addr, Bread); 260*9a747e4fSDavid du Colombier d1 = getdir(p1, slot); 261*9a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { 262*9a747e4fSDavid du Colombier if(p1) 263*9a747e4fSDavid du Colombier putbuf(p1); 264*9a747e4fSDavid du Colombier ou->err = Ephase; 265*9a747e4fSDavid du Colombier goto out; 266*9a747e4fSDavid du Colombier } 267*9a747e4fSDavid du Colombier ow = f->wpath; 268*9a747e4fSDavid du Colombier f->wpath = ow->up; 269*9a747e4fSDavid du Colombier putwp(ow); 270*9a747e4fSDavid du Colombier goto found; 271*9a747e4fSDavid du Colombier } 272*9a747e4fSDavid du Colombier for(addr=0;; addr++) { 273*9a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0); 274*9a747e4fSDavid du Colombier if(!p1 || checktag(p1, Tdir, d->qid.path) ) { 275*9a747e4fSDavid du Colombier if(p1) 276*9a747e4fSDavid du Colombier putbuf(p1); 277*9a747e4fSDavid du Colombier ou->err = Eentry; 278*9a747e4fSDavid du Colombier goto out; 279*9a747e4fSDavid du Colombier } 280*9a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) { 281*9a747e4fSDavid du Colombier d1 = getdir(p1, slot); 282*9a747e4fSDavid du Colombier if(!(d1->mode & DALLOC)) 283*9a747e4fSDavid du Colombier continue; 284*9a747e4fSDavid du Colombier if(strncmp(in->name, d1->name, sizeof(in->name))) 285*9a747e4fSDavid du Colombier continue; 286*9a747e4fSDavid du Colombier /* 287*9a747e4fSDavid du Colombier * update walk path 288*9a747e4fSDavid du Colombier */ 289*9a747e4fSDavid du Colombier w = newwp(); 290*9a747e4fSDavid du Colombier if(!w) { 291*9a747e4fSDavid du Colombier ou->err = Ewalk; 292*9a747e4fSDavid du Colombier putbuf(p1); 293*9a747e4fSDavid du Colombier goto out; 294*9a747e4fSDavid du Colombier } 295*9a747e4fSDavid du Colombier w->addr = f->addr; 296*9a747e4fSDavid du Colombier w->slot = f->slot; 297*9a747e4fSDavid du Colombier w->up = f->wpath; 298*9a747e4fSDavid du Colombier f->wpath = w; 299*9a747e4fSDavid du Colombier slot += DIRPERBUF*addr; 300*9a747e4fSDavid du Colombier goto found; 301*9a747e4fSDavid du Colombier } 302*9a747e4fSDavid du Colombier putbuf(p1); 303*9a747e4fSDavid du Colombier } 304*9a747e4fSDavid du Colombier 305*9a747e4fSDavid du Colombier found: 306*9a747e4fSDavid du Colombier f->addr = p1->addr; 307*9a747e4fSDavid du Colombier mkqid(&f->qid, d1, 1); 308*9a747e4fSDavid du Colombier putbuf(p1); 309*9a747e4fSDavid du Colombier f->slot = slot; 310*9a747e4fSDavid du Colombier 311*9a747e4fSDavid du Colombier setdot: 312*9a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &f->qid); 313*9a747e4fSDavid du Colombier f->open = 0; 314*9a747e4fSDavid du Colombier 315*9a747e4fSDavid du Colombier out: 316*9a747e4fSDavid du Colombier if(p) 317*9a747e4fSDavid du Colombier putbuf(p); 318*9a747e4fSDavid du Colombier if(f) 319*9a747e4fSDavid du Colombier qunlock(f); 320*9a747e4fSDavid du Colombier } 321*9a747e4fSDavid du Colombier 322*9a747e4fSDavid du Colombier void 323*9a747e4fSDavid du Colombier f_clunk(Chan *cp, Oldfcall *in, Oldfcall *ou) 324*9a747e4fSDavid du Colombier { 325*9a747e4fSDavid du Colombier File *f; 326*9a747e4fSDavid du Colombier Tlock *t; 327*9a747e4fSDavid du Colombier long tim; 328*9a747e4fSDavid du Colombier 329*9a747e4fSDavid du Colombier if(CHAT(cp)) { 330*9a747e4fSDavid du Colombier print("c_clunk %d\n", cp->chan); 331*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 332*9a747e4fSDavid du Colombier } 333*9a747e4fSDavid du Colombier 334*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 335*9a747e4fSDavid du Colombier if(!f) { 336*9a747e4fSDavid du Colombier print("%p\n", f); 337*9a747e4fSDavid du Colombier ou->err = Efid; 338*9a747e4fSDavid du Colombier goto out; 339*9a747e4fSDavid du Colombier } 340*9a747e4fSDavid du Colombier if(t = f->tlock) { 341*9a747e4fSDavid du Colombier tim = time(0); 342*9a747e4fSDavid du Colombier if(t->time < tim || t->file != f) 343*9a747e4fSDavid du Colombier ou->err = Ebroken; 344*9a747e4fSDavid du Colombier t->time = 0; /* free the lock */ 345*9a747e4fSDavid du Colombier f->tlock = 0; 346*9a747e4fSDavid du Colombier } 347*9a747e4fSDavid du Colombier if(f->open & FREMOV) 348*9a747e4fSDavid du Colombier ou->err = doremove(f, 0); 349*9a747e4fSDavid du Colombier f->open = 0; 350*9a747e4fSDavid du Colombier freewp(f->wpath); 351*9a747e4fSDavid du Colombier freefp(f); 352*9a747e4fSDavid du Colombier 353*9a747e4fSDavid du Colombier out: 354*9a747e4fSDavid du Colombier if(f) 355*9a747e4fSDavid du Colombier qunlock(f); 356*9a747e4fSDavid du Colombier ou->fid = in->fid; 357*9a747e4fSDavid du Colombier } 358*9a747e4fSDavid du Colombier 359*9a747e4fSDavid du Colombier void 360*9a747e4fSDavid du Colombier f_clwalk(Chan *cp, Oldfcall *in, Oldfcall *ou) 361*9a747e4fSDavid du Colombier { 362*9a747e4fSDavid du Colombier int er, fid; 363*9a747e4fSDavid du Colombier 364*9a747e4fSDavid du Colombier if(CHAT(cp)) 365*9a747e4fSDavid du Colombier print("c_clwalk macro\n"); 366*9a747e4fSDavid du Colombier 367*9a747e4fSDavid du Colombier f_clone(cp, in, ou); /* sets tag, fid */ 368*9a747e4fSDavid du Colombier if(ou->err) 369*9a747e4fSDavid du Colombier return; 370*9a747e4fSDavid du Colombier fid = in->fid; 371*9a747e4fSDavid du Colombier in->fid = in->newfid; 372*9a747e4fSDavid du Colombier f_walk(cp, in, ou); /* sets tag, fid, qid */ 373*9a747e4fSDavid du Colombier er = ou->err; 374*9a747e4fSDavid du Colombier if(er == Eentry) { 375*9a747e4fSDavid du Colombier /* 376*9a747e4fSDavid du Colombier * if error is "no entry" 377*9a747e4fSDavid du Colombier * return non error and fid 378*9a747e4fSDavid du Colombier */ 379*9a747e4fSDavid du Colombier ou->err = 0; 380*9a747e4fSDavid du Colombier f_clunk(cp, in, ou); /* sets tag, fid */ 381*9a747e4fSDavid du Colombier ou->err = 0; 382*9a747e4fSDavid du Colombier ou->fid = fid; 383*9a747e4fSDavid du Colombier if(CHAT(cp)) 384*9a747e4fSDavid du Colombier print(" error: %s\n", errstring[er]); 385*9a747e4fSDavid du Colombier return; 386*9a747e4fSDavid du Colombier } 387*9a747e4fSDavid du Colombier if(er) { 388*9a747e4fSDavid du Colombier /* 389*9a747e4fSDavid du Colombier * if any other error 390*9a747e4fSDavid du Colombier * return an error 391*9a747e4fSDavid du Colombier */ 392*9a747e4fSDavid du Colombier ou->err = 0; 393*9a747e4fSDavid du Colombier f_clunk(cp, in, ou); /* sets tag, fid */ 394*9a747e4fSDavid du Colombier ou->err = er; 395*9a747e4fSDavid du Colombier return; 396*9a747e4fSDavid du Colombier } 397*9a747e4fSDavid du Colombier /* 398*9a747e4fSDavid du Colombier * non error 399*9a747e4fSDavid du Colombier * return newfid 400*9a747e4fSDavid du Colombier */ 401*9a747e4fSDavid du Colombier } 402*9a747e4fSDavid du Colombier 403*9a747e4fSDavid du Colombier void 404*9a747e4fSDavid du Colombier f_open(Chan *cp, Oldfcall *in, Oldfcall *ou) 405*9a747e4fSDavid du Colombier { 406*9a747e4fSDavid du Colombier Iobuf *p; 407*9a747e4fSDavid du Colombier Dentry *d; 408*9a747e4fSDavid du Colombier File *f; 409*9a747e4fSDavid du Colombier Tlock *t; 410*9a747e4fSDavid du Colombier Qid qid; 411*9a747e4fSDavid du Colombier int ro, fmod; 412*9a747e4fSDavid du Colombier 413*9a747e4fSDavid du Colombier if(CHAT(cp)) { 414*9a747e4fSDavid du Colombier print("c_open %d\n", cp->chan); 415*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 416*9a747e4fSDavid du Colombier print(" mode = %o\n", in->mode); 417*9a747e4fSDavid du Colombier } 418*9a747e4fSDavid du Colombier 419*9a747e4fSDavid du Colombier p = 0; 420*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 421*9a747e4fSDavid du Colombier if(!f) { 422*9a747e4fSDavid du Colombier ou->err = Efid; 423*9a747e4fSDavid du Colombier goto out; 424*9a747e4fSDavid du Colombier } 425*9a747e4fSDavid du Colombier 426*9a747e4fSDavid du Colombier /* 427*9a747e4fSDavid du Colombier * if remove on close, check access here 428*9a747e4fSDavid du Colombier */ 429*9a747e4fSDavid du Colombier ro = isro(f->fs->dev); 430*9a747e4fSDavid du Colombier if(in->mode & MRCLOSE) { 431*9a747e4fSDavid du Colombier if(ro) { 432*9a747e4fSDavid du Colombier ou->err = Eronly; 433*9a747e4fSDavid du Colombier goto out; 434*9a747e4fSDavid du Colombier } 435*9a747e4fSDavid du Colombier /* 436*9a747e4fSDavid du Colombier * check on parent directory of file to be deleted 437*9a747e4fSDavid du Colombier */ 438*9a747e4fSDavid du Colombier if(f->wpath == 0 || f->wpath->addr == f->addr) { 439*9a747e4fSDavid du Colombier ou->err = Ephase; 440*9a747e4fSDavid du Colombier goto out; 441*9a747e4fSDavid du Colombier } 442*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->wpath->addr, Bread); 443*9a747e4fSDavid du Colombier d = getdir(p, f->wpath->slot); 444*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 445*9a747e4fSDavid du Colombier ou->err = Ephase; 446*9a747e4fSDavid du Colombier goto out; 447*9a747e4fSDavid du Colombier } 448*9a747e4fSDavid du Colombier if(iaccess(f, d, DWRITE)) { 449*9a747e4fSDavid du Colombier ou->err = Eaccess; 450*9a747e4fSDavid du Colombier goto out; 451*9a747e4fSDavid du Colombier } 452*9a747e4fSDavid du Colombier putbuf(p); 453*9a747e4fSDavid du Colombier } 454*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 455*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 456*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 457*9a747e4fSDavid du Colombier ou->err = Ealloc; 458*9a747e4fSDavid du Colombier goto out; 459*9a747e4fSDavid du Colombier } 460*9a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d)) 461*9a747e4fSDavid du Colombier goto out; 462*9a747e4fSDavid du Colombier mkqid(&qid, d, 1); 463*9a747e4fSDavid du Colombier switch(in->mode & 7) { 464*9a747e4fSDavid du Colombier 465*9a747e4fSDavid du Colombier case MREAD: 466*9a747e4fSDavid du Colombier if(iaccess(f, d, DREAD) && !writeallow) 467*9a747e4fSDavid du Colombier goto badaccess; 468*9a747e4fSDavid du Colombier fmod = FREAD; 469*9a747e4fSDavid du Colombier break; 470*9a747e4fSDavid du Colombier 471*9a747e4fSDavid du Colombier case MWRITE: 472*9a747e4fSDavid du Colombier if((d->mode & DDIR) || 473*9a747e4fSDavid du Colombier (iaccess(f, d, DWRITE) && !writeallow)) 474*9a747e4fSDavid du Colombier goto badaccess; 475*9a747e4fSDavid du Colombier if(ro) { 476*9a747e4fSDavid du Colombier ou->err = Eronly; 477*9a747e4fSDavid du Colombier goto out; 478*9a747e4fSDavid du Colombier } 479*9a747e4fSDavid du Colombier fmod = FWRITE; 480*9a747e4fSDavid du Colombier break; 481*9a747e4fSDavid du Colombier 482*9a747e4fSDavid du Colombier case MBOTH: 483*9a747e4fSDavid du Colombier if((d->mode & DDIR) || 484*9a747e4fSDavid du Colombier (iaccess(f, d, DREAD) && !writeallow) || 485*9a747e4fSDavid du Colombier (iaccess(f, d, DWRITE) && !writeallow)) 486*9a747e4fSDavid du Colombier goto badaccess; 487*9a747e4fSDavid du Colombier if(ro) { 488*9a747e4fSDavid du Colombier ou->err = Eronly; 489*9a747e4fSDavid du Colombier goto out; 490*9a747e4fSDavid du Colombier } 491*9a747e4fSDavid du Colombier fmod = FREAD+FWRITE; 492*9a747e4fSDavid du Colombier break; 493*9a747e4fSDavid du Colombier 494*9a747e4fSDavid du Colombier case MEXEC: 495*9a747e4fSDavid du Colombier if((d->mode & DDIR) || 496*9a747e4fSDavid du Colombier iaccess(f, d, DEXEC)) 497*9a747e4fSDavid du Colombier goto badaccess; 498*9a747e4fSDavid du Colombier fmod = FREAD; 499*9a747e4fSDavid du Colombier break; 500*9a747e4fSDavid du Colombier 501*9a747e4fSDavid du Colombier default: 502*9a747e4fSDavid du Colombier ou->err = Emode; 503*9a747e4fSDavid du Colombier goto out; 504*9a747e4fSDavid du Colombier } 505*9a747e4fSDavid du Colombier if(in->mode & MTRUNC) { 506*9a747e4fSDavid du Colombier if((d->mode & DDIR) || 507*9a747e4fSDavid du Colombier (iaccess(f, d, DWRITE) && !writeallow)) 508*9a747e4fSDavid du Colombier goto badaccess; 509*9a747e4fSDavid du Colombier if(ro) { 510*9a747e4fSDavid du Colombier ou->err = Eronly; 511*9a747e4fSDavid du Colombier goto out; 512*9a747e4fSDavid du Colombier } 513*9a747e4fSDavid du Colombier } 514*9a747e4fSDavid du Colombier t = 0; 515*9a747e4fSDavid du Colombier if(d->mode & DLOCK) { 516*9a747e4fSDavid du Colombier t = tlocked(p, d); 517*9a747e4fSDavid du Colombier if(t == 0) { 518*9a747e4fSDavid du Colombier ou->err = Elocked; 519*9a747e4fSDavid du Colombier goto out; 520*9a747e4fSDavid du Colombier } 521*9a747e4fSDavid du Colombier t->file = f; 522*9a747e4fSDavid du Colombier } 523*9a747e4fSDavid du Colombier if(in->mode & MRCLOSE) 524*9a747e4fSDavid du Colombier fmod |= FREMOV; 525*9a747e4fSDavid du Colombier f->open = fmod; 526*9a747e4fSDavid du Colombier if(in->mode & MTRUNC) 527*9a747e4fSDavid du Colombier if(!(d->mode & DAPND)) 528*9a747e4fSDavid du Colombier dtrunc(p, d); 529*9a747e4fSDavid du Colombier f->tlock = t; 530*9a747e4fSDavid du Colombier f->lastra = 0; 531*9a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &qid); 532*9a747e4fSDavid du Colombier goto out; 533*9a747e4fSDavid du Colombier 534*9a747e4fSDavid du Colombier badaccess: 535*9a747e4fSDavid du Colombier ou->err = Eaccess; 536*9a747e4fSDavid du Colombier f->open = 0; 537*9a747e4fSDavid du Colombier 538*9a747e4fSDavid du Colombier out: 539*9a747e4fSDavid du Colombier if(p) 540*9a747e4fSDavid du Colombier putbuf(p); 541*9a747e4fSDavid du Colombier if(f) 542*9a747e4fSDavid du Colombier qunlock(f); 543*9a747e4fSDavid du Colombier ou->fid = in->fid; 544*9a747e4fSDavid du Colombier } 545*9a747e4fSDavid du Colombier 546*9a747e4fSDavid du Colombier void 547*9a747e4fSDavid du Colombier f_create(Chan *cp, Oldfcall *in, Oldfcall *ou) 548*9a747e4fSDavid du Colombier { 549*9a747e4fSDavid du Colombier Iobuf *p, *p1; 550*9a747e4fSDavid du Colombier Dentry *d, *d1; 551*9a747e4fSDavid du Colombier File *f; 552*9a747e4fSDavid du Colombier int slot, slot1, fmod; 553*9a747e4fSDavid du Colombier long addr, addr1, path; 554*9a747e4fSDavid du Colombier Qid qid; 555*9a747e4fSDavid du Colombier Tlock *t; 556*9a747e4fSDavid du Colombier Wpath *w; 557*9a747e4fSDavid du Colombier 558*9a747e4fSDavid du Colombier if(CHAT(cp)) { 559*9a747e4fSDavid du Colombier print("c_create %d\n", cp->chan); 560*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 561*9a747e4fSDavid du Colombier print(" name = %s\n", in->name); 562*9a747e4fSDavid du Colombier print(" perm = %lx+%lo\n", (in->perm>>28)&0xf, 563*9a747e4fSDavid du Colombier in->perm&0777); 564*9a747e4fSDavid du Colombier print(" mode = %d\n", in->mode); 565*9a747e4fSDavid du Colombier } 566*9a747e4fSDavid du Colombier 567*9a747e4fSDavid du Colombier p = 0; 568*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 569*9a747e4fSDavid du Colombier if(!f) { 570*9a747e4fSDavid du Colombier ou->err = Efid; 571*9a747e4fSDavid du Colombier goto out; 572*9a747e4fSDavid du Colombier } 573*9a747e4fSDavid du Colombier if(isro(f->fs->dev)) { 574*9a747e4fSDavid du Colombier ou->err = Eronly; 575*9a747e4fSDavid du Colombier goto out; 576*9a747e4fSDavid du Colombier } 577*9a747e4fSDavid du Colombier 578*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 579*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 580*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 581*9a747e4fSDavid du Colombier ou->err = Ealloc; 582*9a747e4fSDavid du Colombier goto out; 583*9a747e4fSDavid du Colombier } 584*9a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d)) 585*9a747e4fSDavid du Colombier goto out; 586*9a747e4fSDavid du Colombier if(!(d->mode & DDIR)) { 587*9a747e4fSDavid du Colombier ou->err = Edir2; 588*9a747e4fSDavid du Colombier goto out; 589*9a747e4fSDavid du Colombier } 590*9a747e4fSDavid du Colombier if(cp != cons.chan && iaccess(f, d, DWRITE) && !writeallow) { 591*9a747e4fSDavid du Colombier ou->err = Eaccess; 592*9a747e4fSDavid du Colombier goto out; 593*9a747e4fSDavid du Colombier } 594*9a747e4fSDavid du Colombier accessdir(p, d, FREAD); 595*9a747e4fSDavid du Colombier if(!strncmp(in->name, ".", sizeof(in->name)) || 596*9a747e4fSDavid du Colombier !strncmp(in->name, "..", sizeof(in->name))) { 597*9a747e4fSDavid du Colombier ou->err = Edot; 598*9a747e4fSDavid du Colombier goto out; 599*9a747e4fSDavid du Colombier } 600*9a747e4fSDavid du Colombier if(checkname(in->name)) { 601*9a747e4fSDavid du Colombier ou->err = Ename; 602*9a747e4fSDavid du Colombier goto out; 603*9a747e4fSDavid du Colombier } 604*9a747e4fSDavid du Colombier addr1 = 0; 605*9a747e4fSDavid du Colombier slot1 = 0; /* set */ 606*9a747e4fSDavid du Colombier for(addr=0;; addr++) { 607*9a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0); 608*9a747e4fSDavid du Colombier if(!p1) { 609*9a747e4fSDavid du Colombier if(addr1) 610*9a747e4fSDavid du Colombier break; 611*9a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, Tdir); 612*9a747e4fSDavid du Colombier } 613*9a747e4fSDavid du Colombier if(p1 == 0) { 614*9a747e4fSDavid du Colombier ou->err = Efull; 615*9a747e4fSDavid du Colombier goto out; 616*9a747e4fSDavid du Colombier } 617*9a747e4fSDavid du Colombier if(checktag(p1, Tdir, d->qid.path)) { 618*9a747e4fSDavid du Colombier putbuf(p1); 619*9a747e4fSDavid du Colombier goto phase; 620*9a747e4fSDavid du Colombier } 621*9a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) { 622*9a747e4fSDavid du Colombier d1 = getdir(p1, slot); 623*9a747e4fSDavid du Colombier if(!(d1->mode & DALLOC)) { 624*9a747e4fSDavid du Colombier if(!addr1) { 625*9a747e4fSDavid du Colombier addr1 = p1->addr; 626*9a747e4fSDavid du Colombier slot1 = slot + addr*DIRPERBUF; 627*9a747e4fSDavid du Colombier } 628*9a747e4fSDavid du Colombier continue; 629*9a747e4fSDavid du Colombier } 630*9a747e4fSDavid du Colombier if(!strncmp(in->name, d1->name, sizeof(in->name))) { 631*9a747e4fSDavid du Colombier putbuf(p1); 632*9a747e4fSDavid du Colombier ou->err = Eexist; 633*9a747e4fSDavid du Colombier goto out; 634*9a747e4fSDavid du Colombier } 635*9a747e4fSDavid du Colombier } 636*9a747e4fSDavid du Colombier putbuf(p1); 637*9a747e4fSDavid du Colombier } 638*9a747e4fSDavid du Colombier switch(in->mode & 7) { 639*9a747e4fSDavid du Colombier case MEXEC: 640*9a747e4fSDavid du Colombier case MREAD: /* seems only useful to make directories */ 641*9a747e4fSDavid du Colombier fmod = FREAD; 642*9a747e4fSDavid du Colombier break; 643*9a747e4fSDavid du Colombier 644*9a747e4fSDavid du Colombier case MWRITE: 645*9a747e4fSDavid du Colombier fmod = FWRITE; 646*9a747e4fSDavid du Colombier break; 647*9a747e4fSDavid du Colombier 648*9a747e4fSDavid du Colombier case MBOTH: 649*9a747e4fSDavid du Colombier fmod = FREAD+FWRITE; 650*9a747e4fSDavid du Colombier break; 651*9a747e4fSDavid du Colombier 652*9a747e4fSDavid du Colombier default: 653*9a747e4fSDavid du Colombier ou->err = Emode; 654*9a747e4fSDavid du Colombier goto out; 655*9a747e4fSDavid du Colombier } 656*9a747e4fSDavid du Colombier if(in->perm & PDIR) 657*9a747e4fSDavid du Colombier if((in->mode & MTRUNC) || (in->perm & PAPND) || (fmod & FWRITE)) 658*9a747e4fSDavid du Colombier goto badaccess; 659*9a747e4fSDavid du Colombier /* 660*9a747e4fSDavid du Colombier * do it 661*9a747e4fSDavid du Colombier */ 662*9a747e4fSDavid du Colombier path = qidpathgen(&f->fs->dev); 663*9a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, addr1, Bread|Bimm|Bmod); 664*9a747e4fSDavid du Colombier d1 = getdir(p1, slot1); 665*9a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, d->qid.path)) { 666*9a747e4fSDavid du Colombier if(p1) 667*9a747e4fSDavid du Colombier putbuf(p1); 668*9a747e4fSDavid du Colombier goto phase; 669*9a747e4fSDavid du Colombier } 670*9a747e4fSDavid du Colombier if(d1->mode & DALLOC) { 671*9a747e4fSDavid du Colombier putbuf(p1); 672*9a747e4fSDavid du Colombier goto phase; 673*9a747e4fSDavid du Colombier } 674*9a747e4fSDavid du Colombier 675*9a747e4fSDavid du Colombier strncpy(d1->name, in->name, sizeof(in->name)); 676*9a747e4fSDavid du Colombier /* 677*9a747e4fSDavid du Colombier * bogus argument passing -- see console.c 678*9a747e4fSDavid du Colombier */ 679*9a747e4fSDavid du Colombier if(cp == cons.chan) { 680*9a747e4fSDavid du Colombier d1->uid = cons.uid; 681*9a747e4fSDavid du Colombier d1->gid = cons.gid; 682*9a747e4fSDavid du Colombier } else { 683*9a747e4fSDavid du Colombier d1->uid = f->uid; 684*9a747e4fSDavid du Colombier d1->gid = d->gid; 685*9a747e4fSDavid du Colombier in->perm &= d->mode | ~0666; 686*9a747e4fSDavid du Colombier if(in->perm & PDIR) 687*9a747e4fSDavid du Colombier in->perm &= d->mode | ~0777; 688*9a747e4fSDavid du Colombier } 689*9a747e4fSDavid du Colombier d1->qid.path = path; 690*9a747e4fSDavid du Colombier d1->qid.version = 0; 691*9a747e4fSDavid du Colombier d1->mode = DALLOC | (in->perm & 0777); 692*9a747e4fSDavid du Colombier if(in->perm & PDIR) { 693*9a747e4fSDavid du Colombier d1->mode |= DDIR; 694*9a747e4fSDavid du Colombier d1->qid.path |= QPDIR; 695*9a747e4fSDavid du Colombier } 696*9a747e4fSDavid du Colombier if(in->perm & PAPND) 697*9a747e4fSDavid du Colombier d1->mode |= DAPND; 698*9a747e4fSDavid du Colombier t = 0; 699*9a747e4fSDavid du Colombier if(in->perm & PLOCK) { 700*9a747e4fSDavid du Colombier d1->mode |= DLOCK; 701*9a747e4fSDavid du Colombier t = tlocked(p1, d1); 702*9a747e4fSDavid du Colombier } 703*9a747e4fSDavid du Colombier accessdir(p1, d1, FWRITE); 704*9a747e4fSDavid du Colombier mkqid(&qid, d1, 0); 705*9a747e4fSDavid du Colombier putbuf(p1); 706*9a747e4fSDavid du Colombier accessdir(p, d, FWRITE); 707*9a747e4fSDavid du Colombier 708*9a747e4fSDavid du Colombier /* 709*9a747e4fSDavid du Colombier * do a walk to new directory entry 710*9a747e4fSDavid du Colombier */ 711*9a747e4fSDavid du Colombier w = newwp(); 712*9a747e4fSDavid du Colombier if(!w) { 713*9a747e4fSDavid du Colombier ou->err = Ewalk; 714*9a747e4fSDavid du Colombier goto out; 715*9a747e4fSDavid du Colombier } 716*9a747e4fSDavid du Colombier w->addr = f->addr; 717*9a747e4fSDavid du Colombier w->slot = f->slot; 718*9a747e4fSDavid du Colombier w->up = f->wpath; 719*9a747e4fSDavid du Colombier f->wpath = w; 720*9a747e4fSDavid du Colombier f->qid = qid; 721*9a747e4fSDavid du Colombier f->tlock = t; 722*9a747e4fSDavid du Colombier f->lastra = 0; 723*9a747e4fSDavid du Colombier if(in->mode & MRCLOSE) 724*9a747e4fSDavid du Colombier fmod |= FREMOV; 725*9a747e4fSDavid du Colombier f->open = fmod; 726*9a747e4fSDavid du Colombier f->addr = addr1; 727*9a747e4fSDavid du Colombier f->slot = slot1; 728*9a747e4fSDavid du Colombier if(t) 729*9a747e4fSDavid du Colombier t->file = f; 730*9a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &qid); 731*9a747e4fSDavid du Colombier goto out; 732*9a747e4fSDavid du Colombier 733*9a747e4fSDavid du Colombier badaccess: 734*9a747e4fSDavid du Colombier ou->err = Eaccess; 735*9a747e4fSDavid du Colombier goto out; 736*9a747e4fSDavid du Colombier 737*9a747e4fSDavid du Colombier phase: 738*9a747e4fSDavid du Colombier ou->err = Ephase; 739*9a747e4fSDavid du Colombier 740*9a747e4fSDavid du Colombier out: 741*9a747e4fSDavid du Colombier if(p) 742*9a747e4fSDavid du Colombier putbuf(p); 743*9a747e4fSDavid du Colombier if(f) 744*9a747e4fSDavid du Colombier qunlock(f); 745*9a747e4fSDavid du Colombier ou->fid = in->fid; 746*9a747e4fSDavid du Colombier } 747*9a747e4fSDavid du Colombier 748*9a747e4fSDavid du Colombier void 749*9a747e4fSDavid du Colombier f_read(Chan *cp, Oldfcall *in, Oldfcall *ou) 750*9a747e4fSDavid du Colombier { 751*9a747e4fSDavid du Colombier Iobuf *p, *p1; 752*9a747e4fSDavid du Colombier File *f; 753*9a747e4fSDavid du Colombier Dentry *d, *d1; 754*9a747e4fSDavid du Colombier Tlock *t; 755*9a747e4fSDavid du Colombier long addr, offset, tim; 756*9a747e4fSDavid du Colombier int nread, count, n, o, slot; 757*9a747e4fSDavid du Colombier 758*9a747e4fSDavid du Colombier if(CHAT(cp)) { 759*9a747e4fSDavid du Colombier print("c_read %d\n", cp->chan); 760*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 761*9a747e4fSDavid du Colombier print(" offset = %ld\n", in->offset); 762*9a747e4fSDavid du Colombier print(" count = %ld\n", in->count); 763*9a747e4fSDavid du Colombier } 764*9a747e4fSDavid du Colombier 765*9a747e4fSDavid du Colombier p = 0; 766*9a747e4fSDavid du Colombier count = in->count; 767*9a747e4fSDavid du Colombier offset = in->offset; 768*9a747e4fSDavid du Colombier nread = 0; 769*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 770*9a747e4fSDavid du Colombier if(!f) { 771*9a747e4fSDavid du Colombier ou->err = Efid; 772*9a747e4fSDavid du Colombier goto out; 773*9a747e4fSDavid du Colombier } 774*9a747e4fSDavid du Colombier if(!(f->open & FREAD)) { 775*9a747e4fSDavid du Colombier ou->err = Eopen; 776*9a747e4fSDavid du Colombier goto out; 777*9a747e4fSDavid du Colombier } 778*9a747e4fSDavid du Colombier if(count < 0 || count > MAXDAT) { 779*9a747e4fSDavid du Colombier ou->err = Ecount; 780*9a747e4fSDavid du Colombier goto out; 781*9a747e4fSDavid du Colombier } 782*9a747e4fSDavid du Colombier if(offset < 0) { 783*9a747e4fSDavid du Colombier ou->err = Eoffset; 784*9a747e4fSDavid du Colombier goto out; 785*9a747e4fSDavid du Colombier } 786*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 787*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 788*9a747e4fSDavid du Colombier if(!d || !(d->mode & DALLOC)) { 789*9a747e4fSDavid du Colombier ou->err = Ealloc; 790*9a747e4fSDavid du Colombier goto out; 791*9a747e4fSDavid du Colombier } 792*9a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d)) 793*9a747e4fSDavid du Colombier goto out; 794*9a747e4fSDavid du Colombier if(t = f->tlock) { 795*9a747e4fSDavid du Colombier tim = time(0); 796*9a747e4fSDavid du Colombier if(t->time < tim || t->file != f) { 797*9a747e4fSDavid du Colombier ou->err = Ebroken; 798*9a747e4fSDavid du Colombier goto out; 799*9a747e4fSDavid du Colombier } 800*9a747e4fSDavid du Colombier /* renew the lock */ 801*9a747e4fSDavid du Colombier t->time = tim + TLOCK; 802*9a747e4fSDavid du Colombier } 803*9a747e4fSDavid du Colombier accessdir(p, d, FREAD); 804*9a747e4fSDavid du Colombier if(d->mode & DDIR) { 805*9a747e4fSDavid du Colombier addr = 0; 806*9a747e4fSDavid du Colombier goto dread; 807*9a747e4fSDavid du Colombier } 808*9a747e4fSDavid du Colombier if(offset+count > d->size) 809*9a747e4fSDavid du Colombier count = d->size - offset; 810*9a747e4fSDavid du Colombier while(count > 0) { 811*9a747e4fSDavid du Colombier addr = offset / BUFSIZE; 812*9a747e4fSDavid du Colombier if(addr == f->lastra+1) 813*9a747e4fSDavid du Colombier dbufread(p, d, addr+1); 814*9a747e4fSDavid du Colombier f->lastra = addr; 815*9a747e4fSDavid du Colombier o = offset % BUFSIZE; 816*9a747e4fSDavid du Colombier n = BUFSIZE - o; 817*9a747e4fSDavid du Colombier if(n > count) 818*9a747e4fSDavid du Colombier n = count; 819*9a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0); 820*9a747e4fSDavid du Colombier if(p1) { 821*9a747e4fSDavid du Colombier if(checktag(p1, Tfile, QPNONE)) { 822*9a747e4fSDavid du Colombier ou->err = Ephase; 823*9a747e4fSDavid du Colombier putbuf(p1); 824*9a747e4fSDavid du Colombier goto out; 825*9a747e4fSDavid du Colombier } 826*9a747e4fSDavid du Colombier memmove(ou->data+nread, p1->iobuf+o, n); 827*9a747e4fSDavid du Colombier putbuf(p1); 828*9a747e4fSDavid du Colombier } else 829*9a747e4fSDavid du Colombier memset(ou->data+nread, 0, n); 830*9a747e4fSDavid du Colombier count -= n; 831*9a747e4fSDavid du Colombier nread += n; 832*9a747e4fSDavid du Colombier offset += n; 833*9a747e4fSDavid du Colombier } 834*9a747e4fSDavid du Colombier goto out; 835*9a747e4fSDavid du Colombier 836*9a747e4fSDavid du Colombier dread: 837*9a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0); 838*9a747e4fSDavid du Colombier if(!p1) 839*9a747e4fSDavid du Colombier goto out; 840*9a747e4fSDavid du Colombier if(checktag(p1, Tdir, QPNONE)) { 841*9a747e4fSDavid du Colombier ou->err = Ephase; 842*9a747e4fSDavid du Colombier putbuf(p1); 843*9a747e4fSDavid du Colombier goto out; 844*9a747e4fSDavid du Colombier } 845*9a747e4fSDavid du Colombier n = DIRREC; 846*9a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) { 847*9a747e4fSDavid du Colombier d1 = getdir(p1, slot); 848*9a747e4fSDavid du Colombier if(!(d1->mode & DALLOC)) 849*9a747e4fSDavid du Colombier continue; 850*9a747e4fSDavid du Colombier if(offset >= n) { 851*9a747e4fSDavid du Colombier offset -= n; 852*9a747e4fSDavid du Colombier continue; 853*9a747e4fSDavid du Colombier } 854*9a747e4fSDavid du Colombier if(count < n) { 855*9a747e4fSDavid du Colombier putbuf(p1); 856*9a747e4fSDavid du Colombier goto out; 857*9a747e4fSDavid du Colombier } 858*9a747e4fSDavid du Colombier if(convD2M9p1(d1, ou->data+nread) != n) 859*9a747e4fSDavid du Colombier print("dirread convD2M\n"); 860*9a747e4fSDavid du Colombier nread += n; 861*9a747e4fSDavid du Colombier count -= n; 862*9a747e4fSDavid du Colombier } 863*9a747e4fSDavid du Colombier putbuf(p1); 864*9a747e4fSDavid du Colombier addr++; 865*9a747e4fSDavid du Colombier goto dread; 866*9a747e4fSDavid du Colombier 867*9a747e4fSDavid du Colombier out: 868*9a747e4fSDavid du Colombier count = in->count - nread; 869*9a747e4fSDavid du Colombier if(count > 0) 870*9a747e4fSDavid du Colombier memset(ou->data+nread, 0, count); 871*9a747e4fSDavid du Colombier if(p) 872*9a747e4fSDavid du Colombier putbuf(p); 873*9a747e4fSDavid du Colombier if(f) 874*9a747e4fSDavid du Colombier qunlock(f); 875*9a747e4fSDavid du Colombier ou->fid = in->fid; 876*9a747e4fSDavid du Colombier ou->count = nread; 877*9a747e4fSDavid du Colombier if(CHAT(cp)) 878*9a747e4fSDavid du Colombier print(" nread = %d\n", nread); 879*9a747e4fSDavid du Colombier } 880*9a747e4fSDavid du Colombier 881*9a747e4fSDavid du Colombier void 882*9a747e4fSDavid du Colombier f_write(Chan *cp, Oldfcall *in, Oldfcall *ou) 883*9a747e4fSDavid du Colombier { 884*9a747e4fSDavid du Colombier Iobuf *p, *p1; 885*9a747e4fSDavid du Colombier Dentry *d; 886*9a747e4fSDavid du Colombier File *f; 887*9a747e4fSDavid du Colombier Tlock *t; 888*9a747e4fSDavid du Colombier long offset, addr, tim; 889*9a747e4fSDavid du Colombier int count, nwrite, o, n; 890*9a747e4fSDavid du Colombier 891*9a747e4fSDavid du Colombier if(CHAT(cp)) { 892*9a747e4fSDavid du Colombier print("c_write %d\n", cp->chan); 893*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 894*9a747e4fSDavid du Colombier print(" offset = %ld\n", in->offset); 895*9a747e4fSDavid du Colombier print(" count = %ld\n", in->count); 896*9a747e4fSDavid du Colombier } 897*9a747e4fSDavid du Colombier 898*9a747e4fSDavid du Colombier offset = in->offset; 899*9a747e4fSDavid du Colombier count = in->count; 900*9a747e4fSDavid du Colombier nwrite = 0; 901*9a747e4fSDavid du Colombier p = 0; 902*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 903*9a747e4fSDavid du Colombier if(!f) { 904*9a747e4fSDavid du Colombier ou->err = Efid; 905*9a747e4fSDavid du Colombier goto out; 906*9a747e4fSDavid du Colombier } 907*9a747e4fSDavid du Colombier if(!(f->open & FWRITE)) { 908*9a747e4fSDavid du Colombier ou->err = Eopen; 909*9a747e4fSDavid du Colombier goto out; 910*9a747e4fSDavid du Colombier } 911*9a747e4fSDavid du Colombier if(isro(f->fs->dev)) { 912*9a747e4fSDavid du Colombier ou->err = Eronly; 913*9a747e4fSDavid du Colombier goto out; 914*9a747e4fSDavid du Colombier } 915*9a747e4fSDavid du Colombier if(count < 0 || count > MAXDAT) { 916*9a747e4fSDavid du Colombier ou->err = Ecount; 917*9a747e4fSDavid du Colombier goto out; 918*9a747e4fSDavid du Colombier } 919*9a747e4fSDavid du Colombier if(offset < 0) { 920*9a747e4fSDavid du Colombier ou->err = Eoffset; 921*9a747e4fSDavid du Colombier goto out; 922*9a747e4fSDavid du Colombier } 923*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread|Bmod); 924*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 925*9a747e4fSDavid du Colombier if(!d || !(d->mode & DALLOC)) { 926*9a747e4fSDavid du Colombier ou->err = Ealloc; 927*9a747e4fSDavid du Colombier goto out; 928*9a747e4fSDavid du Colombier } 929*9a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d)) 930*9a747e4fSDavid du Colombier goto out; 931*9a747e4fSDavid du Colombier if(t = f->tlock) { 932*9a747e4fSDavid du Colombier tim = time(0); 933*9a747e4fSDavid du Colombier if(t->time < tim || t->file != f) { 934*9a747e4fSDavid du Colombier ou->err = Ebroken; 935*9a747e4fSDavid du Colombier goto out; 936*9a747e4fSDavid du Colombier } 937*9a747e4fSDavid du Colombier /* renew the lock */ 938*9a747e4fSDavid du Colombier t->time = tim + TLOCK; 939*9a747e4fSDavid du Colombier } 940*9a747e4fSDavid du Colombier accessdir(p, d, FWRITE); 941*9a747e4fSDavid du Colombier if(d->mode & DAPND) 942*9a747e4fSDavid du Colombier offset = d->size; 943*9a747e4fSDavid du Colombier if(offset+count > d->size) 944*9a747e4fSDavid du Colombier d->size = offset+count; 945*9a747e4fSDavid du Colombier while(count > 0) { 946*9a747e4fSDavid du Colombier addr = offset / BUFSIZE; 947*9a747e4fSDavid du Colombier o = offset % BUFSIZE; 948*9a747e4fSDavid du Colombier n = BUFSIZE - o; 949*9a747e4fSDavid du Colombier if(n > count) 950*9a747e4fSDavid du Colombier n = count; 951*9a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, Tfile); 952*9a747e4fSDavid du Colombier if(p1 == 0) { 953*9a747e4fSDavid du Colombier ou->err = Efull; 954*9a747e4fSDavid du Colombier goto out; 955*9a747e4fSDavid du Colombier } 956*9a747e4fSDavid du Colombier if(checktag(p1, Tfile, d->qid.path)) { 957*9a747e4fSDavid du Colombier putbuf(p1); 958*9a747e4fSDavid du Colombier ou->err = Ephase; 959*9a747e4fSDavid du Colombier goto out; 960*9a747e4fSDavid du Colombier } 961*9a747e4fSDavid du Colombier memmove(p1->iobuf+o, in->data+nwrite, n); 962*9a747e4fSDavid du Colombier p1->flags |= Bmod; 963*9a747e4fSDavid du Colombier putbuf(p1); 964*9a747e4fSDavid du Colombier count -= n; 965*9a747e4fSDavid du Colombier nwrite += n; 966*9a747e4fSDavid du Colombier offset += n; 967*9a747e4fSDavid du Colombier } 968*9a747e4fSDavid du Colombier if(CHAT(cp)) 969*9a747e4fSDavid du Colombier print(" nwrite = %d\n", nwrite); 970*9a747e4fSDavid du Colombier 971*9a747e4fSDavid du Colombier out: 972*9a747e4fSDavid du Colombier if(p) 973*9a747e4fSDavid du Colombier putbuf(p); 974*9a747e4fSDavid du Colombier if(f) 975*9a747e4fSDavid du Colombier qunlock(f); 976*9a747e4fSDavid du Colombier ou->fid = in->fid; 977*9a747e4fSDavid du Colombier ou->count = nwrite; 978*9a747e4fSDavid du Colombier } 979*9a747e4fSDavid du Colombier 980*9a747e4fSDavid du Colombier int 981*9a747e4fSDavid du Colombier doremove(File *f, int iscon) 982*9a747e4fSDavid du Colombier { 983*9a747e4fSDavid du Colombier Iobuf *p, *p1; 984*9a747e4fSDavid du Colombier Dentry *d, *d1; 985*9a747e4fSDavid du Colombier long addr; 986*9a747e4fSDavid du Colombier int slot, err; 987*9a747e4fSDavid du Colombier 988*9a747e4fSDavid du Colombier p = 0; 989*9a747e4fSDavid du Colombier p1 = 0; 990*9a747e4fSDavid du Colombier if(isro(f->fs->dev)) { 991*9a747e4fSDavid du Colombier err = Eronly; 992*9a747e4fSDavid du Colombier goto out; 993*9a747e4fSDavid du Colombier } 994*9a747e4fSDavid du Colombier /* 995*9a747e4fSDavid du Colombier * check on parent directory of file to be deleted 996*9a747e4fSDavid du Colombier */ 997*9a747e4fSDavid du Colombier if(f->wpath == 0 || f->wpath->addr == f->addr) { 998*9a747e4fSDavid du Colombier err = Ephase; 999*9a747e4fSDavid du Colombier goto out; 1000*9a747e4fSDavid du Colombier } 1001*9a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, f->wpath->addr, Bread); 1002*9a747e4fSDavid du Colombier d1 = getdir(p1, f->wpath->slot); 1003*9a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { 1004*9a747e4fSDavid du Colombier err = Ephase; 1005*9a747e4fSDavid du Colombier goto out; 1006*9a747e4fSDavid du Colombier } 1007*9a747e4fSDavid du Colombier if(!iscon && iaccess(f, d1, DWRITE)) { 1008*9a747e4fSDavid du Colombier err = Eaccess; 1009*9a747e4fSDavid du Colombier goto out; 1010*9a747e4fSDavid du Colombier } 1011*9a747e4fSDavid du Colombier accessdir(p1, d1, FWRITE); 1012*9a747e4fSDavid du Colombier putbuf(p1); 1013*9a747e4fSDavid du Colombier p1 = 0; 1014*9a747e4fSDavid du Colombier 1015*9a747e4fSDavid du Colombier /* 1016*9a747e4fSDavid du Colombier * check on file to be deleted 1017*9a747e4fSDavid du Colombier */ 1018*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 1019*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 1020*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 1021*9a747e4fSDavid du Colombier err = Ealloc; 1022*9a747e4fSDavid du Colombier goto out; 1023*9a747e4fSDavid du Colombier } 1024*9a747e4fSDavid du Colombier if(err = mkqidcmp(&f->qid, d)) 1025*9a747e4fSDavid du Colombier goto out; 1026*9a747e4fSDavid du Colombier 1027*9a747e4fSDavid du Colombier /* 1028*9a747e4fSDavid du Colombier * if deleting a directory, make sure it is empty 1029*9a747e4fSDavid du Colombier */ 1030*9a747e4fSDavid du Colombier if((d->mode & DDIR)) 1031*9a747e4fSDavid du Colombier for(addr=0;; addr++) { 1032*9a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0); 1033*9a747e4fSDavid du Colombier if(!p1) 1034*9a747e4fSDavid du Colombier break; 1035*9a747e4fSDavid du Colombier if(checktag(p1, Tdir, d->qid.path)) { 1036*9a747e4fSDavid du Colombier err = Ephase; 1037*9a747e4fSDavid du Colombier goto out; 1038*9a747e4fSDavid du Colombier } 1039*9a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) { 1040*9a747e4fSDavid du Colombier d1 = getdir(p1, slot); 1041*9a747e4fSDavid du Colombier if(!(d1->mode & DALLOC)) 1042*9a747e4fSDavid du Colombier continue; 1043*9a747e4fSDavid du Colombier err = Eempty; 1044*9a747e4fSDavid du Colombier goto out; 1045*9a747e4fSDavid du Colombier } 1046*9a747e4fSDavid du Colombier putbuf(p1); 1047*9a747e4fSDavid du Colombier } 1048*9a747e4fSDavid du Colombier 1049*9a747e4fSDavid du Colombier /* 1050*9a747e4fSDavid du Colombier * do it 1051*9a747e4fSDavid du Colombier */ 1052*9a747e4fSDavid du Colombier dtrunc(p, d); 1053*9a747e4fSDavid du Colombier memset(d, 0, sizeof(Dentry)); 1054*9a747e4fSDavid du Colombier settag(p, Tdir, QPNONE); 1055*9a747e4fSDavid du Colombier 1056*9a747e4fSDavid du Colombier out: 1057*9a747e4fSDavid du Colombier if(p1) 1058*9a747e4fSDavid du Colombier putbuf(p1); 1059*9a747e4fSDavid du Colombier if(p) 1060*9a747e4fSDavid du Colombier putbuf(p); 1061*9a747e4fSDavid du Colombier return err; 1062*9a747e4fSDavid du Colombier } 1063*9a747e4fSDavid du Colombier 1064*9a747e4fSDavid du Colombier void 1065*9a747e4fSDavid du Colombier f_remove(Chan *cp, Oldfcall *in, Oldfcall *ou) 1066*9a747e4fSDavid du Colombier { 1067*9a747e4fSDavid du Colombier File *f; 1068*9a747e4fSDavid du Colombier 1069*9a747e4fSDavid du Colombier if(CHAT(cp)) { 1070*9a747e4fSDavid du Colombier print("c_remove %d\n", cp->chan); 1071*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 1072*9a747e4fSDavid du Colombier } 1073*9a747e4fSDavid du Colombier 1074*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 1075*9a747e4fSDavid du Colombier if(!f) { 1076*9a747e4fSDavid du Colombier ou->err = Efid; 1077*9a747e4fSDavid du Colombier goto out; 1078*9a747e4fSDavid du Colombier } 1079*9a747e4fSDavid du Colombier ou->err = doremove(f, cp==cons.chan); 1080*9a747e4fSDavid du Colombier 1081*9a747e4fSDavid du Colombier out: 1082*9a747e4fSDavid du Colombier ou->fid = in->fid; 1083*9a747e4fSDavid du Colombier if(f) 1084*9a747e4fSDavid du Colombier qunlock(f); 1085*9a747e4fSDavid du Colombier } 1086*9a747e4fSDavid du Colombier 1087*9a747e4fSDavid du Colombier void 1088*9a747e4fSDavid du Colombier f_stat(Chan *cp, Oldfcall *in, Oldfcall *ou) 1089*9a747e4fSDavid du Colombier { 1090*9a747e4fSDavid du Colombier Iobuf *p; 1091*9a747e4fSDavid du Colombier Dentry *d; 1092*9a747e4fSDavid du Colombier File *f; 1093*9a747e4fSDavid du Colombier 1094*9a747e4fSDavid du Colombier if(CHAT(cp)) { 1095*9a747e4fSDavid du Colombier print("c_stat %d\n", cp->chan); 1096*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 1097*9a747e4fSDavid du Colombier } 1098*9a747e4fSDavid du Colombier 1099*9a747e4fSDavid du Colombier p = 0; 1100*9a747e4fSDavid du Colombier memset(ou->stat, 0, sizeof(ou->stat)); 1101*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 1102*9a747e4fSDavid du Colombier if(!f) { 1103*9a747e4fSDavid du Colombier ou->err = Efid; 1104*9a747e4fSDavid du Colombier goto out; 1105*9a747e4fSDavid du Colombier } 1106*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 1107*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 1108*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 1109*9a747e4fSDavid du Colombier ou->err = Ealloc; 1110*9a747e4fSDavid du Colombier goto out; 1111*9a747e4fSDavid du Colombier } 1112*9a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d)) 1113*9a747e4fSDavid du Colombier goto out; 1114*9a747e4fSDavid du Colombier if(d->qid.path == QPROOT) /* stat of root gives time */ 1115*9a747e4fSDavid du Colombier d->atime = time(0); 1116*9a747e4fSDavid du Colombier if(convD2M9p1(d, ou->stat) != DIRREC) 1117*9a747e4fSDavid du Colombier print("stat convD2M\n"); 1118*9a747e4fSDavid du Colombier 1119*9a747e4fSDavid du Colombier out: 1120*9a747e4fSDavid du Colombier if(p) 1121*9a747e4fSDavid du Colombier putbuf(p); 1122*9a747e4fSDavid du Colombier if(f) 1123*9a747e4fSDavid du Colombier qunlock(f); 1124*9a747e4fSDavid du Colombier ou->fid = in->fid; 1125*9a747e4fSDavid du Colombier } 1126*9a747e4fSDavid du Colombier 1127*9a747e4fSDavid du Colombier void 1128*9a747e4fSDavid du Colombier f_wstat(Chan *cp, Oldfcall *in, Oldfcall *ou) 1129*9a747e4fSDavid du Colombier { 1130*9a747e4fSDavid du Colombier Iobuf *p, *p1; 1131*9a747e4fSDavid du Colombier Dentry *d, *d1, xd; 1132*9a747e4fSDavid du Colombier File *f; 1133*9a747e4fSDavid du Colombier int slot; 1134*9a747e4fSDavid du Colombier long addr; 1135*9a747e4fSDavid du Colombier 1136*9a747e4fSDavid du Colombier if(CHAT(cp)) { 1137*9a747e4fSDavid du Colombier print("c_wstat %d\n", cp->chan); 1138*9a747e4fSDavid du Colombier print(" fid = %d\n", in->fid); 1139*9a747e4fSDavid du Colombier } 1140*9a747e4fSDavid du Colombier 1141*9a747e4fSDavid du Colombier p = 0; 1142*9a747e4fSDavid du Colombier p1 = 0; 1143*9a747e4fSDavid du Colombier d1 = 0; 1144*9a747e4fSDavid du Colombier f = filep(cp, in->fid, 0); 1145*9a747e4fSDavid du Colombier if(!f) { 1146*9a747e4fSDavid du Colombier ou->err = Efid; 1147*9a747e4fSDavid du Colombier goto out; 1148*9a747e4fSDavid du Colombier } 1149*9a747e4fSDavid du Colombier if(isro(f->fs->dev)) { 1150*9a747e4fSDavid du Colombier ou->err = Eronly; 1151*9a747e4fSDavid du Colombier goto out; 1152*9a747e4fSDavid du Colombier } 1153*9a747e4fSDavid du Colombier 1154*9a747e4fSDavid du Colombier /* 1155*9a747e4fSDavid du Colombier * first get parent 1156*9a747e4fSDavid du Colombier */ 1157*9a747e4fSDavid du Colombier if(f->wpath) { 1158*9a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, f->wpath->addr, Bread); 1159*9a747e4fSDavid du Colombier d1 = getdir(p1, f->wpath->slot); 1160*9a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { 1161*9a747e4fSDavid du Colombier ou->err = Ephase; 1162*9a747e4fSDavid du Colombier goto out; 1163*9a747e4fSDavid du Colombier } 1164*9a747e4fSDavid du Colombier } 1165*9a747e4fSDavid du Colombier 1166*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 1167*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 1168*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 1169*9a747e4fSDavid du Colombier ou->err = Ealloc; 1170*9a747e4fSDavid du Colombier goto out; 1171*9a747e4fSDavid du Colombier } 1172*9a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d)) 1173*9a747e4fSDavid du Colombier goto out; 1174*9a747e4fSDavid du Colombier 1175*9a747e4fSDavid du Colombier convM2D9p1(in->stat, &xd); 1176*9a747e4fSDavid du Colombier if(CHAT(cp)) { 1177*9a747e4fSDavid du Colombier print(" d.name = %s\n", xd.name); 1178*9a747e4fSDavid du Colombier print(" d.uid = %d\n", xd.uid); 1179*9a747e4fSDavid du Colombier print(" d.gid = %d\n", xd.gid); 1180*9a747e4fSDavid du Colombier print(" d.mode = %.4x\n", xd.mode); 1181*9a747e4fSDavid du Colombier } 1182*9a747e4fSDavid du Colombier 1183*9a747e4fSDavid du Colombier /* 1184*9a747e4fSDavid du Colombier * if chown, 1185*9a747e4fSDavid du Colombier * must be god 1186*9a747e4fSDavid du Colombier */ 1187*9a747e4fSDavid du Colombier while(xd.uid != d->uid) { 1188*9a747e4fSDavid du Colombier if(wstatallow) /* set to allow chown during boot */ 1189*9a747e4fSDavid du Colombier break; 1190*9a747e4fSDavid du Colombier ou->err = Enotu; 1191*9a747e4fSDavid du Colombier goto out; 1192*9a747e4fSDavid du Colombier } 1193*9a747e4fSDavid du Colombier 1194*9a747e4fSDavid du Colombier /* 1195*9a747e4fSDavid du Colombier * if chgroup, 1196*9a747e4fSDavid du Colombier * must be either 1197*9a747e4fSDavid du Colombier * a) owner and in new group 1198*9a747e4fSDavid du Colombier * b) leader of both groups 1199*9a747e4fSDavid du Colombier */ 1200*9a747e4fSDavid du Colombier while(xd.gid != d->gid) { 1201*9a747e4fSDavid du Colombier if(wstatallow || writeallow) /* set to allow chgrp during boot */ 1202*9a747e4fSDavid du Colombier break; 1203*9a747e4fSDavid du Colombier if(d->uid == f->uid && ingroup(f->uid, xd.gid)) 1204*9a747e4fSDavid du Colombier break; 1205*9a747e4fSDavid du Colombier if(leadgroup(f->uid, xd.gid)) 1206*9a747e4fSDavid du Colombier if(leadgroup(f->uid, d->gid)) 1207*9a747e4fSDavid du Colombier break; 1208*9a747e4fSDavid du Colombier ou->err = Enotg; 1209*9a747e4fSDavid du Colombier goto out; 1210*9a747e4fSDavid du Colombier } 1211*9a747e4fSDavid du Colombier 1212*9a747e4fSDavid du Colombier /* 1213*9a747e4fSDavid du Colombier * if rename, 1214*9a747e4fSDavid du Colombier * must have write permission in parent 1215*9a747e4fSDavid du Colombier */ 1216*9a747e4fSDavid du Colombier if(xd.name[0] == 0) 1217*9a747e4fSDavid du Colombier strncpy(xd.name, d->name, sizeof(xd.name)); 1218*9a747e4fSDavid du Colombier while(strncmp(d->name, xd.name, sizeof(d->name)) != 0) { 1219*9a747e4fSDavid du Colombier if(checkname(xd.name)) { 1220*9a747e4fSDavid du Colombier ou->err = Ename; 1221*9a747e4fSDavid du Colombier goto out; 1222*9a747e4fSDavid du Colombier } 1223*9a747e4fSDavid du Colombier 1224*9a747e4fSDavid du Colombier if(strcmp(xd.name, ".") == 0 || strcmp(xd.name, "..") == 0) { 1225*9a747e4fSDavid du Colombier ou->err = Ename; 1226*9a747e4fSDavid du Colombier goto out; 1227*9a747e4fSDavid du Colombier } 1228*9a747e4fSDavid du Colombier 1229*9a747e4fSDavid du Colombier /* 1230*9a747e4fSDavid du Colombier * drop entry to prevent lock, then 1231*9a747e4fSDavid du Colombier * check that destination name is unique, 1232*9a747e4fSDavid du Colombier */ 1233*9a747e4fSDavid du Colombier putbuf(p); 1234*9a747e4fSDavid du Colombier for(addr=0;; addr++) { 1235*9a747e4fSDavid du Colombier p = dnodebuf(p1, d1, addr, 0); 1236*9a747e4fSDavid du Colombier if(!p) 1237*9a747e4fSDavid du Colombier break; 1238*9a747e4fSDavid du Colombier if(checktag(p, Tdir, d1->qid.path)) { 1239*9a747e4fSDavid du Colombier putbuf(p); 1240*9a747e4fSDavid du Colombier continue; 1241*9a747e4fSDavid du Colombier } 1242*9a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) { 1243*9a747e4fSDavid du Colombier d = getdir(p, slot); 1244*9a747e4fSDavid du Colombier if(!(d->mode & DALLOC)) 1245*9a747e4fSDavid du Colombier continue; 1246*9a747e4fSDavid du Colombier if(!strncmp(xd.name, d->name, sizeof(xd.name))) { 1247*9a747e4fSDavid du Colombier ou->err = Eexist; 1248*9a747e4fSDavid du Colombier goto out; 1249*9a747e4fSDavid du Colombier } 1250*9a747e4fSDavid du Colombier } 1251*9a747e4fSDavid du Colombier putbuf(p); 1252*9a747e4fSDavid du Colombier } 1253*9a747e4fSDavid du Colombier 1254*9a747e4fSDavid du Colombier /* 1255*9a747e4fSDavid du Colombier * reacquire entry 1256*9a747e4fSDavid du Colombier */ 1257*9a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread); 1258*9a747e4fSDavid du Colombier d = getdir(p, f->slot); 1259*9a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { 1260*9a747e4fSDavid du Colombier ou->err = Ephase; 1261*9a747e4fSDavid du Colombier goto out; 1262*9a747e4fSDavid du Colombier } 1263*9a747e4fSDavid du Colombier 1264*9a747e4fSDavid du Colombier if(wstatallow || writeallow) /* set to allow rename during boot */ 1265*9a747e4fSDavid du Colombier break; 1266*9a747e4fSDavid du Colombier if(!d1 || iaccess(f, d1, DWRITE)) { 1267*9a747e4fSDavid du Colombier ou->err = Eaccess; 1268*9a747e4fSDavid du Colombier goto out; 1269*9a747e4fSDavid du Colombier } 1270*9a747e4fSDavid du Colombier break; 1271*9a747e4fSDavid du Colombier } 1272*9a747e4fSDavid du Colombier 1273*9a747e4fSDavid du Colombier /* 1274*9a747e4fSDavid du Colombier * if mode/time, either 1275*9a747e4fSDavid du Colombier * a) owner 1276*9a747e4fSDavid du Colombier * b) leader of either group 1277*9a747e4fSDavid du Colombier */ 1278*9a747e4fSDavid du Colombier while(d->mtime != xd.mtime || 1279*9a747e4fSDavid du Colombier ((d->mode^xd.mode) & (DAPND|DLOCK|0777))) { 1280*9a747e4fSDavid du Colombier if(wstatallow) /* set to allow chmod during boot */ 1281*9a747e4fSDavid du Colombier break; 1282*9a747e4fSDavid du Colombier if(d->uid == f->uid) 1283*9a747e4fSDavid du Colombier break; 1284*9a747e4fSDavid du Colombier if(leadgroup(f->uid, xd.gid)) 1285*9a747e4fSDavid du Colombier break; 1286*9a747e4fSDavid du Colombier if(leadgroup(f->uid, d->gid)) 1287*9a747e4fSDavid du Colombier break; 1288*9a747e4fSDavid du Colombier ou->err = Enotu; 1289*9a747e4fSDavid du Colombier goto out; 1290*9a747e4fSDavid du Colombier } 1291*9a747e4fSDavid du Colombier d->mtime = xd.mtime; 1292*9a747e4fSDavid du Colombier d->uid = xd.uid; 1293*9a747e4fSDavid du Colombier d->gid = xd.gid; 1294*9a747e4fSDavid du Colombier d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR)); 1295*9a747e4fSDavid du Colombier 1296*9a747e4fSDavid du Colombier strncpy(d->name, xd.name, sizeof(d->name)); 1297*9a747e4fSDavid du Colombier if(wstatallow) { 1298*9a747e4fSDavid du Colombier p->flags |= Bmod; 1299*9a747e4fSDavid du Colombier if(xd.atime) 1300*9a747e4fSDavid du Colombier d->atime = xd.atime; 1301*9a747e4fSDavid du Colombier if(xd.mtime) 1302*9a747e4fSDavid du Colombier d->mtime = xd.mtime; 1303*9a747e4fSDavid du Colombier } else 1304*9a747e4fSDavid du Colombier accessdir(p, d, FREAD); 1305*9a747e4fSDavid du Colombier 1306*9a747e4fSDavid du Colombier out: 1307*9a747e4fSDavid du Colombier if(p) 1308*9a747e4fSDavid du Colombier putbuf(p); 1309*9a747e4fSDavid du Colombier if(p1) 1310*9a747e4fSDavid du Colombier putbuf(p1); 1311*9a747e4fSDavid du Colombier if(f) 1312*9a747e4fSDavid du Colombier qunlock(f); 1313*9a747e4fSDavid du Colombier ou->fid = in->fid; 1314*9a747e4fSDavid du Colombier } 1315*9a747e4fSDavid du Colombier 1316*9a747e4fSDavid du Colombier void 1317*9a747e4fSDavid du Colombier (*call9p1[MAXSYSCALL])(Chan*, Oldfcall*, Oldfcall*) = 1318*9a747e4fSDavid du Colombier { 1319*9a747e4fSDavid du Colombier [Tnop9p1] f_nop, 1320*9a747e4fSDavid du Colombier [Tosession9p1] f_session, 1321*9a747e4fSDavid du Colombier [Tsession9p1] f_session, 1322*9a747e4fSDavid du Colombier [Tflush9p1] f_flush, 1323*9a747e4fSDavid du Colombier [Toattach9p1] f_attach, 1324*9a747e4fSDavid du Colombier [Tattach9p1] f_attach, 1325*9a747e4fSDavid du Colombier [Tclone9p1] f_clone, 1326*9a747e4fSDavid du Colombier [Twalk9p1] f_walk, 1327*9a747e4fSDavid du Colombier [Topen9p1] f_open, 1328*9a747e4fSDavid du Colombier [Tcreate9p1] f_create, 1329*9a747e4fSDavid du Colombier [Tread9p1] f_read, 1330*9a747e4fSDavid du Colombier [Twrite9p1] f_write, 1331*9a747e4fSDavid du Colombier [Tclunk9p1] f_clunk, 1332*9a747e4fSDavid du Colombier [Tremove9p1] f_remove, 1333*9a747e4fSDavid du Colombier [Tstat9p1] f_stat, 1334*9a747e4fSDavid du Colombier [Twstat9p1] f_wstat, 1335*9a747e4fSDavid du Colombier [Tclwalk9p1] f_clwalk, 1336*9a747e4fSDavid du Colombier }; 1337*9a747e4fSDavid du Colombier 1338*9a747e4fSDavid du Colombier static void 1339*9a747e4fSDavid du Colombier send(Chan *c, uchar *buf, int n) 1340*9a747e4fSDavid du Colombier { 1341*9a747e4fSDavid du Colombier int fd, m; 1342*9a747e4fSDavid du Colombier 1343*9a747e4fSDavid du Colombier fd = c->chan; 1344*9a747e4fSDavid du Colombier m = write(fd, buf, n); 1345*9a747e4fSDavid du Colombier if(m == n) 1346*9a747e4fSDavid du Colombier return; 1347*9a747e4fSDavid du Colombier panic("write failed"); 1348*9a747e4fSDavid du Colombier } 1349*9a747e4fSDavid du Colombier 1350*9a747e4fSDavid du Colombier void 1351*9a747e4fSDavid du Colombier error9p1(Chan *c, uchar *buf) 1352*9a747e4fSDavid du Colombier { 1353*9a747e4fSDavid du Colombier buf[0] = Rnop9p1; 1354*9a747e4fSDavid du Colombier buf[1] = ~0; 1355*9a747e4fSDavid du Colombier buf[2] = ~0; 1356*9a747e4fSDavid du Colombier 1357*9a747e4fSDavid du Colombier send(c, buf, 3); 1358*9a747e4fSDavid du Colombier } 1359*9a747e4fSDavid du Colombier 1360*9a747e4fSDavid du Colombier void 1361*9a747e4fSDavid du Colombier serve9p1(Chan *chan, uchar *ib, int nib) 1362*9a747e4fSDavid du Colombier { 1363*9a747e4fSDavid du Colombier int n, t; 1364*9a747e4fSDavid du Colombier uchar inbuf[MAXMSG+MAXDAT], outbuf[MAXMSG+MAXDAT]; 1365*9a747e4fSDavid du Colombier Oldfcall fi, fo; 1366*9a747e4fSDavid du Colombier 1367*9a747e4fSDavid du Colombier for(;;){ 1368*9a747e4fSDavid du Colombier if(nib){ 1369*9a747e4fSDavid du Colombier memmove(inbuf, ib, nib); 1370*9a747e4fSDavid du Colombier n = nib; 1371*9a747e4fSDavid du Colombier nib = 0; 1372*9a747e4fSDavid du Colombier }else 1373*9a747e4fSDavid du Colombier n = read(chan->chan, inbuf, sizeof inbuf); 1374*9a747e4fSDavid du Colombier if(chat) 1375*9a747e4fSDavid du Colombier print("read msg %d\n", n); 1376*9a747e4fSDavid du Colombier if(n == 0 && (chan == cons.srvchan || chan == cons.chan)) 1377*9a747e4fSDavid du Colombier continue; 1378*9a747e4fSDavid du Colombier if(n <= 0) 1379*9a747e4fSDavid du Colombier return; 1380*9a747e4fSDavid du Colombier if(convM2S9p1(inbuf, &fi, n) != n){ 1381*9a747e4fSDavid du Colombier error9p1(chan, outbuf); 1382*9a747e4fSDavid du Colombier continue; 1383*9a747e4fSDavid du Colombier } 1384*9a747e4fSDavid du Colombier 1385*9a747e4fSDavid du Colombier t = fi.type; 1386*9a747e4fSDavid du Colombier if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) { 1387*9a747e4fSDavid du Colombier print("9p1: bad message type\n"); 1388*9a747e4fSDavid du Colombier error9p1(chan, outbuf); 1389*9a747e4fSDavid du Colombier continue; 1390*9a747e4fSDavid du Colombier } 1391*9a747e4fSDavid du Colombier 1392*9a747e4fSDavid du Colombier if(CHAT(chan)) 1393*9a747e4fSDavid du Colombier print("9p1: fi %O\n", &fi); 1394*9a747e4fSDavid du Colombier 1395*9a747e4fSDavid du Colombier /* 1396*9a747e4fSDavid du Colombier * set up reply message 1397*9a747e4fSDavid du Colombier */ 1398*9a747e4fSDavid du Colombier fo.err = 0; 1399*9a747e4fSDavid du Colombier if(t == Tread9p1) 1400*9a747e4fSDavid du Colombier fo.data = (char*)outbuf + 8; 1401*9a747e4fSDavid du Colombier 1402*9a747e4fSDavid du Colombier /* 1403*9a747e4fSDavid du Colombier * call the file system 1404*9a747e4fSDavid du Colombier */ 1405*9a747e4fSDavid du Colombier cons.work.count++; 1406*9a747e4fSDavid du Colombier cons.rate.count += n; 1407*9a747e4fSDavid du Colombier 1408*9a747e4fSDavid du Colombier /* 1409*9a747e4fSDavid du Colombier * call the file system 1410*9a747e4fSDavid du Colombier */ 1411*9a747e4fSDavid du Colombier rlock(&mainlock); 1412*9a747e4fSDavid du Colombier rlock(&chan->reflock); 1413*9a747e4fSDavid du Colombier 1414*9a747e4fSDavid du Colombier (*call9p1[t])(chan, &fi, &fo); 1415*9a747e4fSDavid du Colombier 1416*9a747e4fSDavid du Colombier runlock(&chan->reflock); 1417*9a747e4fSDavid du Colombier runlock(&mainlock); 1418*9a747e4fSDavid du Colombier 1419*9a747e4fSDavid du Colombier fo.type = t+1; 1420*9a747e4fSDavid du Colombier fo.tag = fi.tag; 1421*9a747e4fSDavid du Colombier 1422*9a747e4fSDavid du Colombier if(chat) 1423*9a747e4fSDavid du Colombier print("9p1: fo %O\n", &fo); 1424*9a747e4fSDavid du Colombier 1425*9a747e4fSDavid du Colombier if(fo.err) { 1426*9a747e4fSDavid du Colombier strcpy(fo.ename, errstring[fo.err]); 1427*9a747e4fSDavid du Colombier if(CHAT(cp)) 1428*9a747e4fSDavid du Colombier print(" error: %s\n", fo.ename); 1429*9a747e4fSDavid du Colombier fo.type = Terror9p1+1; 1430*9a747e4fSDavid du Colombier } 1431*9a747e4fSDavid du Colombier 1432*9a747e4fSDavid du Colombier n = convS2M9p1(&fo, outbuf); 1433*9a747e4fSDavid du Colombier if(n == 0) { 1434*9a747e4fSDavid du Colombier print("9p1: bad S2M conversion\n"); 1435*9a747e4fSDavid du Colombier error9p1(chan, outbuf); 1436*9a747e4fSDavid du Colombier continue; 1437*9a747e4fSDavid du Colombier } 1438*9a747e4fSDavid du Colombier 1439*9a747e4fSDavid du Colombier cons.rate.count += n; 1440*9a747e4fSDavid du Colombier send(chan, outbuf, n); 1441*9a747e4fSDavid du Colombier } 1442*9a747e4fSDavid du Colombier } 1443