## diffname port/chan.c 1990/0227 ## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/chan.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" struct{ Lock; Chan *free; }chanalloc; int incref(Ref *r) { lock(r); r->ref++; unlock(r); return r->ref; } int decref(Ref *r) { lock(r); r->ref--; unlock(r); return r->ref; } void chaninit(void) { int i; Chan *c; chanalloc.free = ialloc(conf.nchan*sizeof(Chan), 0); c = chanalloc.free; for(i=0; ifid = i; c->next = c+1; } c->next = 0; } void chandevreset(void) { int i; for(i=0; inext; c->flag = 0; c->ref = 1; unlock(&chanalloc); c->offset = 0; c->mnt = 0; c->stream = 0; return c; } unlock(&chanalloc); print("no chans\n"); if(u == 0) panic("newchan"); u->p->state = Wakeme; alarm(1000, wakeme, u->p); sched(); goto loop; } void close(Chan *c) { if(decref(c) == 0){ if(!waserror()){ (*devtab[c->type].close)(c); poperror(); } lock(&chanalloc); c->next = chanalloc.free; chanalloc.free = c; unlock(&chanalloc); } } int eqchan(Chan *a, Chan *b, long qmask) { if((a->qid^b->qid) & qmask) return 0; if(a->type != b->type) return 0; if(a->dev != b->dev) return 0; return 1; } /* * omnt is locked. return with nmnt locked. */ Mount* mountsplit(Mount *omnt) { Mount *nmnt; print("mount copy on write\n"); nmnt = newmount(); lock(nmnt); nmnt->term = omnt->term; nmnt->mountid = omnt->mountid; nmnt->next = omnt->next; if(nmnt->next) incref(nmnt); nmnt->c = omnt->c; incref(nmnt->c); omnt->ref--; unlock(omnt); return nmnt; } int mount(Chan *new, Chan *old, int flag) { int i; Mtab *mt, *mz; Mount *mnt, *omnt, *nmnt, *pmnt; Pgrp *pg; int isnew; if(CHDIR & (old->qid^new->qid)) error(0, Emount); if((old->qid&CHDIR)==0 && (flag&MORDER)!=MREPL) error(0, Emount); mz = 0; isnew = 0; pg = u->p->pgrp; lock(pg); if(waserror()){ unlock(pg); nexterror(); } /* * Is old already in mount table? */ mt = pg->mtab; for(i=0; inmtab; i++,mt++){ if(mt->c==0 && mz==0) mz = mt; else if(eqchan(mt->c, old, CHDIR|QPATH)) goto Found; } isnew = 1; if(mz == 0){ if(i == conf.nmtab) error(0, Enomount); mz = &pg->mtab[i]; pg->nmtab++; } mz->mnt = 0; mz->c = old; mt = mz; Found: new->flag = CMOUNT; if(flag & MCREATE) new->flag |= CCREATE; mnt = newmount(); mnt->c = new; switch(flag & MORDER){ /* * These two always go at head of list */ case MBEFORE: if(mt->mnt == 0) error(0, Enotunion); /* fall through */ case MREPL: omnt = mt->mnt; if(omnt) incref(omnt); mnt->next = omnt; mt->mnt = mnt; mnt->term = 1; if((flag&MORDER) == MBEFORE) mnt->term = 0; break; /* * This one never goes at head of list */ case MAFTER: if(mt->mnt == 0) error(0, Enotunion); omnt = mt->mnt; pmnt = 0; while(!omnt->term){ lock(omnt); if(omnt->ref > 1){ omnt = mountsplit(omnt); if(pmnt) pmnt->next = omnt; else mt->mnt = omnt; } unlock(omnt); nmnt = omnt->next; if(nmnt == 0) panic("MAFTER term"); pmnt = omnt; omnt = nmnt; } mnt->next = omnt->next; omnt->next = mnt; mnt->term = 1; omnt->term = 0; break; } incref(new); if(isnew) incref(old); unlock(pg); poperror(); return mnt->mountid; } Chan* clone(Chan *c, Chan *nc) { return (*devtab[c->type].clone)(c, nc); } Chan* domount(Chan *c) { int i; ulong mntid; Mtab *mt; Mount *mnt; Pgrp *pg; Chan *nc, *mc; pg = u->p->pgrp; /* * Is c in in mount table? */ mt = pg->mtab; for(i=0; inmtab; i++,mt++) if(mt->c && eqchan(mt->c, c, CHDIR|QPATH)) goto Found; /* * No; c is unaffected */ return c; /* * Yes; move c through table */ Found: lock(pg); if(!eqchan(mt->c, c, CHDIR|QPATH)){ /* table changed underfoot */ print("domount: changed underfoot?\n"); unlock(pg); return c; } mnt = mt->mnt; mntid = mnt->mountid; mc = mnt->c; incref(mc); unlock(pg); if(waserror()){ close(mc); nexterror(); } nc = clone(mc, 0); close(mc); poperror(); close(c); nc->mnt = mnt; nc->mountid = mntid; return nc; } Chan* walk(Chan *ac, char *name, int domnt) { Mount *mnt; int first = 1; Chan *c = ac; Chan *nc, *mc; Pgrp *pg = u->p->pgrp; /* * name may be empty if the file name is "/", "#c" etc. */ Again: if(name[0] && (*devtab[c->type].walk)(c, name)==0){ if(!(c->flag&CMOUNT)) goto Notfound; mnt = c->mnt; if(mnt == 0) panic("walk"); lock(pg); if(mnt->term){ unlock(pg); goto Notfound; } if(c->mountid != mnt->mountid){ print("walk: changed underfoot?\n"); unlock(pg); goto Notfound; } mnt = mnt->next; mc = mnt->c; incref(mc); unlock(pg); if(waserror()){ close(mc); nexterror(); } if(mnt == 0) panic("walk 1"); nc = clone(mc, 0); close(mc); poperror(); if(!first) close(c); nc->mnt = mnt; c = nc; first = 0; goto Again; } if(name[0]) /* walk succeeded */ c->flag &= ~CMOUNT; if(!first) close(ac); if(domnt) return domount(c); return c; Notfound: if(!first) close(c); return 0; } /* * c is a mounted non-creatable directory. find a creatable one. */ Chan* createdir(Chan *c) { Mount *mnt; Pgrp *pg = u->p->pgrp; Chan *mc, *nc; lock(pg); if(waserror()){ unlock(pg); nexterror(); } mnt = c->mnt; if(c->mountid != mnt->mountid){ print("createdir: changed underfoot?\n"); error(0, Enocreate); } do{ if(mnt->term) error(0, Enocreate); mnt = mnt->next; }while(!(mnt->c->flag&CCREATE)); mc = mnt->c; incref(mc); unlock(pg); if(waserror()){ close(mc); nexterror(); } nc = clone(mc, 0); poperror(); close(c); close(mc); nc->mnt = mnt; return nc; } /* * Turn a name into a channel. * &name[0] is known to be a valid address. It may be a kernel address. */ Chan* namec(char *name, int amode, int omode, ulong perm) { Chan *c, *nc; int t; int mntok; char *elem = u->elem; if(name[0] == 0) error(0, Enonexist); mntok = 1; if(name[0] == '/'){ c = clone(u->slash, 0); /* * Skip leading slashes. */ name = skipslash(name); }else if(name[0] == '#'){ mntok = 0; if(!((ulong)name & KZERO)) validaddr((ulong)(name+1), 2, 0); if(name[1]=='|' || ('A'<=name[1] && name[1]<='Z')) error(0, Enonexist); t = devno(name[1], 1); if(t == -1) error(0, Ebadsharp); name += 2; if(*name == '/'){ name = skipslash(name); elem[0]=0; }else name = nextelem(name, elem); c = (*devtab[t].attach)(elem); }else c = clone(u->dot, 0); if(waserror()){ close(c); nexterror(); } name = nextelem(name, elem); if(mntok) if(!(amode==Amount && elem[0]==0)) /* don't domount on dot or slash */ c = domount(c); /* see case Atodir below */ /* * How to treat the last element of the name depends on the operation. * Therefore do all but the last element by the easy algorithm. */ while(*name){ if((nc=walk(c, elem, mntok)) == 0) error(0, Enonexist); c = nc; name = nextelem(name, elem); } /* * Last element; act according to type of access. */ switch(amode){ case Aaccess: if((nc=walk(c, elem, mntok)) == 0) error(0, Enonexist); c = nc; break; case Atodir: /* * Directories (e.g. for cd) are left before the mount point, * so one may mount on / or . and see the effect. */ if((nc=walk(c, elem, 0)) == 0) error(0, Enonexist); c = nc; if(!(c->qid & CHDIR)) error(0, Enotdir); break; case Aopen: if((nc=walk(c, elem, mntok)) == 0) error(0, Enonexist); c = nc; Open: c = (*devtab[c->type].open)(c, omode); break; case Amount: /* * When mounting on an already mounted upon directory, one wants * the second mount to be attached to the original directory, not * the replacement. */ if((nc=walk(c, elem, 0)) == 0) error(0, Enonexist); c = nc; break; case Acreate: if((nc=walk(c, elem, 1)) != 0){ c = nc; omode |= OTRUNC; goto Open; } if((c->flag&(CMOUNT|CCREATE)) == CMOUNT) c = createdir(c); (*devtab[c->type].create)(c, elem, omode, perm); break; default: panic("unknown namec access %d\n", amode); } poperror(); return c; } /* * name[0] is addressable. */ char* skipslash(char *name) { while(*name == '/'){ if(((ulong)name&KZERO)==0 && (((ulong)name+1)&(BY2PG-1))==0) validaddr((ulong)name+1, 1, 0); name++; } return name; } char isfrog[]={ /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, [' '] 1, ['/'] 1, [0x7f] 1, }; /* * name[0] should not be a slash. * Advance name to next element in path, copying current element into elem. * Return pointer to next element, skipping slashes. * &name[0] is known to be a valid address. */ char* nextelem(char *name, char *elem) { int i, user, c; char *end, *e; if(*name == '/') error(0, Efilename); end = vmemchr(name, 0, NAMELEN); if(end == 0){ end = vmemchr(name, '/', NAMELEN); if(end == 0) error(0, Efilename); }else{ e = memchr(name, '/', end-name); if(e) end = e; } while(name < end){ c = *name++; if((c&0x80) || isfrog[c]) error(0, Ebadchar); *elem++ = c; } *elem = 0; return skipslash(name); } void isdir(Chan *c) { if(c->qid & CHDIR) return; error(0, Enotdir); } . ## diffname port/chan.c 1990/0303 ## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/chan.c /n/bootesdump/1990/0303/sys/src/9/mips/chan.c 80a c->mchan = 0; c->mqid = 0; . ## diffname port/chan.c 1990/0321 ## diff -e /n/bootesdump/1990/0303/sys/src/9/mips/chan.c /n/bootesdump/1990/0321/sys/src/9/mips/chan.c 394c pprint("createdir: changed underfoot?\n"); . 355a nc->mountid = mnt->mountid; . 336c pprint("walk: changed underfoot?\n"); . 289c pprint("domount: changed underfoot?\n"); . 248a } if(islast) pg->nmtab++; . 247c if(mz){ mz->c = old; . 185d 182c islast++; . 177d 175a } . 174c else if(eqchan(mt->c, old, CHDIR|QPATH)){ mz = 0; . 163a if(mnt){ mnt->c = 0; /* caller will close new */ closemount(mnt); } . 160c islast = 0; mnt = 0; . 152c int islast; . ## diffname port/chan.c 1990/0513 ## diff -e /n/bootesdump/1990/0321/sys/src/9/mips/chan.c /n/bootesdump/1990/0513/sys/src/9/mips/chan.c 494a } . 493c if((nc=walk(c, elem, mntok)) == 0){ print("%d pc %lux\n", u->nerrlab, u->errlab[u->nerrlab-1].pc); . ## diffname port/chan.c 1990/0515 ## diff -e /n/bootesdump/1990/0513/sys/src/9/mips/chan.c /n/bootesdump/1990/0515/sys/src/9/mips/chan.c 496d 493,494c if((nc=walk(c, elem, mntok)) == 0) . ## diffname port/chan.c 1990/0603 ## diff -e /n/bootesdump/1990/0515/sys/src/9/mips/chan.c /n/bootesdump/1990/0603/sys/src/9/mips/chan.c 217a else mnt->term = 1; . 215d 210,213c mnt->next = mt->mnt; . 137c incref(nmnt->next); . ## diffname port/chan.c 1990/0617 ## diff -e /n/bootesdump/1990/0603/sys/src/9/mips/chan.c /n/bootesdump/1990/0617/sys/src/9/mips/chan.c 130d ## diffname port/chan.c 1990/0707 ## diff -e /n/bootesdump/1990/0617/sys/src/9/mips/chan.c /n/bootesdump/1990/0707/sys/src/9/mips/chan.c 74a c->type = 0; /* if closed before changed, this calls rooterror, a nop */ . ## diffname port/chan.c 1990/08141 ## diff -e /n/bootesdump/1990/0707/sys/src/9/mips/chan.c /n/bootesdump/1990/08141/sys/src/9/mips/chan.c 535a if(omode & OCEXEC) c->flag |= CCEXEC; . 513a if(omode & OCEXEC) c->flag |= CCEXEC; . 450c if(name[1]=='|' || name[1]=='M') . ## diffname port/chan.c 1990/0820 ## diff -e /n/bootesdump/1990/08141/sys/src/9/mips/chan.c /n/bootesdump/1990/0820/sys/src/9/mips/chan.c 558a } if(*name == '.'){ if(((ulong)name&KZERO)==0 && (((ulong)name+1)&(BY2PG-1))==0) validaddr((ulong)name+1, 1, 0); if(name[1]==0 || name[1]=='/'){ name++; goto Again; } . 554a Again: . 529a if(isdot) error(0, Eisdir); . 509,511c if(isdot) c = domount(c); else{ if((nc=walk(c, elem, mntok)) == 0) error(0, Enonexist); c = nc; } . 491,493c if(isdot) c = domount(c); else{ if((nc=walk(c, elem, mntok)) == 0) error(0, Enonexist); c = nc; } . 484a . 471,472c if(mntok && !isdot) if(!(amode==Amount && elem[0]==0)) /* don't domount on slash */ . 463a name = skipslash(name); /* eat leading ./ */ if(*name == 0) isdot = 1; } . 462c }else{ . 439a isdot = 0; . 434c int mntok, isdot; . 343c pprint("walk: changed underfoot? '%s'\n", name); . ## diffname port/chan.c 1990/0821 ## diff -e /n/bootesdump/1990/0820/sys/src/9/mips/chan.c /n/bootesdump/1990/0821/sys/src/9/mips/chan.c 615c end = memchr(name, '/', NAMELEN); . 613c end = memchr(name, 0, NAMELEN); . 603d 578,585d 576a if(*name=='.' && (name[1]==0 || name[1]=='/')){ name++; goto Again; . 573,575c while(*name == '/') . 449,450d 438a /* * Make sure all of name is o.k. first byte is validated * externally so if it's a kernel address we know it's o.k. */ if(!((ulong)name & KZERO)){ p = name; t = BY2PG-((ulong)p&(BY2PG-1)); while(vmemchr(p, 0, t) == 0){ p += t; t = BY2PG; } } elem = u->elem; . 435c char *p; char *elem; . ## diffname port/chan.c 1990/0907 ## diff -e /n/bootesdump/1990/0821/sys/src/9/mips/chan.c /n/bootesdump/1990/0907/sys/src/9/mips/chan.c 103a c->flag = CFREE; . 98a if(c->flag & CFREE) panic("close"); . ## diffname port/chan.c 1990/0914 ## diff -e /n/bootesdump/1990/0907/sys/src/9/mips/chan.c /n/bootesdump/1990/0914/sys/src/9/mips/chan.c 544a saveregisters(); /* else error() in open has wrong value of c saved */ . 427a void saveregisters(void) { } . 378,379c . 374a if(domnt){ if(waserror()){ print("domount error\n"); if(!first) close(c); return 0; } c = domount(c); poperror(); } . ## diffname port/chan.c 1990/09141 ## diff -e /n/bootesdump/1990/0914/sys/src/9/mips/chan.c /n/bootesdump/1990/09141/sys/src/9/mips/chan.c 377d ## diffname port/chan.c 1990/1009 ## diff -e /n/bootesdump/1990/09141/sys/src/9/mips/chan.c /n/bootesdump/1990/1009/sys/src/9/mips/chan.c 482c if(name[1]=='M') . ## diffname port/chan.c 1990/1104 ## diff -e /n/bootesdump/1990/1009/sys/src/9/mips/chan.c /n/bootesdump/1990/1104/sys/src/9/mips/chan.c 29c return x; . 27c x = --r->ref; . 25a int x; . 20c return x; . 18c x = ++r->ref; . 16a int x; . ## diffname port/chan.c 1990/11211 ## diff -e /n/bootesdump/1990/1104/sys/src/9/mips/chan.c /n/bootesdump/1990/11211/sys/src/9/mips/chan.c 666c error(Enotdir); . 664c if(c->qid.path & CHDIR) . 654c error(Ebadchar); . 645c error(Efilename); . 640c error(Efilename); . 582c error(Eisdir); . 576c error(Enonexist); . 559c error(Enonexist); . 550,551c if(!(c->qid.path & CHDIR)) error(Enotdir); . 548c error(Enonexist); . 537c error(Enonexist); . 522c error(Enonexist); . 490c error(Ebadsharp); . 487c error(Enonexist); . 460c error(Enonexist); . 423c error(Enocreate); . 419c error(Enocreate); . 230c error(Enotunion); . 213c error(Enotunion); . 193c error(Enomount); . 161,164c if(CHDIR & (old->qid.path^new->qid.path)) error(Emount); if((old->qid.path&CHDIR)==0 && (flag&MORDER)!=MREPL) error(Emount); . 122a if(!pathonly && a->qid.vers!=b->qid.vers) return 0; . 121c return a.path==b.path && a.vers==b.vers; } int eqchan(Chan *a, Chan *b, int pathonly) { if(a->qid.path != b->qid.path) . 119c eqqid(Qid a, Qid b) . 87c c->mqid = (Qid){0, 0}; . 82a c->dev = 0; . ## diffname port/chan.c 1990/1122 ## diff -e /n/bootesdump/1990/11211/sys/src/9/mips/chan.c /n/bootesdump/1990/1122/sys/src/9/mips/chan.c 311c if(!eqchan(mt->c, c, 1)){ /* table changed underfoot */ . 299c if(mt->c && eqchan(mt->c, c, 1)) . 195c else if(eqchan(mt->c, old, 1)){ . ## diffname port/chan.c 1991/0413 ## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/chan.c /n/bootesdump/1991/0413/sys/src/9/port/chan.c 111,115c (*devtab[c->type].close)(c); freechan(c); poperror(); . 107,109c if(waserror()) { freechan(c); nexterror(); . 101a freechan(Chan *c) { c->flag = CFREE; lock(&chanalloc); c->next = chanalloc.free; chanalloc.free = c; unlock(&chanalloc); } void . ## diffname port/chan.c 1991/0414 ## diff -e /n/bootesdump/1991/0413/sys/src/9/port/chan.c /n/bootesdump/1991/0414/sys/src/9/port/chan.c 121,123c c->flag = CFREE; lock(&chanalloc); c->next = chanalloc.free; chanalloc.free = c; unlock(&chanalloc); . 117,119c if(!waserror()) { (*devtab[c->type].close)(c); poperror(); . 104,108c if(decref(c) == 0){ c->flag = CFREE; lock(&chanalloc); c->next = chanalloc.free; chanalloc.free = c; unlock(&chanalloc); } . ## diffname port/chan.c 1991/0416 ## diff -e /n/bootesdump/1991/0414/sys/src/9/port/chan.c /n/bootesdump/1991/0416/sys/src/9/port/chan.c 551d 533,534c /* * If mounting, don't follow the mount entry for root or the * current directory. */ if(mntok && !isdot && !(amode==Amount && elem[0]==0)) . ## diffname port/chan.c 1991/0421 ## diff -e /n/bootesdump/1991/0416/sys/src/9/port/chan.c /n/bootesdump/1991/0421/sys/src/9/port/chan.c 86a c->aux = 0; c->mntindex = 0; . ## diffname port/chan.c 1991/0423 ## diff -e /n/bootesdump/1991/0421/sys/src/9/port/chan.c /n/bootesdump/1991/0423/sys/src/9/port/chan.c 624c if(f.c->flag & CMOUNT){ f.c->mnt = f.mnt; f.c->mountid = f.mountid; } return f.c; . 622a if(f.needcl) doclone(&f); . 617c f.c->flag |= CCEXEC; . 613,615c if((f.c->flag&(CMOUNT|CCREATE)) == CMOUNT) createdir(&f); if(f.needcl) doclone(&f); (*devtab[f.c->type].create)(f.c, elem, omode, perm); . 608,609c if(walk(&f, elem, 1) != 0){ . 602d 600c if(walk(&f, elem, 0) == 0) . 591c f.c->flag |= CCEXEC; . 588,589c saveregisters(); /* else error() in open has wrong value of c saved */ if(f.needcl) doclone(&f); f.c = (*devtab[f.c->type].open)(f.c, omode); . 585d 583c if(walk(&f, elem, mntok) == 0) . 581c domount(&f); . 574,575c if(!(f.c->qid.path & CHDIR)) . 572c if(walk(&f, elem, 0) == 0) . 563d 561c if(walk(&f, elem, mntok) == 0) . 559c domount(&f); . 549d 547c if(walk(&f, elem, mntok) == 0) . 540c domount(&f); /* see case Atodir below */ . 529c close(f.c); . 522c f.c = u->dot; incref(f.c); f.needcl = 1; . 520c f.c = (*devtab[t].attach)(elem); f.needcl = 0; . 502c f.c = u->slash; incref(f.c); f.needcl = 1; . 500a f.mnt = 0; . 480a Finger f; . 476d 468a void doclone(Finger *f) { Chan *nc; if(f->needcl == 0) return; nc = clone(f->c, 0); close(f->c); f->c = nc; f->needcl = 0; } . 458,461c close(f->c); f->needcl = 1; f->c = mc; . 452,456d 439,440c mnt = f->mnt; if(f->mountid != mnt->mountid){ . 432c Chan *mc; . 427,428c void createdir(Finger *f) . 425c * f->c is a mounted non-creatable directory. find a creatable one. . 416,417d 414a return 1; . 412,413c if(domnt) domount(f); . 408,409c /* * we get here only if we have a cloned and walked * channel */ if(!first) close(f->c); f->c = c; f->needcl = 0; f->mnt = 0; c->flag &= ~CMOUNT; . 406c c = mc; first = 0; . 370,403d 360,368c if(name[0]){ for(;;){ if(!first || f->needcl){ mc = (*devtab[c->type].clwalk)(c, name); if(mc){ close(c); c = mc; break; } } else { if((*devtab[c->type].walk)(c, name) != 0){ break; } } if(!(c->flag&CMOUNT)) goto Notfound; if(mnt == 0) panic("walk"); /* ??? is this safe ??? */ lock(pg); if(mnt->term){ unlock(pg); goto Notfound; } if(mountid != mnt->mountid){ pprint("walk: changed underfoot? '%s'\n", name); unlock(pg); goto Notfound; } mnt = mnt->next; mountid = mnt->mountid; mc = mnt->c; incref(mc); . 353,354c Mount *mnt = f->mnt; ulong mountid = f->mountid; Chan *c = f->c; Chan *mc; . 351d 348,349c int walk(Finger *f, char *name, int domnt) . 335,345c close(f->c); f->c = mc; f->needcl = 1; . 330,332c f->mnt = mt->mnt; f->mountid = f->mnt->mountid; mc = mt->mnt->c; . 328c return; . 325c if(!eqchan(mt->c, f->c, 1)){ /* table changed underfoot */ . 318c return; . 313c if(mt->c && eqchan(mt->c, f->c, 1)) . 305c Chan *mc; . 303d 301d 297,298c void domount(Finger *f) . 88d 86d 13a /* * used by namec, domount, and walk to point * to the current mount entry during name resolution */ typedef struct Finger Finger; struct Finger { Chan *c; /* channel we're walking */ int needcl; /* true if we need to clone c before using it */ Mount *mnt; /* last mount point we ran traversed */ ulong mountid; /* id of that mount point */ }; . ## diffname port/chan.c 1991/0426 ## diff -e /n/bootesdump/1991/0423/sys/src/9/port/chan.c /n/bootesdump/1991/0426/sys/src/9/port/chan.c 114,125d ## diffname port/chan.c 1991/0427 ## diff -e /n/bootesdump/1991/0426/sys/src/9/port/chan.c /n/bootesdump/1991/0427/sys/src/9/port/chan.c 624,628c return c; . 621,622d 615c c->flag |= CCEXEC; . 609,613c close(cc); poperror(); /* * the file didn't exist, try the create */ if((c->flag&(CMOUNT|CCREATE)) == CMOUNT) c = createdir(c); (*devtab[c->type].create)(c, elem, omode, perm); . 605c /* * Walk the element before trying to create it * to see if it exists. We clone the channel * first, just in case someone is trying to * use clwalk outside the kernel. */ cc = clone(c, 0); if(waserror()){ close(cc); nexterror(); } if((nc=walk(cc, elem, 1)) != 0){ poperror(); close(c); c = nc; . 599a c = nc; . 598c if((nc=walk(c, elem, 0)) == 0) . 589c c->flag |= CCEXEC; . 584,587c saveregisters(); /* else error() in open has wrong value of c saved */ c = (*devtab[c->type].open)(c, omode); . 581a c = nc; . 580c if((nc=walk(c, elem, mntok)) == 0) . 578c c = domount(c); . 572c c = nc; if(!(c->qid.path & CHDIR)) . 570c if((nc=walk(c, elem, 0)) == 0) . 561a c = nc; . 560c if((nc=walk(c, elem, mntok)) == 0) . 558c c = domount(c); . 548a c = nc; . 547c if((nc=walk(c, elem, mntok)) == 0) . 540c c = domount(c); /* see case Atodir below */ . 529c close(c); . 520,522c c = clone(u->dot, 0); . 517,518c c = (*devtab[t].attach)(elem); . 497,499c c = clone(u->slash, 0); . 495d 474d 469a Chan *c, *nc, *cc; . 450,462d 440,442c close(c); close(mc); nc->mnt = mnt; return nc; . 438a if(waserror()){ close(mc); nexterror(); } nc = clone(mc, 0); . 426,427c mnt = c->mnt; if(c->mountid != mnt->mountid){ . 419c Chan *mc, *nc; . 414,415c Chan* createdir(Chan *c) . 412c * c is a mounted non-creatable directory. find a creatable one. . 404a return c; . 403d 400,401c if(!first) close(ac); . 397a if(domnt){ if(waserror()){ if(!first) close(c); return 0; } c = domount(c); poperror(); . 393,396c close(c); nc->mnt = mnt; nc->mountid = mnt->mountid; c = nc; first = 0; goto Again; } if(name[0]) /* walk succeeded */ . 387,391c if(c->mountid != mnt->mountid){ pprint("walk: changed underfoot? '%s'\n", name); unlock(pg); goto Notfound; } mnt = mnt->next; mc = mnt->c; incref(mc); unlock(pg); if(waserror()){ close(mc); nexterror(); } if(mnt == 0) panic("walk 1"); nc = clone(mc, 0); close(mc); poperror(); . 382,385c goto Notfound; . 349,380c Again: if(name[0] && (*devtab[c->type].walk)(c, name)==0){ if(!(c->flag&CMOUNT)) goto Notfound; mnt = c->mnt; if(mnt == 0) panic("walk"); lock(pg); if(mnt->term){ . 340,343c Chan *c = ac; Chan *nc, *mc; . 338a Mount *mnt; . 336,337c Chan* walk(Chan *ac, char *name, int domnt) . 331,333c if(waserror()){ close(mc); nexterror(); } nc = clone(mc, 0); close(mc); poperror(); close(c); nc->mnt = mnt; nc->mountid = mntid; return nc; . 326,328c mnt = mt->mnt; mntid = mnt->mountid; mc = mnt->c; . 324c return c; . 321c if(!eqchan(mt->c, c, 1)){ /* table changed underfoot */ . 314c return c; . 309c if(mt->c && eqchan(mt->c, c, 1)) . 301c Chan *nc, *mc; . 299a Mount *mnt; . 298a ulong mntid; . 295,296c Chan* domount(Chan *c) . 98a c->mntindex = 0; . 97a c->stream = 0; . 14,25d ## diffname port/chan.c 1991/0705 ## diff -e /n/bootesdump/1991/0427/sys/src/9/port/chan.c /n/bootesdump/1991/0705/sys/src/9/port/chan.c 32a if(x < 0) panic("decref"); . ## diffname port/chan.c 1991/0722 ## diff -e /n/bootesdump/1991/0705/sys/src/9/port/chan.c /n/bootesdump/1991/0722/sys/src/9/port/chan.c 34a } . 33c if(x < 0) { if(u) { print("%d: %s %lux %lux\n", u->p->pid, u->p->text, *(ulong*)((Ureg*)UREGADDR)->pc, r); for(i = 0; i < NSEG; i++) { s = u->p->seg[i]; if(s) print("%d: %lux %lux %lux", i, s, s->base, s->top); } } . 28a int i; Segment *s; . 24a #include "ureg.h" . ## diffname port/chan.c 1991/0723 ## diff -e /n/bootesdump/1991/0722/sys/src/9/port/chan.c /n/bootesdump/1991/0723/sys/src/9/port/chan.c 47c . 37,45c if(x < 0) . ## diffname port/chan.c 1991/0727 ## diff -e /n/bootesdump/1991/0723/sys/src/9/port/chan.c /n/bootesdump/1991/0727/sys/src/9/port/chan.c 666a void nameok(char *elem) { while(*elem) { if((*elem&0x80) || isfrog[*elem]) error(Ebadchar); elem++; } } . 614a nameok(elem); . 8d ## diffname port/chan.c 1991/0912 ## diff -e /n/bootesdump/1991/0727/sys/src/9/port/chan.c /n/bootesdump/1991/0912/sys/src/9/port/chan.c 445a poperror(); . ## diffname port/chan.c 1991/1011 ## diff -e /n/bootesdump/1991/0912/sys/src/9/port/chan.c /n/bootesdump/1991/1011/sys/src/9/port/chan.c 629c if(c->mnt && !(c->flag&CCREATE)) . 583c /* else error() in open has wrong value of c saved */ saveregisters(); . 475c char *elem, *nn; . 438,456c error(Enocreate); . 433,436c for(f = c->mnt; f; f = f->next) { if(f->to->flag&CCREATE) { nc = clone(f->to, 0); nc->mnt = f; runlock(&pg->ns); close(c); return nc; } . 428,430c pg = u->p->pgrp; rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); . 424,426c Pgrp *pg; Chan *nc; Mount *f; . 415c c = 0; } poperror(); runlock(&pg->ns); if(c) { if(dotdot) c = undomount(c); c->mnt = 0; if(domnt) { if(waserror()) { close(c); nexterror(); } c = domount(c); poperror(); } close(ac); } return c; . 412,413c if((*devtab[ac->type].walk)(ac, name) != 0) { if(dotdot) ac = undomount(ac); if(domnt) ac = domount(ac); return ac; } if(ac->mnt == 0) return 0; pg = u->p->pgrp; rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); if(c) close(c); nexterror(); } for(f = ac->mnt; f; f = f->next) { c = clone(f->to, 0); if((*devtab[c->type].walk)(c, name) != 0) break; . 410c dotdot = 0; if(name[0] == '.') if(name[1] == '.') if(name[2] == '\0') { ac = undomount(ac); dotdot = 1; } . 408a if(*name == '\0') return ac; . 406,407c Chan* walk(Chan *ac, char *name, int domnt) { Pgrp *pg; Chan *c = 0; Mount *f; int dotdot; . 404a poperror(); runlock(&pg->ns); return c; } . 402,403d 393,400c he = &pg->mnthash[MNTHASH]; for(h = pg->mnthash; h < he; h++) { for(f = *h; f; f = f->hash) { for(t = f->mount; t; t = t->next) if(eqchan(c, t->to, 1)) { close(c); c = clone(t->head->from, 0); break; } . 351,390c pg = u->p->pgrp; rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); nexterror(); . 345,349c Pgrp *pg; Mhead **h, **he, *f; Mount *t; . 343c undomount(Chan *c) . 336,339c runlock(&pg->ns); return c; . 333,334c c->mnt = 0; for(m = MOUNTH(pg, c); m; m = m->hash) if(eqchan(m->from, c, 1)) { nc = clone(m->mount->to, 0); nc->mnt = m->mount; nc->mountid = m->mount->mountid; close(c); c = nc; break; } . 302,330c rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); . 299c Chan *nc; Mhead *m; . 294,297d 278,282c if(mounted == 0) { *l = m->hash; wunlock(&pg->ns); mountfree(m->mount); close(m->from); mntheadfree(m); return; } p = &m->mount; for(f = *p; f; f = f->next) { if(eqchan(f->to, mounted, 1)) { *p = f->next; f->next = 0; mountfree(f); if(m->mount == 0) { *l = m->hash; wunlock(&pg->ns); close(m->from); mntheadfree(m); return; } wunlock(&pg->ns); return; } p = &f->next; } wunlock(&pg->ns); errors("not in union"); . 273,276c if(m == 0) { wunlock(&pg->ns); errors("not mounted"); . 242,270c void unmount(Chan *mnt, Chan *mounted) { Pgrp *pg; Mhead *m, **l; Mount *f, **p; pg = u->p->pgrp; wlock(&pg->ns); l = &MOUNTH(pg, mnt); for(m = *l; m; m = m->hash) { if(eqchan(m->from, mnt, 1)) break; l = &m->hash; . 233,240c wunlock(&pg->ns); poperror(); return nm->mountid; } . 224,231c if(m->mount && order == MAFTER) { for(f = m->mount; f->next; f = f->next) ; f->next = nm; } else { nm->next = m->mount; m->mount = nm; } . 221,222d 217,218c if(m->mount && order == MREPL) { mountfree(m->mount); m->mount = 0; } nm = newmount(m, new); . 214,215d 208,212c if(m == 0) { m = newmnthead(); m->from = old; incref(old); m->hash = *l; *l = m; if(order != MREPL) m->mount = newmount(m, old); . 196,206c l = &MOUNTH(pg, old); for(m = *l; m; m = m->hash) { if(eqchan(m->from, old, 1)) break; l = &m->hash; . 187,193c wlock(&pg->ns); if(waserror()) { wunlock(&pg->ns); . 183,185d 180c order = flag&MORDER; if((old->qid.path&CHDIR)==0 && order != MREPL) . 176c Mount *nm, *f; Mhead *m, **l; int order; . 172,174d 147,168d 113a . 99,106d 89,97c resrcwait("no chans\n"); . 81,87c for(;;) { lock(&chanalloc); if(c = chanalloc.free) { chanalloc.free = c->next; /* if closed before changed, this calls rooterror, a nop */ c->type = 0; c->flag = 0; c->ref = 1; unlock(&chanalloc); c->dev = 0; c->offset = 0; c->mnt = 0; c->stream = 0; c->aux = 0; c->mntindex = 0; c->mchan = 0; c->mqid = (Qid){0, 0}; return c; } . ## diffname port/chan.c 1991/1105 ## diff -e /n/bootesdump/1991/1011/sys/src/9/port/chan.c /n/bootesdump/1991/1105/sys/src/9/port/chan.c 595a poperror(); . 592a /* * protect against the open/create race. This is not a complete * fix. It just reduces the window. */ if(waserror()) { strcpy(createerr, u->error); nc = walk(c, elem, 1); if(nc == 0) errors(createerr); c = nc; omode |= OTRUNC; goto Open; } . 436a char createerr[ERRLEN]; . ## diffname port/chan.c 1991/1107 ## diff -e /n/bootesdump/1991/1105/sys/src/9/port/chan.c /n/bootesdump/1991/1107/sys/src/9/port/chan.c 653a if(elem >= eelem) error(Efilename); . 649a char *eelem; eelem = elem+NAMELEN; . ## diffname port/chan.c 1991/1126 ## diff -e /n/bootesdump/1991/1107/sys/src/9/port/chan.c /n/bootesdump/1991/1126/sys/src/9/port/chan.c 412a poperror(); . ## diffname port/chan.c 1991/1206 ## diff -e /n/bootesdump/1991/1126/sys/src/9/port/chan.c /n/bootesdump/1991/1206/sys/src/9/port/chan.c 665,666d 556c * subsequent mounts to be attached to the original directory, not . 85c /* if you get an error before associating with a dev, close calls rootclose, a nop */ . 24,25d ## diffname port/chan.c 1992/0101 ## diff -e /n/bootesdump/1991/1206/sys/src/9/port/chan.c /n/bootesdump/1992/0101/sys/src/9/port/chan.c 684,685c c = *(uchar*)name++; if(isfrog[c]) . 654c if(isfrog[*(uchar*)elem]) . 644a /*0x80+ NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, . 637c char isfrog[256]={ . ## diffname port/chan.c 1992/0111 ## diff -e /n/bootesdump/1992/0101/sys/src/9/port/chan.c /n/bootesdump/1992/0111/sys/src/9/port/chan.c 603c error(createerr); . 257c error(Eunion); . 226c error(Eunmount); . 6c #include "../port/error.h" . ## diffname port/chan.c 1992/0213 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/chan.c /n/bootesdump/1992/0213/sys/src/9/port/chan.c 693d 691d 688,689c name += chartorune(&r, name); if(r= NAMELEN) error(Efilename); memmove(elem, name, w); elem[w] = 0; . 673a Rune r; . 672c int i, user, w; . ## diffname port/chan.c 1992/0320 ## diff -e /n/bootesdump/1992/0213/sys/src/9/port/chan.c /n/bootesdump/1992/0320/sys/src/9/port/chan.c 115,119c chanfree(c); . 104a chanfree(Chan *c) { c->flag = CFREE; lock(&chanalloc); c->next = chanalloc.free; chanalloc.free = c; unlock(&chanalloc); } void . ## diffname port/chan.c 1992/0321 ## diff -e /n/bootesdump/1992/0320/sys/src/9/port/chan.c /n/bootesdump/1992/0321/sys/src/9/port/chan.c 2c #include "../port/lib.h" . ## diffname port/chan.c 1992/0520 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/chan.c /n/bootesdump/1992/0520/sys/src/9/port/chan.c 423a return 0; /* not reached */ . 101a return 0; /* not reached */ . ## diffname port/chan.c 1992/0619 ## diff -e /n/bootesdump/1992/0520/sys/src/9/port/chan.c /n/bootesdump/1992/0619/sys/src/9/port/chan.c 255c free(m); . 241c free(m); . 181c m = smalloc(sizeof(Mhead)); . 94d ## diffname port/chan.c 1992/0620 ## diff -e /n/bootesdump/1992/0619/sys/src/9/port/chan.c /n/bootesdump/1992/0620/sys/src/9/port/chan.c 101c /* if you get an error before associating with a dev, close calls rootclose, a nop */ c->type = 0; c->flag = 0; c->ref = 1; c->dev = 0; c->offset = 0; c->mnt = 0; c->stream = 0; c->aux = 0; c->mchan = 0; c->mqid = (Qid){0, 0}; return c; . 79,99c SET(nfid); lock(&chanalloc); c = chanalloc.free; if(c) chanalloc.free = c->next; else nfid = ++chanalloc.fid; unlock(&chanalloc); if(c == 0) { c = smalloc(sizeof(Chan)); c->fid = nfid; . 77a int nfid; . 41,56d 10a int fid; . 8c struct { . ## diffname port/chan.c 1992/0711 ## diff -e /n/bootesdump/1992/0620/sys/src/9/port/chan.c /n/bootesdump/1992/0711/sys/src/9/port/chan.c 671,672c int w; char *end; . 435c char *elem; . 30,31d ## diffname port/chan.c 1992/0811 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/chan.c /n/bootesdump/1992/0811/sys/src/9/port/chan.c 546a if(omode & ORCLOSE) c->flag |= CRCLOSE; . ## diffname port/chan.c 1992/0825 ## diff -e /n/bootesdump/1992/0811/sys/src/9/port/chan.c /n/bootesdump/1992/0825/sys/src/9/port/chan.c 475c } else { . 461c } else if(name[0] == '#') { . 455c if(name[0] == '/') { . 314a } . 309c for(t = f->mount; t; t = t->next) { . ## diffname port/chan.c 1992/0919 ## diff -e /n/bootesdump/1992/0825/sys/src/9/port/chan.c /n/bootesdump/1992/0919/sys/src/9/port/chan.c 648,651d ## diffname port/chan.c 1992/1217 ## diff -e /n/bootesdump/1992/0919/sys/src/9/port/chan.c /n/bootesdump/1992/1217/sys/src/9/port/chan.c 471d 468c t = devno(r, 1); . 466c name++; name += chartorune(&r, name); if(r == 'M') . 431a Rune r; . 54c for(i=0; isession){ freesession(c->session); c->session = 0; } . ## diffname port/chan.c 1993/0501 ## diff -e /n/bootesdump/1993/0330/sys/src/9/port/chan.c /n/fornaxdump/1993/0501/sys/src/brazil/port/chan.c 691c while(name < end){ . 683,686c end = utfrune(name, '/'); if(end == 0) end = strchr(name, 0); w = end-name; . 678c char *end; . 609c strcpy(createerr, up->error); . 605,606c * protect against the open/create race. * This is not a complete fix. It just reduces the window. . 588c nc = walk(cc, elem, 1); if(nc != 0) { . 567c nc = walk(c, elem, 0); if(nc == 0) . 563,565c * When mounting on an already mounted upon directory, * one wants subsequent mounts to be attached to the * original directory, not the replacement. . 546,547c else { nc = walk(c, elem, mntok); if(nc == 0) . 536c nc = walk(c, elem, 0); if(nc == 0) . 524,525c else { nc = walk(c, elem, mntok); if(nc == 0) . 517,519d 506,511c while(*name) { nc = walk(c, elem, mntok); if(nc == 0) . 478,487c c = (*devtab[t].attach)(elem+n); name = skipslash(name); break; default: c = clone(up->dot, 0); name = skipslash(name); . 471,474c elem[0] = 0; n = 0; while(*name && (*name != '/' || n < 2)) elem[n++] = *name++; elem[n] = '\0'; n = chartorune(&r, elem+1)+1; if(r == 'M') { name = skipslash(name); if(*name) error(Eperm); return mchan(elem+n); } . 467,469c break; case '#': . 461,465c switch(name[0]) { case '/': c = clone(up->slash, 0); . 458c elem = up->elem; . 452c while(vmemchr(p, 0, t) == 0) { . 445,449c if(!((ulong)name & KZERO)) { . 439a int t, n; int mntok, isdot; Chan *c, *nc, *cc; . 437d 434,435d 421a Chan* mchan(char *id) { Chan *c; Pgrp *pg; Mount *t; int mdev; ulong mountid; Mhead **h, **he, *f; mountid = strtoul(id, 0, 0); mdev = devno('M', 0); pg = up->pgrp; rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); nexterror(); } he = &pg->mnthash[MNTHASH]; for(h = pg->mnthash; h < he; h++) { for(f = *h; f; f = f->hash) { for(t = f->mount; t; t = t->next) { c = t->to; if(c->type == mdev && c->mntptr->id == mountid) { c = c->mntptr->c; incref(c); runlock(&pg->ns); poperror(); return c; } } } } error(Enonexist); return 0; } . 402c pg = up->pgrp; . 388a close(ac); . 387c c = domount(c); poperror(); . 375,385c if(c == 0) return 0; if(dotdot) c = undomount(c); c->mnt = 0; if(domnt) { if(waserror()) { close(c); nexterror(); . 357c c = 0; pg = up->pgrp; . 339,341c if(name[0] == '.' && name[1] == '.' && name[2] == '\0') { . 335c if(name[0] == '\0') . 331c Chan *c; . 303c pg = up->pgrp; . 284a nc->xmnt = nc->mnt; . 273c pg = up->pgrp; . 214c pg = up->pgrp; . 188c nm = newmount(m, new, flag, spec); . 180c m->mount = newmount(m, old, 0, 0); . 159c pg = up->pgrp; . 149d 146a int order; . 144c mount(Chan *new, Chan *old, int flag, char *spec) . 121a chanfree(c); } . 120a /* ASSERT */ if(c->path && c->path->ref == 0) { char buf[64]; ptpath(c->path, buf, sizeof(buf)); print(">>%s %c %d %lux.%lux\n", buf, devchar[c->type], c->dev, c->qid.path, c->qid.vers); . 114,119c if(decref(c)) return; if(!waserror()) { (*devtab[c->type].close)(c); poperror(); . 111c if(c->flag&CFREE) . 101a /* * Channel can be closed before a path is created or the last * channel in a mount which has already cleared its pt names */ if(c->path) decref(c->path); . 97a . 89a c->path = 0; . 76c lock(&chanalloc); c->fid = ++chanalloc.fid; c->link = chanalloc.list; chanalloc.list = c; unlock(&chanalloc); . 70,71d 68c if(c != 0) . 64,65d 62d 40a chanrec(Mnt *m) { Chan *c; lock(&chanalloc); for(c = chanalloc.list; c; c = c->link) if(c->mntptr == m) c->flag |= CRECOV; unlock(&chanalloc); } void . 12a Chan *free; Chan *list; . 11d ## diffname port/chan.c 1993/0511 ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/chan.c /n/fornaxdump/1993/0511/sys/src/brazil/port/chan.c 99d ## diffname port/chan.c 1993/0526 ## diff -e /n/fornaxdump/1993/0511/sys/src/brazil/port/chan.c /n/fornaxdump/1993/0526/sys/src/brazil/port/chan.c 67c for(i=0; devchar[i]; i++) . 58c for(i=0; devchar[i]; i++) . ## diffname port/chan.c 1993/1007 ## diff -e /n/fornaxdump/1993/0526/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1007/sys/src/brazil/port/chan.c 595a nc = walk(c, elem, mntok); if(nc == 0) error(Enonexist); c = nc; . 590,594c break; . 588c if(isdot) { . 586c switch(amode) { . ## diffname port/chan.c 1993/1013 ## diff -e /n/fornaxdump/1993/1007/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1013/sys/src/brazil/port/chan.c 101a c->mcp = 0; . ## diffname port/chan.c 1993/1015 ## diff -e /n/fornaxdump/1993/1013/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1015/sys/src/brazil/port/chan.c 144,150d ## diffname port/chan.c 1993/1017 ## diff -e /n/fornaxdump/1993/1015/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1017/sys/src/brazil/port/chan.c 617a if(omode == OEXEC) c->flag |= CTEXT; . ## diffname port/chan.c 1993/1018 ## diff -e /n/fornaxdump/1993/1017/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1018/sys/src/brazil/port/chan.c 619c c->flag &= ~CCACHE; c = (*devtab[c->type].open)(c, omode); . 616,617c saveregisters(); . ## diffname port/chan.c 1993/1111 ## diff -e /n/fornaxdump/1993/1018/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1111/sys/src/brazil/port/chan.c 266c if(eqchan(f->to, mounted, 1) || eqchan(f->to->mchan, mounted, 1)) { . ## diffname port/chan.c 1993/1114 ## diff -e /n/fornaxdump/1993/1111/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1114/sys/src/brazil/port/chan.c 541a name = skipslash(name); . 539,540c if(amode != Aopen || omode != ORDWR) . ## diffname port/chan.c 1993/1115 ## diff -e /n/fornaxdump/1993/1114/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1115/sys/src/brazil/port/chan.c 224c for(f = nm; f->next; f = f->next) ; f->next = m->mount; . 214d 212a if(new->mnt != 0) { h = &nm->next; for(um = new->mnt->next; um; um = um->next) { flg = um->flag; if(flg == 0) flg = MAFTER; f = newmount(m, um->to, flg, um->spec); *h = f; h = &f->next; } } . 173a Mount *nm, *f, *um, **h; . 171,172c int order, flg; . ## diffname port/chan.c 1993/1121 ## diff -e /n/fornaxdump/1993/1115/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1121/sys/src/brazil/port/chan.c 553c skipslash(name); . ## diffname port/chan.c 1993/1216 ## diff -e /n/fornaxdump/1993/1121/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1216/sys/src/brazil/port/chan.c 222a } if(m->mount && order == MREPL) { mountfree(m->mount); m->mount = 0; . 216,218d 213a /* * copy a union when binding it onto a directory */ flg = order; if(order == MREPL) flg = MAFTER; . 207,211d ## diffname port/chan.c 1993/1217 ## diff -e /n/fornaxdump/1993/1216/sys/src/brazil/port/chan.c /n/fornaxdump/1993/1217/sys/src/brazil/port/chan.c 202a /* * if this is a union mount, add the old * node to the mount chain. */ . 197a /* * nothing mounted here yet. create a mount * head and add to the hash table. */ . ## diffname port/chan.c 1994/0115 ## diff -e /n/fornaxdump/1993/1217/sys/src/brazil/port/chan.c /n/fornaxdump/1994/0115/sys/src/brazil/port/chan.c 289a /* BUG: Needs to be 2 pass */ . ## diffname port/chan.c 1994/0509 ## diff -e /n/fornaxdump/1994/0115/sys/src/brazil/port/chan.c /n/fornaxdump/1994/0509/sys/src/brazil/port/chan.c 291c if(eqchan(f->to, mounted, 1) || (f->to->mchan && eqchan(f->to->mchan, mounted, 1))) { . ## diffname port/chan.c 1994/0812 ## diff -e /n/fornaxdump/1994/0509/sys/src/brazil/port/chan.c /n/fornaxdump/1994/0812/sys/src/brazil/port/chan.c 133c if(c == 0 || (c->flag&CFREE)) . ## diffname port/chan.c 1994/0813 ## diff -e /n/fornaxdump/1994/0812/sys/src/brazil/port/chan.c /n/fornaxdump/1994/0813/sys/src/brazil/port/chan.c 133c if(c->flag&CFREE) . ## diffname port/chan.c 1994/1212 ## diff -e /n/fornaxdump/1994/0813/sys/src/brazil/port/chan.c /n/fornaxdump/1994/1212/sys/src/brazil/port/chan.c 565,568c c = mchan(elem+n); name = skipslash(name); break; . 503,504c c = clone(c, 0); . ## diffname port/chan.c 1995/0208 ## diff -e /n/fornaxdump/1994/1212/sys/src/brazil/port/chan.c /n/fornaxdump/1995/0208/sys/src/brazil/port/chan.c 564,565c if(elem[n] == 'c') { c = mchan(elem+n+1, 0); name = skipslash(name); if(*name) error(Efilename); return c; } else { c = mchan(elem+n, 1); name = skipslash(name); } . 503c if(walkname == 0) { c = c->mntptr->c; incref(c); } else c = clone(c, 0); . 478c mchan(char *id, int walkname) . ## diffname port/chan.c 1996/0730 ## diff -e /n/fornaxdump/1995/0208/sys/src/brazil/port/chan.c /n/fornaxdump/1996/0730/sys/src/brazil/port/chan.c 727a if(omode & ORCLOSE) c->flag |= CRCLOSE; . ## diffname port/chan.c 1997/0327 ## diff -e /n/fornaxdump/1996/0730/sys/src/brazil/port/chan.c /n/emeliedump/1997/0327/sys/src/brazil/port/chan.c 725c devtab[c->type]->create(c, elem, omode, perm); . 703c cclose(cc); . 698c cclose(c); . 691c cclose(cc); . 689c cc = cclone(c, 0); . 659c c = devtab[c->type]->open(c, omode); . 597c cclose(c); . 590c c = cclone(up->dot, 0); . 586c c = devtab[t]->attach(elem+n); . 557c c = cclone(up->slash, 0); . 508c c = cclone(c, 0); . 474c return 0; . 469c cclose(c); . 465c nc = cclone(f->to, 0); . 443c cclose(ac); . 437c cclose(c); . 422c cclose(c); . 419,420c c = cclone(f->to, 0); if(devtab[c->type]->walk(c, name) != 0) . 415c cclose(c); . 397c if(devtab[ac->type]->walk(ac, name) != 0) { . 368,369c cclose(c); c = cclone(t->head->from, 0); . 339c cclose(c); . 335c nc = cclone(m->mount->to, 0); . 315c return devtab[c->type]->clone(c, nc); . 313c cclone(Chan *c, Chan *nc) . 299c cclose(m->from); . 283c cclose(m->from); . 258c cunmount(Chan *mnt, Chan *mounted) . 168c cmount(Chan *new, Chan *old, int flag, char *spec) . 140c devtab[c->type]->close(c); . 134,135c panic("cclose %lux", getcallerpc(c)); . 131c cclose(Chan *c) . 68c devtab[i]->init(); . 59c devtab[i]->reset(); . ## diffname port/chan.c 1997/0408 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/chan.c /n/emeliedump/1997/0408/sys/src/brazil/port/chan.c 67c for(i=0; devtab[i] != nil; i++) . 58c for(i=0; devtab[i] != nil; i++) . ## diffname port/chan.c 1997/0813 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/chan.c /n/emeliedump/1997/0813/sys/src/brazil/port/chan.c 418a c->flag &= ~CCREATE; /* not inherited through a walk */ . 395a ac->flag &= ~CCREATE; /* not inherited through a walk */ . ## diffname port/chan.c 1997/1121 ## diff -e /n/emeliedump/1997/0813/sys/src/brazil/port/chan.c /n/emeliedump/1997/1121/sys/src/brazil/port/chan.c 368c c = nc; . 366a nc = cclone(t->head->from, 0); . 353a Mhead **h, **he, *f; . 352d 350a Chan *nc; . ## diffname port/chan.c 1997/1208 ## diff -e /n/emeliedump/1997/1121/sys/src/brazil/port/chan.c /n/emeliedump/1997/1208/sys/src/brazil/port/chan.c 106a int okchan1(Chan *c) { if(c->type > 64) return 0; if((ulong)(c->next) & 3) return 0; if((ulong)(c->link) & 3) return 0; if((ulong)(c->path) & 3) return 0; if((ulong)(c->mnt) & 3) return 0; if((ulong)(c->xmnt) & 3) return 0; if((ulong)(c->mcp) & 3) return 0; if((ulong)(c->mchan) & 3) return 0; if((ulong)(c->session) & 3) return 0; return 1; } void okchan(char *msg, int n) { int s; Chan *c; return; s = splhi(); for(c = chanalloc.list; c; c = c->link) if(!okchan1(c)){ spllo(); print("okchan: %s (%d=#%.8lux)\n", msg, n, n); panic("okchan"); } splx(s); } . ## diffname port/chan.c 1997/1210 ## diff -e /n/emeliedump/1997/1208/sys/src/brazil/port/chan.c /n/emeliedump/1997/1210/sys/src/brazil/port/chan.c 140,144c okchan1(c, msg, n); . 137d 110,128c int i, bad; bad = 0; if(c->type > 64){ print("bad type %d\n", c->type); bad = 1; } if((ulong)(c->next) & 3){ print("bad next %.8lux\n", c->next); bad = 1; } if((ulong)(c->link) & 3){ print("bad link %.8lux\n", c->link); bad = 1; } if((ulong)(c->path) & 3){ print("bad path %.8lux\n", c->path); bad = 1; } if((ulong)(c->mnt) & 3){ print("bad mnt %.8lux\n", c->mnt); bad = 1; } if((ulong)(c->xmnt) & 3){ print("bad xmnt %.8lux\n", c->xmnt); bad = 1; } if((ulong)(c->mcp) & 3){ print("bad mcp %.8lux\n", c->mcp); bad = 1; } if((ulong)(c->mchan) & 3){ print("bad mchan %.8lux\n", c->mchan); bad = 1; } if((ulong)(c->session) & 3){ print("bad session %.8lux\n", c->session); bad = 1; } if(!bad) return; print("okchan: %s (%d=#%.8lux)\n", msg, n, n); for(i=0; i<16; i++){ print("%d=%.8lux\n", i, ((ulong*)c)[i]); if((i&7) == 7) print("\n"); } for(;;); . 107,108c void okchan1(Chan *c, char *msg, int n) . ## diffname port/chan.c 1997/1211 ## diff -e /n/emeliedump/1997/1210/sys/src/brazil/port/chan.c /n/emeliedump/1997/1211/sys/src/brazil/port/chan.c 166a return; . ## diffname port/chan.c 1998/0221 ## diff -e /n/emeliedump/1997/1211/sys/src/brazil/port/chan.c /n/emeliedump/1998/0221/sys/src/brazil/port/chan.c 108,174d ## diffname port/chan.c 1998/0224 ## diff -e /n/emeliedump/1998/0221/sys/src/brazil/port/chan.c /n/emeliedump/1998/0224/sys/src/brazil/port/chan.c 724d 721,722c if(walk(&c, elem, 1) < 0) . 702c c = cc; . 698,699c if(walk(&cc, elem, 1) == 0){ . 679d 676,677c if(walk(&c, elem, 0) < 0) . 653d 650,651c if(walk(&c, elem, mntok) < 0) . 641d 638,639c if(walk(&c, elem, 0) < 0) . 630d 627,628c if(walk(&c, elem, mntok) < 0) . 617d 614,615c if(walk(&c, elem, mntok) < 0) . 540c Chan *c, *cc; . 447c *cp = c; return 0; . 431,432c if(c == nil) return -1; . 426c c = nil; . 410c c = nil; . 407,408c if(ac->mnt == nil) return -1; . 403,404c *cp = domount(*cp); return 0; . 401c *cp = undomount(*cp); . 394c *cp = ac = undomount(ac); . 390c return 0; . 388a ac = *cp; . 385c Chan *c, *ac; . 381,382c int walk(Chan **cp, char *name, int domnt) . ## diffname port/chan.c 1998/0416 ## diff -e /n/emeliedump/1998/0224/sys/src/brazil/port/chan.c /n/emeliedump/1998/0416/sys/src/brazil/port/chan.c 122a } . 121c if(c->path) { if (c->path->ref <= 0) { char buf[100]; ptpath(c->path, buf, sizeof(buf)); print("decref %s\n", buf); } . ## diffname port/chan.c 1998/0512 ## diff -e /n/emeliedump/1998/0416/sys/src/brazil/port/chan.c /n/emeliedump/1998/0512/sys/src/brazil/port/chan.c 674c * one wants subsequent mounts to be attached to the . 662c . 456c return 0; . 415c if(ac->mnt == nil) . 345,346c c = nc; break; . 217c if(order != MREPL) . 128c } . 123,126c char buf[100]; ptpath(c->path, buf, sizeof(buf)); print("decref %s\n", buf); } . 35c if(x < 0) . ## diffname port/chan.c 1998/0813 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/chan.c /n/emeliedump/1998/0813/sys/src/brazil/port/chan.c 606a c->mnt = nil; . ## diffname port/chan.c 1998/0829 ## diff -e /n/emeliedump/1998/0813/sys/src/brazil/port/chan.c /n/emeliedump/1998/0829/sys/src/brazil/port/chan.c 814a } void putmhead(Mhead *m) { if(decref(m) == 0) free(m); . 711c if(c->mh != nil && !(c->flag&CCREATE)) . 607d 478,479c if(nc->mh != nil) putmhead(nc->mh); nc->mh = c->mh; incref(c->mh); runlock(&c->mh->lock); . 475c for(f = c->mh->mount; f; f = f->next) { . 472c runlock(&c->mh->lock); . 469,470c rlock(&c->mh->lock); . 465d 445c if(c->mh){ putmhead(c->mh); c->mh = nil; } . 437c runlock(&ac->mh->lock); . 428c for(f = ac->mh->mount; f; f = f->next) { . 423c runlock(&ac->mh->lock); . 421c rlock(&ac->mh->lock); . 419d 415c if(ac->mh == nil) . 390d 349d 347a runlock(&m->lock); } . 346c poperror(); runlock(&m->lock); return c; . 341,343c if(nc->mh != nil) putmhead(nc->mh); nc->mh = m; nc->xmh = m; incref(m); . 339a if(waserror()) { runlock(&m->lock); nexterror(); } runlock(&pg->ns); . 338c for(m = MOUNTH(pg, c); m; m = m->hash){ rlock(&m->lock); . 336d 332,334c if(c->mh){ putmhead(c->mh); c->mh = 0; . 313c wunlock(&m->lock); . 308c wunlock(&m->lock); . 305c wunlock(&m->lock); putmhead(m); . 301c if(m->mount == nil) { . 291a wunlock(&pg->ns); . 289c wunlock(&m->lock); putmhead(m); . 287a m->mount = nil; . 283a wlock(&m->lock); . 257c wunlock(&m->lock); . 230c um = new->mh->mount; for(um = um->next; um; um = um->next) { . 222c if(new->mh != nil && new->mh->mount != nil) { . 219a wlock(&m->lock); if(waserror()){ wunlock(&m->lock); nexterror(); } wunlock(&pg->ns); . 207a m->ref = 1; . 190,193d 116a if(c->mh != nil){ putmhead(c->mh); c->mh = nil; } . 98c c->mh = 0; c->xmh = 0; c->uri = 0; . ## diffname port/chan.c 1999/0122 ## diff -e /n/emeliedump/1998/0829/sys/src/brazil/port/chan.c /n/emeliedump/1999/0122/sys/src/brazil/port/chan.c 752c devtab[c->type]->create(c, elem, omode&~OCEXEC, perm); . 691c c = devtab[c->type]->open(c, omode&~OCEXEC); . ## diffname port/chan.c 1999/0323 ## diff -e /n/emeliedump/1999/0122/sys/src/brazil/port/chan.c /n/emeliedump/1999/0323/sys/src/brazil/port/chan.c 788c /* [' '] 1, rob - let's try this out */ . ## diffname port/chan.c 1999/0501 ## diff -e /n/emeliedump/1999/0323/sys/src/brazil/port/chan.c /n/emeliedump/1999/0501/sys/src/brazil/port/chan.c 147c panic("cclose %lux", getcallerpc(&c)); . ## diffname port/chan.c 1999/0629 ## diff -e /n/emeliedump/1999/0501/sys/src/brazil/port/chan.c /n/emeliedump/1999/0629/sys/src/brazil/port/chan.c 762a poperror(); /* peculiar workaround for #/ */ if(newname){ if(cname->s[0]=='#' && cname->s[1]=='/') cleanname(cname, 2); else cleanname(cname, 0); cnameclose(c->name); c->name = cname; }else cnameclose(cname); . 691a if(cc != c) newname = 0; . 690a cc = c; . 629a cname = newcname(up->dot->name->s); cname = addelem(cname, name); . 613a poperror(); cnameclose(cname); . 600a cname = newcname(name); /* save this before advancing */ . 598a c = cclone(up->slash, 0); . 597c cname = newcname(name); /* save this before advancing */ . 591a newname = 1; cname = nil; if(waserror()){ cnameclose(cname); nexterror(); } . 575c Cname *cname; int t, n, newname; . 565a * In place, rewrite name to compress multiple /, eliminate ., and process .. */ void cleanname(Cname *n, int offset) { char *p, *q, *dotdot, *name; int rooted; name = n->s+offset; rooted = name[0] == '/'; /* * invariants: * p points at beginning of path element we're considering. * q points just past the last path element we wrote (no slash). * dotdot points just past the point where .. cannot backtrack * any further (no slash). */ p = q = dotdot = name+rooted; while(*p) { if(p[0] == '/') /* null element */ p++; else if(p[0] == '.' && SEP(p[1])) p += 1; /* don't count the separator in case it is nul */ else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) { p += 2; if(q > dotdot) { /* can backtrack */ while(--q > dotdot && *q != '/') ; } else if(!rooted) { /* ``/..'' ≡ ``/'', but ``./../'' ≡ ``..'' */ if(q != name) *q++ = '/'; *q++ = '.'; *q++ = '.'; dotdot = q; } } else { /* real path element */ if(q != name+rooted) *q++ = '/'; while((*q = *p) != '/' && *q != 0) p++, q++; } } if(q == name) /* empty string is really ``.'' */ *q++ = '.'; *q = 0; n->len = (q-name) + offset; } /* . 413a walkname(Chan **cp, char *name, int domnt) { Chan *c; if(walk(cp, name, domnt) < 0) return -1; c = *cp; if(c->name == nil) c->name = newcname(name); else c->name = addelem(c->name, name); return 0; } int . 336c nc = devtab[c->type]->clone(c, nc); if(nc != nil){ nc->name = c->name; if(c->name) incref(c->name); } return nc; . 124,135c cnameclose(c->name); . 109a cnameclose(Cname *n) { if(n == 0) return; if(decref(n)) return; decref(&ncname); free(n->s); free(n); } Cname* addelem(Cname *n, char *s) { int i, a; char *t; Cname *new; if(n->ref > 1){ /* copy on write */ new = newcname(n->s); cnameclose(n); n = new; } i = strlen(s); if(n->len+1+i+1 < n->alen){ a = n->len+1+i+1 + CNAMESLOP; t = smalloc(a); memmove(t, n->s, n->len+1); free(n->s); n->s = t; n->alen = a; } n->s[n->len++] = '/'; memmove(n->s+n->len, s, i+1); n->len += i; return n; } void . 108a static Ref ncname; Cname* newcname(char *s) { Cname *n; int i; n = smalloc(sizeof(Cname)); i = strlen(s); n->len = i; n->alen = i+CNAMESLOP; n->s = smalloc(n->alen); memmove(n->s, s, i+1); n->ref = 1; incref(&ncname); return n; } . 105a c->name = 0; . 103d 15a #define SEP(c) ((c) == 0 || (c) == '/') . 7a enum { CNAMESLOP = 20 }; . ## diffname port/chan.c 1999/0630 ## diff -e /n/emeliedump/1999/0629/sys/src/brazil/port/chan.c /n/emeliedump/1999/0630/sys/src/brazil/port/chan.c 162c if(n->len+1+i+1 > n->alen){ . ## diffname port/chan.c 1999/0716 ## diff -e /n/emeliedump/1999/0630/sys/src/brazil/port/chan.c /n/emeliedump/1999/0716/sys/src/brazil/port/chan.c 915c cleancname(cname, 0); . 913c cleancname(cname, 1); . 688c *q = '\0'; . 672c } else if(!rooted) { /* /.. is / but ./../ is .. */ . 646c cleancname(Cname *n, int offset) . ## diffname port/chan.c 1999/0718 ## diff -e /n/emeliedump/1999/0716/sys/src/brazil/port/chan.c /n/emeliedump/1999/0718/sys/src/brazil/port/chan.c 959c if(!slashok || *elem!='/') error(Ebadchar); . 952c nameok(char *elem, int slashok) . 868c nameok(elem, 0); . ## diffname port/chan.c 1999/0811 ## diff -e /n/emeliedump/1999/0718/sys/src/brazil/port/chan.c /n/emeliedump/1999/0811/sys/src/brazil/port/chan.c 513c *cp = domount(c); . 510,511c /* walk succeeded: update name associated with *cp (ac) */ c = *cp; if(c->name == nil) c->name = newcname(name); else c->name = addelem(c->name, name); if(dotdot){ cleancname(c->name, c->name->s[0]=='#'); /* could be cheaper */ *cp = undomount(c); } . 476,490d 462a /* don't need to update nc->name because c->name is same! */ . 461a /* * We want to come out on the left hand side of the mount * point using the element of the union that we entered on. * To do this, find the element that has a from name of * c->name->s. */ if(strcmp(t->head->from->name->s, c->name->s) != 0) continue; . 428a cnameclose(nc->name); nc->name = c->name; incref(c->name); . 21a void cleancname(Cname*, int); . ## diffname port/chan.c 1999/0820 ## diff -e /n/emeliedump/1999/0811/sys/src/brazil/port/chan.c /n/emeliedump/1999/0820/sys/src/brazil/port/chan.c 520c *cp = domount(*cp); . ## diffname port/chan.c 1999/1105 ## diff -e /n/emeliedump/1999/0820/sys/src/brazil/port/chan.c /n/emeliedump/1999/1105/sys/src/9/port/chan.c 50,61d ## diffname port/chan.c 1999/1224 ## diff -e /n/emeliedump/1999/1105/sys/src/9/port/chan.c /n/emeliedump/1999/1224/sys/src/9/port/chan.c 737a } . 736c while(*name && (*name != '/' || n < 2)){ if(n >= NAMELEN-1) error(Efilename); . 554a if(domnt) *cp = domount(c); . 545,552c /* replace c->name by ac->name */ cnameclose(c->name); c->name = ac->name; if(ac->name) incref(ac->name); c = updatecname(c, name, dotdot); . 538,540d 497,506c *cp = updatecname(*cp, name, dotdot); . 475a Chan * updatecname(Chan *c, char *name, int dotdot) { if(c->name == nil) c->name = newcname(name); else c->name = addelem(c->name, name); if(dotdot){ cleancname(c->name, c->name->s[0]=='#'); /* could be cheaper */ c = undomount(c); } return c; } . 159c if(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/') /* don't insert extra slash if one is present */ n->s[n->len++] = '/'; . ## diffname port/chan.c 1999/1230 ## diff -e /n/emeliedump/1999/1224/sys/src/9/port/chan.c /n/emeliedump/1999/1230/sys/src/9/port/chan.c 916,919c cleancname(cname); . 914d 655,690c /* * The correct name is #i rather than #i/, * but the correct name of #/ is #/. */ if(strcmp(p, "/")==0 && n->s[1] != '/') *p = '\0'; }else cleanname(n->s); n->len = strlen(n->s); . 652,653c if(n->s[0] == '#'){ p = strchr(n->s, '/'); if(p == nil) return; cleanname(p); . 649,650c char *p; . 647c cleancname(Cname *n) . 486c cleancname(c->name); /* could be cheaper */ . 22c void cleancname(Cname*); . ## diffname port/chan.c 2000/0322 ## diff -e /n/emeliedump/1999/1230/sys/src/9/port/chan.c /n/emeliedump/2000/0322/sys/src/9/port/chan.c 712a /* * noattach is sandboxing. * * the OK exceptions are: * | it only gives access to pipes you create * d this process's file descriptors * e this process's environment * the iffy exceptions are: * c time and pid, but also cons and consctl * p control of your own processes (and unfortunately * any others left unprotected) */ if(up->pgrp->noattach) if(strchr("|decp", name[1]) == 0) error(Enoattach); . ## diffname port/chan.c 2000/0326 ## diff -e /n/emeliedump/2000/0322/sys/src/9/port/chan.c /n/emeliedump/2000/0326/sys/src/9/port/chan.c 723a * all are ASCII, so it's safe to use strchr to check. . ## diffname port/chan.c 2000/0330 ## diff -e /n/emeliedump/2000/0326/sys/src/9/port/chan.c /n/emeliedump/2000/0330/sys/src/9/port/chan.c 740,755c /* actually / is caught by parsing earlier */ if(utfrune("M", r)) error(Enoattach); if(up->pgrp->noattach && utfrune("|decp", r)) error(Enoattach); . 726,738d 724d 712a cname = newcname(name); /* save this before advancing */ mntok = 0; elem[0] = 0; n = 0; while(*name && (*name != '/' || n < 2)){ if(n >= NAMELEN-1) error(Efilename); elem[n++] = *name++; } elem[n] = '\0'; . 595,637d ## diffname port/chan.c 2000/0904 ## diff -e /n/emeliedump/2000/0330/sys/src/9/port/chan.c /n/emeliedump/2000/0904/sys/src/9/port/chan.c 644c if(((ulong)name & KZERO) != KZERO) { . ## diffname port/chan.c 2000/1124 ## diff -e /n/emeliedump/2000/0904/sys/src/9/port/chan.c /n/emeliedump/2000/1124/sys/src/9/port/chan.c 696c if(up->pgrp->noattach && utfrune("|decp", r)==nil) . ## diffname port/chan.c 2001/0214 ## diff -e /n/emeliedump/2000/1124/sys/src/9/port/chan.c /n/emeliedump/2001/0214/sys/src/9/port/chan.c 364d ## diffname port/chan.c 2001/0424 ## diff -e /n/emeliedump/2001/0214/sys/src/9/port/chan.c /n/emeliedump/2001/0424/sys/src/9/port/chan.c 666a if(*name == 0) isdot = 1; . ## diffname port/chan.c 2001/0502 ## diff -e /n/emeliedump/2001/0424/sys/src/9/port/chan.c /n/emeliedump/2001/0502/sys/src/9/port/chan.c 202a poperror(); . 201a devtab[c->type]->close(c); . 197,199c if(waserror()){ print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->error : "no user"); //BUG return; . ## diffname port/chan.c 2001/0503 ## diff -e /n/emeliedump/2001/0502/sys/src/9/port/chan.c /n/emeliedump/2001/0503/sys/src/9/port/chan.c 204a chanfree(c); . 203d 198a chanfree(c); . ## diffname port/chan.c 2001/0504 ## diff -e /n/emeliedump/2001/0503/sys/src/9/port/chan.c /n/emeliedump/2001/0504/sys/src/9/port/chan.c 198c // print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->error : "no user"); . ## diffname port/chan.c 2001/0527 ## diff -e /n/emeliedump/2001/0504/sys/src/9/port/chan.c /n/emeliedump/2001/0527/sys/src/9/port/chan.c 944a } . 943c if(m && decref(m) == 0){ decref(&mheadcounter); m->mount = (Mount*)0xCafeBeef; . 939a /* * This is necessary because there are many * pointers to the top of a given mount list: * * - the mhead in the namespace hash table * - the mhead in chans returned from findmount: * used in namec and then by unionread. * - the mhead in chans returned from createdir: * used in the open/create race protect, which is gone. * * The RWlock in the Mhead protects the mount list it contains. * The mount list is deleted when we cunmount. * The RWlock ensures that nothing is using the mount list at that time. * * It is okay to replace c->mh with whatever you want as * long as you are sure you have a unique reference to it. * * This comment might belong somewhere else. */ . 935c if(c->qid.type & QTDIR) . 929d 914,927c if(((ulong)name & KZERO) != KZERO) { p = name; t = BY2PG-((ulong)p&(BY2PG-1)); while((ename=vmemchr(p, 0, t)) == nil) { p += t; t = BY2PG; } }else ename = memchr(name, 0, (1<<16)); if(ename==nil || ename-name>=(1<<16)) error("name too long"); while(*name){ /* all characters above '~' are ok */ c = *(uchar*)name; if(c >= Runeself) name += chartorune(&r, name); else{ if(isfrog[c]) if(!slashok || c!='/') error(Ebadchar); name++; } . 910,911c char *p, *ename; uint t; int c; . 907,908c void validname(char *name, int slashok) . 905c * Check that the name * a) is in valid memory. * b) is shorter than 2^16 bytes, so it can fit in a 9P string field. * c) contains no frogs. * The first byte is known to be addressible by the requester, so the * routine works for kernel and user memory both. * The parameter slashok flags whether a slash character is an error * or a valid character. . 888,903d 883d 871c if(*name=='.' && (name[1]=='\0' || name[1]=='/')){ . 863c * name is valid. skip leading / and ./ and trailing . . 851,858c /* place final element in genbuf for e.g. exec */ if(e.nelems > 0) kstrcpy(up->genbuf, e.elems[e.nelems-1], sizeof up->genbuf); else kstrcpy(up->genbuf, ".", sizeof up->genbuf); free(e.name); free(e.elems); . 837,843c panic("namec: not reached"); . 826,833c /* * We need our own copy of the Chan because we're * about to send a create, which will move it. Once we have * our own copy, we can fix the name, which might be wrong * if findmount gave us a new Chan. */ cnew = cunique(cnew); cnameclose(cnew->name); cnew->name = c->name; incref(cnew->name); devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm); poperror(); if(omode & OCEXEC) cnew->flag |= CCEXEC; if(omode & ORCLOSE) cnew->flag |= CRCLOSE; if(m) putmhead(m); cclose(c); c = cnew; break; }else{ /* create failed */ cclose(cnew); if(m) putmhead(m); if(omode & OEXCL) nexterror(); if(walk(&c, e.elems+e.nelems-1, 1, nomount) < 0) nexterror(); . 823,824c m = nil; cnew = nil; /* is this assignment necessary? */ if(!waserror()){ /* try create */ if(!nomount && findmount(&cnew, &m, c->type, c->dev, c->qid)) cnew = createdir(cnew, m); else{ cnew = c; incref(cnew); } . 821c * The semantics of the create(2) system call are that if the * file exists and can be written, it is to be opened with truncation. * On the other hand, the create(5) message fails if the file exists. * If we get two create(2) calls happening simultaneously, * they might both get here and send create(5) messages, but only * one of the messages will succeed. To provide the expected create(2) * semantics, the call with the failed message needs to try the above * walk again, opening for truncation. This correctly solves the * create/create race, in the sense that any observable outcome can * be explained as one happening before the other. * The create/create race is quite common. For example, it happens * when two rc subshells simultaneously update the same * environment variable. * * The implementation still admits a create/create/remove race: * (A) walk to file, fails * (B) walk to file, fails * (A) create file, succeeds, returns * (B) create file, fails * (A) remove file, succeeds, returns * (B) walk to file, return failure. * * This is hardly as common as the create/create race, and is really * not too much worse than what might happen if (B) got a hold of a * file descriptor and then the file was removed -- either way (B) can't do * anything with the result of the create call. So we don't care about this race. * * Applications that care about more fine-grained decision of the races * can use the OEXCL flag to get at the underlying create(5) semantics; * by default we provide the common case. * * We need to stay behind the mount point in case we * need to do the first walk again (should the create fail). * * We also need to cross the mount point and find the directory * in the union in which we should be creating. * * The channel staying behind is c, the one moving forward is cnew. . 817,818d 804,813c e.nelems++; if(walk(&c, e.elems+e.nelems-1, 1, nomount) == 0){ if(omode&OEXCL){ cclose(c); error(Eexist); } . 799,802c * We've already walked all but the last element. * If the last exists, try to open it OTRUNC. * If omode&OEXCL is set, just give up. . 795,797d 790,791d 788c * original directory, not the replacement. Don't domount. . 783a case Atodir: /* * Directories (e.g. for cd) are left before the mount point, * so one may mount on / or . and see the effect. */ if(!(c->qid.type & QTDIR)) error(Enotdir); break; . 775,776d 773d 767c /* save the name; domount might change c */ cname = c->name; incref(cname); m = nil; if(!nomount) domount(&c, &m); /* our own copy to open or remove */ c = cunique(c); /* now it's our copy anyway, we can put the name back */ cnameclose(c->name); c->name = cname; if(amode == Aremove){ putmhead(m); break; } if(c->umh != nil){ print("cunique umh\n"); putmhead(c->umh); } c->umh = m; /* save registers else error() in open has wrong value of c saved */ . 760,765d 748,758c case Aremove: . 740,745c if(!nomount) domount(&c, nil); . 738c if(walk(&c, e.elems, e.nelems, nomount) < 0) error(Enonexist); switch(amode){ . 732,735c /* * On create, don't try to walk the last path element just yet. */ if(amode == Acreate){ if(e.nelems == 0) error(Eisdir); e.nelems--; . 729,730c parsename(name, &e); . 726,727c * Build a list of elements in the path. . 723,724d 719a free(e.name); free(e.elems); //dumpmount(); . 718a if(strcmp(up->error, Enonexist) == 0){ if(strlen(aname) < ERRMAX/3 || (name=strrchr(aname, '/'))==nil || name==aname) snprint(up->error, sizeof up->error, "\"%s\" does not exist", aname); else snprint(up->error, sizeof up->error, "file \"...%s\" does not exist", name); } . 717a e.name = nil; e.elems = nil; . 714,715c break; . 710,712c c = up->dot; incref(c); . 708a . 705,707c c = devtab[t]->attach(up->genbuf+n); . 696c n = chartorune(&r, up->genbuf+1)+1; . 683c up->genbuf[n] = '\0'; . 681c up->genbuf[n++] = *name++; . 678,679c while(*name!='\0' && (*name != '/' || n < 2)){ if(n >= sizeof(up->genbuf)-1) . 674,676c nomount = 1; up->genbuf[0] = '\0'; . 672a . 669,671d 667c c = up->slash; incref(c); . 646,665c /* * Find the starting off point (the current slash, the root of * a device tree, or the current dot) as well as the name to * evaluate starting there. */ nomount = 0; switch(name[0]){ . 643,644c name = aname; if(name[0] == '\0') error("empty file name"); validname(name, 1); . 638,641c Elemlist e; Rune r; Mhead *m; char *name; . 634,636c int n, t, nomount; Chan *c, *cnew; . 632c namec(char *aname, int amode, int omode, ulong perm) . 629a * * Opening with amode Aopen, Acreate, or Aremove guarantees * that the result will be the only reference to that particular fid. * This is necessary since we might pass the result to * devtab[]->remove(). * * Opening Atodir, Amount, or Aaccess does not guarantee this. * * Opening Aaccess can, under certain conditions, return a * correct Chan* but with an incorrect Cname attached. * Since the functions that open Aaccess (sysstat, syswstat, sys_stat) * do not use the Cname*, this avoids an unnecessary clone. . 627a * The name is known to be valid. * Copy the name so slashes can be overwritten. * An empty string will set nelem=0. */ static void parsename(char *name, Elemlist *e) { char *slash; kstrdup(&e->name, name); name = e->name; e->nelems = 0; e->elems = nil; for(;;){ name = skipslash(name); if(*name=='\0') break; growparse(e); e->elems[e->nelems++] = name; slash = utfrune(name, '/'); if(slash == nil) break; *slash++ = '\0'; name = slash; } } /* . 626a static void growparse(Elemlist *e) { char **new; enum { Delta = 8 }; if(e->nelems % Delta == 0){ new = smalloc((e->nelems+Delta) * sizeof(char*)); memmove(new, e->elems, e->nelems*sizeof(char*)); free(e->elems); e->elems = new; } } . 580,587c for(f = m->mount; f; f = f->next) { if(f->mflag&MCREATE) { nc = cclone(f->to); runlock(&m->lock); . 577c runlock(&m->lock); . 575c rlock(&m->lock); . 570c createdir(Chan *c, Mhead *m) . 561,562c cclose(*cp); *cp = c; if(chandebug) print("success\n"); . 554,559c c->name = cname; . 552c putmhead(mh); c = cunique(c); if(c->umh != nil){ print("walk umh\n"); putmhead(c->umh); c->umh = nil; } . 547,549c names += n; nnames -= n; //print("nc %s nnames %d devchar %C qid %.8llux\n", cname->s, nnames, devtab[c->type]->dc, c->qid.path); free(wq); . 544,545c for(i=0; iwalk(c, nil, names, ntry)) == nil){ if(chandebug) print("walk failed."); /* try a union mount, if any */ if(mh == nil || nomount){ Giveup: if(chandebug) print("give up\n"); //delay(2000); cclose(c); cnameclose(cname); return -1; } rlock(&mh->lock); if(waserror()){ runlock(&mh->lock); nexterror(); } for(f = mh->mount; f; f = f->next) { if(chandebug) print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.path, devtab[c->type]->dc, c->dev); if((wq = devtab[f->to->type]->walk(f->to, nil, names, ntry)) != nil) break; } poperror(); runlock(&mh->lock); if(wq == nil) goto Giveup; type = f->to->type; dev = f->to->dev; } nmh = nil; if(dotdot) { assert(wq->nqid == 1); assert(wq->clone != nil); if(chandebug) print("undo."); nc = undomount(wq->clone, cname); n = 1; } else { nc = nil; if(chandebug) print("find."); if(!nomount) for(i=0; inqid && iqid[i])) break; if(nc == nil){ /* no mount points along path */ if(wq->clone == nil){ cclose(c); cnameclose(cname); free(wq); if(chandebug) print("fail\n"); return -1; } n = wq->nqid; nc = wq->clone; }else{ /* stopped early, at a mount point */ if(wq->clone != nil){ cclose(wq->clone); wq->clone = nil; } n = i+1; } } . 524c type = c->type; dev = c->dev; . 521,522c if(chandebug){ print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.path, devtab[c->type]->dc, c->dev); for(i=0; i 0){ ntry = nnames; if(ntry > MAXWELEM) ntry = MAXWELEM; dotdot = 0; for(i=0; iname; incref(cname); mh = nil; . 501c //BUG: waserror? . 499c Mhead *mh, *nmh; Walkqid *wq; . 497c int i, dotdot, n, ntry, type, dev; Chan *c, *nc; Cname *cname; . 495c walk(Chan **cp, char **names, int nnames, int nomount) . 479,493c /* * Either walks all the way or not at all. No partial results. */ . 465,466c nc = t->head->from; incref(nc); . 463c if(strcmp(t->head->from->name->s, name->s) != 0) . 438c undomount(Chan *c, Cname *name) . 436a int domount(Chan **cp, Mhead **mp) { return findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid); } . 434c return 0; . 428c return 1; . 415,426c if(mp != nil){ incref(m); if(*mp != nil) putmhead(*mp); *mp = m; } if(*cp != nil) cclose(*cp); incref(m->mount->to); *cp = m->mount->to; . 409,413c if(m->from == nil){ print("m %p m->from 0\n", m); runlock(&m->lock); continue; } if(eqchantdqid(m->from, type, dev, qid, 1)) { . 402,407c for(m = MOUNTH(pg, qid); m; m = m->hash){ . 397d 393,394c int findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid) . 384,389c Chan *nc; Walkqid *wq; wq = devtab[c->type]->walk(c, nil, nil, 0); if(wq == nil) error("clone failed"); nc = wq->clone; free(wq); nc->name = c->name; if(c->name) incref(c->name); . 382c cclone(Chan *c) . 332c l = &MOUNTH(pg, mnt->qid); . 328a if(mnt->umh) /* should not happen */ print("cmount newp extra umh\n"); if(mounted && mounted->umh) print("cmount old extra umh\n"); . 303c nm->mflag |= MCREATE; . 289c um = mh->mount; . 281c if(mh != nil && mh->mount != nil) { . 259a incref(&mheadcounter); . 254c if(m == nil) { . 247c l = &MOUNTH(pg, old->qid); . 243a mh = nil; domount(newp, &mh); new = *newp; /* * Not allowed to bind when the old directory * is itself a union. (Maybe it should be allowed, but I don't see * what the semantics would be.) * * We need to check mh->mount->next to tell unions apart from * simple mount points, so that things like * mount -c fd /root * bind -c /root / * work. The check of mount->mflag catches things like * mount fd /root * bind -c /root / * * This is far more complicated than it should be, but I don't * see an easier way at the moment. -rsc */ if((flag&MCREATE) && mh && mh->mount && (mh->mount->next || !(mh->mount->mflag&MCREATE))) error(Emount); . 241c if((old->qid.type&QTDIR)==0 && order != MREPL) . 238a if((*newp)->umh) /* should not happen */ print("cmount newp extra umh\n"); if(old->umh) print("cmount old extra umh\n"); . 236c if(QTDIR & (old->qid.type^(*newp)->qid.type)) . 234a Chan *new; . 233c Mhead *m, **l, *mh; . 230a if(a->qid.path != qid.path) return 0; if(!pathonly && a->qid.vers!=qid.vers) return 0; if(a->type != type) return 0; if(a->dev != dev) return 0; return 1; } int cmount(Chan **newp, Chan *old, int flag, char *spec) { . 229c eqchantdqid(Chan *a, int type, int dev, Qid qid, int pathonly) . 207a /* * Make sure we have the only copy of c. (Copy on write.) */ Chan* cunique(Chan *c) { Chan *nc; if(c->ref != 1) { nc = cclone(c); cclose(c); c = nc; } return c; } . 179a if(c->umc != nil){ cclose(c->umc); c->umc = nil; } . 175,178c if(c->umh != nil){ putmhead(c->umh); c->umh = nil; . 171,173c if(c->version){ free(c->version); c->version = 0; . 162a if(isdotdot(s)) cleancname(n); . 142a if(s[0]=='.' && s[1]=='\0') return n; . 127c if(n == nil) . 101a c->version = 0; . 100c memset(&c->mqid, 0, sizeof(c->mqid)); . 94,95c c->iounit = 0; c->umh = 0; . 84a if(chandebug) print("newchan %d\n", c->fid); . 78c if(c == nil) { . 49a kstrcpy(char *s, char *t, int ns) { int nt; nt = strlen(t); if(nt+1 <= ns){ memmove(s, t, nt+1); return; } /* too long */ if(ns < 4){ /* but very short! */ strncpy(s, t, ns); return; } /* truncate with ... at character boundary (very rare case) */ memmove(s, t, ns-4); ns -= 4; s[ns] = '\0'; /* look for first byte of UTF-8 sequence by skipping continuation bytes */ while(ns>0 && (s[--ns]&0xC0)==0x80) ; strcpy(s+ns, "..."); } int emptystr(char *s) { if(s == nil) return 1; if(s[0] == '\0') return 1; return 0; } /* * Atomically replace *p with copy of s */ void kstrdup(char **p, char *s) { int n; char *t, *prev; static Lock l; n = strlen(s)+1; // if(n == 1){ // ulong pc; // int i; // static ulong pcs[128]; // pc = getcallerpc(&p); // for(i=0; igenbuf; */ . 24a isdotdot(char *p) { return p[0]=='.' && p[1]=='.' && p[2]=='\0'; } int . 20a typedef struct Elemlist Elemlist; struct Elemlist { char *name; /* copy of name, so '/' can be overwritten */ int nelems; char **elems; }; . 7a int chandebug=0; /* toggled by sysr1 */ /* transition BUG */ int client9p = 2; int kernel9p = 2; int domount(Chan**, Mhead**); Ref mheadcounter; void dumpmount(void) /* DEBUGGING */ { Pgrp *pg; Mount *t; Mhead **h, **he, *f; if(up == nil){ print("no process for dumpmount\n"); return; } pg = up->pgrp; if(pg == nil){ print("no pgrp for dumpmount\n"); return; } rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); nexterror(); } he = &pg->mnthash[MNTHASH]; for(h = pg->mnthash; h < he; h++) { for(f = *h; f; f = f->hash) { print("head: %p: %s 0x%llux.%lud %C %lud -> \n", f, f->from->name->s, f->from->qid.path, f->from->qid.vers, devtab[f->from->type]->dc, f->from->dev); for(t = f->mount; t; t = t->next) print("\t%p: %s (umh %p)\n", t, t->to->name->s, t->to->umh); } } poperror(); runlock(&pg->ns); } . ## diffname port/chan.c 2001/0530 ## diff -e /n/emeliedump/2001/0527/sys/src/9/port/chan.c /n/emeliedump/2001/0530/sys/src/9/port/chan.c 806a if(chandebug) print("undidmount nc %s...", nc->name->s); . 805c if(chandebug) print("undo wq->clone->name %s cname %s...", wq->clone->name->s, cname->s); . ## diffname port/chan.c 2001/0601 ## diff -e /n/emeliedump/2001/0530/sys/src/9/port/chan.c /n/emeliedump/2001/0601/sys/src/9/port/chan.c 863c if(chandebug) print("[%lud]\twalk succeeds; name %s chan (path %.8llux dev %C %lud)\n", up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev); . 845d 840,842d 832a for(i=0; ipid); for(j=0; j<=i; j++) print("%s%s", j?"/":"", names[j]); print(" becomes "); print("%s\n", c2name(nc)); qunlock(&chanprint); } . 821d 816a if(chandebug) print("[%lud]\tno mount points along path\n", up->pid); . 811d 807c if(chandebug) print("[%lud]\tundo returned %s\n", up->pid, c2name(nc)); . 805c cname = addelem(cname, ".."); if(chandebug) print("[%lud]\tundo wq->clone %s cname %s\n", up->pid, c2name(wq->clone), cname?cname->s:""); . 787c if(chandebug) print("[%lud]\twalk from %s (path %.8llux dev %C %lud)\n", up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev); . 773,774c if(chandebug) print("[%lud]\tgive up\n", up->pid); . 769c if(chandebug) print("[%lud]\twalk failed.\n", up->pid); . 760c print("%s%s", i?"/":"", names[i]); print("\n"); qunlock(&chanprint); . 758c qlock(&chanprint); print("[%lud]\twalk from %s (path %.8llux dev %C %lud) to ", up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev); . 728a qunlock(&chanprint); . 727c print("%s%s", i?"/":"", names[i]); . 725c qlock(&chanprint); print("[%lud] walk %s to ", up->pid, c2name(c)); . 692a if(chandebug) print("[%lud]\tundomount found %s\n", up->pid, c2name(c)); . 678a if(strcmp(f->from->name->s, name->s) != 0) continue; if(chandebug) print("[%lud]\tundomount found head %s; need chan (path %.8llux dev %C %lud)\n", up->pid, name->s, c->qid.path, devtab[c->type]->dc, c->dev); . 228d 54a char* c2name(Chan *c) /* DEBUGGING */ { if(c == nil) return ""; if(c->name == nil) return ""; if(c->name->s == nil) return ""; return c->name->s; } . 48c print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->name->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev); . 14d 8a QLock chanprint; /* probably asking for trouble (deadlocks) -rsc */ . ## diffname port/chan.c 2001/0803 ## diff -e /n/emeliedump/2001/0601/sys/src/9/port/chan.c /n/emeliedump/2001/0803/sys/src/9/port/chan.c 559c print("cunmount old extra umh\n"); . 557c print("cunmount newp extra umh\n"); . ## diffname port/chan.c 2001/0819 ## diff -e /n/emeliedump/2001/0803/sys/src/9/port/chan.c /n/emeliedump/2001/0819/sys/src/9/port/chan.c 900,901d 894a if(c->umh != nil){ //BUG print("walk umh\n"); putmhead(c->umh); c->umh = nil; } . 889,893d 875d 857,865d 846,847d 836,837d 833,834d 816d 810,813d 798d 794d 778,786d 743,751d 735,736d 710,711d 693,695d 358a . 344a if(c->mux != nil){ muxclose(c->mux); c->mux = nil; } if(c->mchan != nil){ cclose(c->mchan); c->mchan = nil; } . 333,336d 258d 255a c->mux = 0; . 177,189d ## diffname port/chan.c 2001/0822 ## diff -e /n/emeliedump/2001/0819/sys/src/9/port/chan.c /n/emeliedump/2001/0822/sys/src/9/port/chan.c 1244a . 1226c error(createerr); /* report true error */ . 1224a /* save error */ kstrcpy(createerr, up->error, sizeof createerr); . 1108,1111c if(omode & OCEXEC) c->flag |= CCEXEC; if(omode & ORCLOSE) c->flag |= CRCLOSE; break; } . 1106c c = devtab[c->type]->open(c, omode&~OCEXEC); . 1103,1104c if(omode == OEXEC) c->flag &= ~CCACHE; . 1100,1101c /* save registers else error() in open has wrong value of c saved */ saveregisters(); . 1098c if(c->qid.type&QTDIR) c->umh = m; else putmhead(m); . 1093a case Aopen: case Acreate: . 1092d 1089c switch(amode){ case Aremove: . 971a char createerr[ERRMAX]; . 774c for(f = mh->mount->next; f; f = f->next) . 551c print("cunmount old extra umh %p has %p\n", mounted, mounted->umh); . 549c print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh); . 239a c->dri = 0; . ## diffname port/chan.c 2001/0823 ## diff -e /n/emeliedump/2001/0822/sys/src/9/port/chan.c /n/emeliedump/2001/0823/sys/src/9/port/chan.c 1102c /* only save the mount head if it's a multiple element union */ if(m && m->mount && m->mount->next) . ## diffname port/chan.c 2001/0912 ## diff -e /n/emeliedump/2001/0823/sys/src/9/port/chan.c /n/emeliedump/2001/0912/sys/src/9/port/chan.c 549,552c if(mnt->umh) /* should not happen */ print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh); /* * It _can_ happen that mounted->umh is non-nil, * because mounted is the result of namec(Aopen) * (see sysfile.c:/^sysunmount). * If we open a union directory, it will have a umh. * Although surprising, this is okay, since the * cclose will take care of freeing the umh. */ . ## diffname port/chan.c 2001/0919 ## diff -e /n/emeliedump/2001/0912/sys/src/9/port/chan.c /n/emeliedump/2001/0919/sys/src/9/port/chan.c 1078a break; case Abind: m = nil; if(!nomount) domount(&c, &m); c->umh = m; . 441a mh = new->umh; . 439,440d 429,430d ## diffname port/chan.c 2001/0922 ## diff -e /n/emeliedump/2001/0919/sys/src/9/port/chan.c /n/emeliedump/2001/0922/sys/src/9/port/chan.c 1239a c->name = addelem(c->name, e.elems[e.nelems-1]); . ## diffname port/chan.c 2001/0924 ## diff -e /n/emeliedump/2001/0922/sys/src/9/port/chan.c /n/emeliedump/2001/0924/sys/src/9/port/chan.c 1251a } up->errstr = createerr; . 1249,1250c createerr = up->errstr; up->errstr = tmperrbuf; /* note: we depend that walk does not error */ if(walk(&c, e.elems+e.nelems-1, 1, nomount) < 0){ up->errstr = createerr; . 1046c snprint(up->errstr, ERRMAX, "file \"...%s\" does not exist", name); . 1044c snprint(up->errstr, ERRMAX, "\"%s\" does not exist", aname); . 1042c if(strcmp(up->errstr, Enonexist) == 0){ . 977c char *createerr, tmperrbuf[ERRMAX]; . 778a /* * mh->mount == c, so start at mh->mount->next */ . ## diffname port/chan.c 2001/0926 ## diff -e /n/emeliedump/2001/0924/sys/src/9/port/chan.c /n/emeliedump/2001/0926/sys/src/9/port/chan.c 356c // print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->errstr : "no user"); . ## diffname port/chan.c 2001/1118 ## diff -e /n/emeliedump/2001/0926/sys/src/9/port/chan.c /n/emeliedump/2001/1118/sys/src/9/port/chan.c 1167d 1164,1165c if(omode&OEXCL) . ## diffname port/chan.c 2001/1130 ## diff -e /n/emeliedump/2001/1118/sys/src/9/port/chan.c /n/emeliedump/2001/1130/sys/src/9/port/chan.c 356,357c print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->errstr : "no user"); /* don't chanfree: better leak than leave a dangling pointer */ . ## diffname port/chan.c 2001/1204 ## diff -e /n/emeliedump/2001/1130/sys/src/9/port/chan.c /n/emeliedump/2001/1204/sys/src/9/port/chan.c 360,362d 355,358c if(!waserror()){ devtab[c->type]->close(c); poperror(); . ## diffname port/chan.c 2001/1213 ## diff -e /n/emeliedump/2001/1204/sys/src/9/port/chan.c /n/emeliedump/2001/1213/sys/src/9/port/chan.c 802c for(i=0; inqid && i e.nelems){ print("namec %s walk error npath=%d\n", aname, npath); nexterror(); } len = prefix+e.off[npath]; strcpy(tmperrbuf, up->errstr); if(len < ERRMAX/3 || (name=memrchr(aname, '/', len))==nil || name==aname) snprint(up->errstr, ERRMAX, "\"%.*s\" %s", len, aname, tmperrbuf); else snprint(up->errstr, ERRMAX, "\"...%.*s\" %s", (int)(len-(name-aname)), name, tmperrbuf); nexterror(); } . 1049a free(e.off); . 1041,1046d 1039a e.off = nil; e.nelems = 0; . 1036a prefix = name - aname; . 970c int n, prefix, len, t, nomount, npath; . 950a void* memrchr(void *va, int c, long n) { uchar *a, *e; a = va; for(e=a+n-1; e>a; e--) if(*e == c) return e; return nil; } . 945a } e->off[e->nelems] = slash - e->name; . 944c if(slash == nil){ e->off[e->nelems] = name+strlen(name) - e->name; . 941a . 936a e->off = smalloc(sizeof(int)); e->off[0] = 0; . 919a inew = smalloc((e->nelems+Delta+1) * sizeof(int)); memmove(inew, e->off, e->nelems*sizeof(int)); free(e->off); e->off = inew; . 912a int *inew; . 848a if(nerror) *nerror = 0; . 828,830d 822c cname = addelem(cname, names[nhave+i]); . 808a if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){ if(nerror) *nerror = nhave+wq->nqid+1; strcpy(up->errstr, Edoesnotexist); }else{ if(nerror) *nerror = nhave+wq->nqid; strcpy(up->errstr, Enotdir); } . 769,788d 766a if(nerror) *nerror = nhave+1; . 763,764c if(mh && !nomount){ /* * mh->mount == c, so start at mh->mount->next */ rlock(&mh->lock); for(f = mh->mount->next; f; f = f->next) if((wq = devtab[f->to->type]->walk(f->to, nil, names+nhave, ntry)) != nil) break; runlock(&mh->lock); if(f != nil){ type = f->to->type; dev = f->to->dev; } } if(wq == nil){ . 761c if((wq = devtab[type]->walk(c, nil, names+nhave, ntry)) == nil){ . 744,745c for(i=0; iqid.type&QTDIR)==0){ if(nerror) *nerror = nhave; cnameclose(cname); cclose(c); strcpy(up->errstr, Enotdir); return -1; } ntry = nnames - nhave; . 716c int dev, dotdot, i, n, nhave, ntry, type; . 714c walk(Chan **cp, char **names, int nnames, int nomount, int *nerror) . 712a static char Edoesnotexist[] = "does not exist"; . 711c * Either walks all the way or not at all. No partial results in *cp. * *nerror is the number of names to display in an error message. . 87a int *off; . ## diffname port/chan.c 2002/0109 ## diff -e /n/emeliedump/2002/0104/sys/src/9/port/chan.c /n/emeliedump/2002/0109/sys/src/9/port/chan.c 210a void chandevshutdown(void) { int i; /* shutdown in reverse order */ for(i=0; devtab[i] != nil; i++) ; for(i--; i >= 0; i--) devtab[i]->shutdown(); } . ## diffname port/chan.c 2002/0115 ## diff -e /n/emeliedump/2002/0109/sys/src/9/port/chan.c /n/emeliedump/2002/0115/sys/src/9/port/chan.c 11,14d ## diffname port/chan.c 2002/0411 ## diff -e /n/emeliedump/2002/0115/sys/src/9/port/chan.c /n/emeliedump/2002/0411/sys/src/9/port/chan.c 1432d 1394,1395c if(!slashok || c!='/'){ snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname); error(up->genbuf); } . 1373a name = aname; . 1369c char *p, *ename, *name; . 1367c validname(char *aname, int slashok) . 481d 12d ## diffname port/chan.c 2002/0416 ## diff -e /n/emeliedump/2002/0411/sys/src/9/port/chan.c /n/emeliedump/2002/0416/sys/src/9/port/chan.c 1119c snprint(up->genbuf, sizeof up->genbuf, "...%.*s", (int)(len-(name-aname)), name); snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, tmperrbuf); . 1117c snprint(up->genbuf, sizeof up->genbuf, "%.*s", len, aname); . ## diffname port/chan.c 2002/0731 ## diff -e /n/emeliedump/2002/0416/sys/src/9/port/chan.c /n/emeliedump/2002/0731/sys/src/9/port/chan.c 1163a c->umh = nil; . 1162c print("cunique umh Open\n"); . 1133a if(c->umh != nil) putmhead(c->umh); . 609a wunlock(&pg->ns); . 604a wunlock(&pg->ns); . 600a wunlock(&pg->ns); . 587d 479,483c m = newmhead(old); . 433,434c if(old->umh)print("cmount old extra umh\n"); . 420a Mhead* newmhead(Chan *from) { Mhead *mh; int n; mh = smalloc(sizeof(Mhead)); mh->ref = 1; mh->from = from; incref(from); n = from->name->len; if(n >= sizeof(mh->fromname)) n = sizeof(mh->fromname)-1; memmove(mh->fromname, from->name->s, n); mh->fromname[n] = 0; return mh; } . ## diffname port/chan.c 2002/0801 ## diff -e /n/emeliedump/2002/0731/sys/src/9/port/chan.c /n/emeliedump/2002/0801/sys/src/9/port/chan.c 847a if(mh != nil) putmhead(mh); . 815a if(mh != nil) putmhead(mh); . 771a if(mh != nil) {print("walk 1\n"); putmhead(mh); } . ## diffname port/chan.c 2002/0830 ## diff -e /n/emeliedump/2002/0801/sys/src/9/port/chan.c /n/emeliedump/2002/0830/sys/src/9/port/chan.c 115c panic("decref, pc=0x%lux", getcallerpc(&r)); . ## diffname port/chan.c 2002/0911 ## diff -e /n/emeliedump/2002/0830/sys/src/9/port/chan.c /n/emeliedump/2002/0911/sys/src/9/port/chan.c 437c */ . 431a /* . 425d ## diffname port/chan.c 2003/0303 ## diff -e /n/emeliedump/2002/0911/sys/src/9/port/chan.c /n/emeliedump/2003/0303/sys/src/9/port/chan.c 1367,1370d 1364,1365c while(name[0]=='/' || (name[0]=='.' && (name[1]==0 || name[1]=='/'))) . 1359c * name is valid. skip leading / and ./ as much as possible . 1148a if(e.mustbedir && !(c->qid.type&QTDIR)){ npath = e.nelems; strcpy(tmperrbuf, "not a directory"); goto NameError; } if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR)){ npath = e.nelems; error("cannot exec directory"); } . 1140a NameError: len = prefix+e.off[npath]; . 1139d 1130c error(Eexist); . 1128a /* perm must have DMDIR if last element is / or /. */ if(e.mustbedir && !(perm&DMDIR)){ npath = e.nelems; strcpy(tmperrbuf, "create without DMDIR"); goto NameError; } /* don't try to walk the last path element just yet. */ . 1126c * On create, .... . 1102d 1062d 998a e->mustbedir = 0; . 994d 992a } . 991c if(*name=='\0'){ e->mustbedir = 1; . 988c e->off[0] = skipslash(name) - name; . 976a * A path ending in / or /. or /.//./ etc. will have * e.mustbedir = 1, so that we correctly * reject, e.g., "/adm/users/." when /adm/users is a file * rather than a directory. . 83a int mustbedir; . ## diffname port/chan.c 2003/0509 ## diff -e /n/emeliedump/2003/0303/sys/src/9/port/chan.c /n/emeliedump/2003/0509/sys/src/9/port/chan.c 1218d 1206a case Aaccess: . 1205a /* record whether c is on a mount point */ c->ismtpt = m!=nil; . 1188a case Aaccess: . 1175,1179d 1165,1166c nameerror(aname, "not a directory"); . 1152,1160c nameerror(aname, up->errstr); . 1137,1138c nameerror(aname, "create without DMDIR"); . 1110d 1045c int n, t, nomount, npath; . 1037,1040c * Under certain circumstances, opening Aaccess will cause * an unnecessary clone in order to get a cunique Chan so it * can attach the correct name. Sysstat and sys_stat need the * correct name so they can rewrite the stat info. . 1035c * Opening Atodir or Amount does not guarantee this. . 1030c * Opening with amode Aopen, Acreate, Aremove, or Aaccess guarantees . 1025a void nameerror(char *name, char *error) { int len; char tmperr[ERRMAX], *p; strcpy(tmperr, error); /* error might be in genbuf or tmperr */ len = strlen(name); if(len < ERRMAX/3 || (p=strrchr(name, '/'))==nil || p==name) snprint(up->genbuf, sizeof up->genbuf, "%s", name); else snprint(up->genbuf, sizeof up->genbuf, "...%s", p); snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, tmperr); nexterror(); } . 835c }else{ . 828c if(dotdot){ . 804c * mh->mount->to == c, so start at mh->mount->next . 776d 774d 658,663c if(m->from == nil){ print("m %p m->from 0\n", m); runlock(&m->lock); continue; } if(eqchantdqid(m->from, type, dev, qid, 1)){ . 329a if(c->dirrock != nil){ free(c->dirrock); c->dirrock = 0; c->nrock = 0; c->mrock = 0; } . 255a c->ismtpt = 0; . 245a c->devoffset = 0; . 52c channame(Chan *c) /* DEBUGGING */ .