Add devwd - portable watchdog driver interface. Also change dotdot algorithm as described in 9fans. [rsc] --rw-rw-r-- M 57833 rsc sys 2342 Sep 12 23:32 sys/src/9/port/devwd.c [rsc] --rw-rw-r-- M 57833 glenda sys 13624 Sep 13 00:37 sys/src/9/alphapc/main.c /n/sourcesdump/2005/0913/plan9/sys/src/9/alphapc/main.c:176,183 - /n/sourcesdump/2005/0914/plan9/sys/src/9/alphapc/main.c:176,183 * Then early kproc's will have a root and dot. */ up->slash = namec("#/", Atodir, 0, 0); - cnameclose(up->slash->name); - up->slash->name = newcname("/"); + pathclose(up->slash->path); + up->slash->path = newpath("/"); up->dot = cclone(up->slash); chandevinit(); [rsc] --rw-rw-r-- M 57833 glenda bitsy 9081 Sep 13 00:37 sys/src/9/bitsy/main.c /n/sourcesdump/2005/0913/plan9/sys/src/9/bitsy/main.c:96,103 - /n/sourcesdump/2005/0914/plan9/sys/src/9/bitsy/main.c:96,103 * Then early kproc's will have a root and dot. */ up->slash = namec("#/", Atodir, 0, 0); - cnameclose(up->slash->name); - up->slash->name = newcname("/"); + pathclose(up->slash->path); + up->slash->path = newpath("/"); up->dot = cclone(up->slash); chandevinit(); [rsc] --rw-rw-r-- M 57833 glenda sys 8342 Sep 13 00:37 sys/src/9/mtx/main.c /n/sourcesdump/2005/0913/plan9/sys/src/9/mtx/main.c:116,123 - /n/sourcesdump/2005/0914/plan9/sys/src/9/mtx/main.c:116,123 * Then early kproc's will have a root and dot. */ up->slash = namec("#/", Atodir, 0, 0); - cnameclose(up->slash->name); - up->slash->name = newcname("/"); + pathclose(up->slash->path); + up->slash->path = newpath("/"); up->dot = cclone(up->slash); chandevinit(); [rsc] --rw-rw-r-- M 57833 glenda sys 14691 Sep 13 00:37 sys/src/9/pc/main.c /n/sourcesdump/2005/0913/plan9/sys/src/9/pc/main.c:166,173 - /n/sourcesdump/2005/0914/plan9/sys/src/9/pc/main.c:166,173 * Then early kproc's will have a root and dot. */ up->slash = namec("#/", Atodir, 0, 0); - cnameclose(up->slash->name); - up->slash->name = newcname("/"); + pathclose(up->slash->path); + up->slash->path = newpath("/"); up->dot = cclone(up->slash); chandevinit(); [rsc] --rw-rw-r-- M 57833 glenda sys 9241 Sep 13 00:36 sys/src/9/port/cache.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/cache.c:148,154 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/cache.c:148,154 o = e->start+e->len; } pprint("%s: 0x%lux.0x%lux %d %d %s (%d %c)\n", - s, m->qid.path, m->qid.vers, m->type, m->dev, c->name, nb, ct ? 'C' : 'N'); + s, m->qid.path, m->qid.vers, m->type, m->dev, c->path, nb, ct ? 'C' : 'N'); for(e = m->list; e; e = e->next) { pprint("\t%4d %5d %4d %lux\n", [rsc] --rw-rw-r-- M 57833 glenda sys 33640 Sep 13 00:35 sys/src/9/port/chan.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:6,16 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:6,44 #include "../port/error.h" int chandebug=0; /* toggled by sysr1 */ - QLock chanprint; /* probably asking for trouble (deadlocks) -rsc */ + #define DBG if(chandebug)iprint - int domount(Chan**, Mhead**); + enum + { + PATHSLOP = 20, + PATHMSLOP = 20, + }; - void + struct + { + Lock; + int fid; + Chan *free; + Chan *list; + }chanalloc; + + typedef struct Elemlist Elemlist; + + struct Elemlist + { + char *aname; /* original name */ + char *name; /* copy of name, so '/' can be overwritten */ + int nelems; + char **elems; + int *off; + int mustbedir; + int nerror; + int prefix; + }; + + #define SEP(c) ((c) == 0 || (c) == '/') + + static void dumpmount(void) /* DEBUGGING */ { Pgrp *pg; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:27,46 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:55,74 return; } rlock(&pg->ns); - if(waserror()) { + 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(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->path->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) (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); + print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->path->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev); } } poperror(); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:47,95 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:75,92 runlock(&pg->ns); } - char* - channame(Chan *c) /* DEBUGGING */ + chanpath(Chan *c) { if(c == nil) return ""; - if(c->name == nil) - return ""; - if(c->name->s == nil) - return ""; - return c->name->s; + if(c->path == nil) + return ""; + if(c->path->s == nil) + return ""; + return c->path->s; } - enum - { - CNAMESLOP = 20 - }; - - struct - { - Lock; - int fid; - Chan *free; - Chan *list; - }chanalloc; - - typedef struct Elemlist Elemlist; - - struct Elemlist - { - char *aname; /* original name */ - char *name; /* copy of name, so '/' can be overwritten */ - int nelems; - char **elems; - int *off; - int mustbedir; - int nerror; - int prefix; - }; - - #define SEP(c) ((c) == 0 || (c) == '/') - void cleancname(Cname*); - int isdotdot(char *p) { /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:230,236 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:227,233 chanalloc.free = c->next; unlock(&chanalloc); - if(c == nil) { + if(c == nil){ c = smalloc(sizeof(Chan)); lock(&chanalloc); c->fid = ++chanalloc.fid; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:256,330 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:253,435 c->mcp = 0; c->mux = 0; memset(&c->mqid, 0, sizeof(c->mqid)); - c->name = 0; + c->path = 0; c->ismtpt = 0; + return c; } - static Ref ncname; + Ref npath; - Cname* - newcname(char *s) + Path* + newpath(char *s) { - Cname *n; int i; + Path *p; - n = smalloc(sizeof(Cname)); + p = smalloc(sizeof(Path)); 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; + p->len = i; + p->alen = i+PATHSLOP; + p->s = smalloc(p->alen); + memmove(p->s, s, i+1); + p->ref = 1; + incref(&npath); + + /* + * Cannot use newpath for arbitrary names because the mtpt + * array will not be populated correctly. The names #/ and / are + * allowed, but other names with / in them draw warnings. + */ + if(strchr(s, '/') && strcmp(s, "#/") != 0 && strcmp(s, "/") != 0) + print("newpath: %s from %lux\n", s, getcallerpc(&s)); + + p->mlen = 1; + p->malen = PATHMSLOP; + p->mtpt = smalloc(p->malen*sizeof p->mtpt[0]); + return p; } + static Path* + copypath(Path *p) + { + int i; + Path *pp; + + pp = smalloc(sizeof(Path)); + pp->ref = 1; + incref(&npath); + DBG("copypath %s %p => %p\n", p->s, p, pp); + + pp->len = p->len; + pp->alen = p->alen; + pp->s = smalloc(p->alen); + memmove(pp->s, p->s, p->len+1); + + pp->mlen = p->mlen; + pp->malen = p->malen; + pp->mtpt = smalloc(p->malen*sizeof pp->mtpt[0]); + for(i=0; imlen; i++){ + pp->mtpt[i] = p->mtpt[i]; + if(pp->mtpt[i]) + incref(pp->mtpt[i]); + } + + return pp; + } + void - cnameclose(Cname *n) + pathclose(Path *p) { - if(n == nil) + int i; + + if(p == nil) return; - if(decref(n)) + //XXX + DBG("pathclose %p %s ref=%ld =>", p, p->s, p->ref); + for(i=0; imlen; i++) + DBG(" %p", p->mtpt[i]); + DBG("\n"); + + if(decref(p)) return; - decref(&ncname); - free(n->s); - free(n); + decref(&npath); + free(p->s); + for(i=0; imlen; i++) + if(p->mtpt[i]) + cclose(p->mtpt[i]); + free(p->mtpt); + free(p); } - Cname* - addelem(Cname *n, char *s) + /* + * In place, rewrite name to compress multiple /, eliminate ., and process .. + * (Really only called to remove a trailing .. that has been added. + * Otherwise would need to update n->mtpt as well.) + */ + static void + fixdotdotname(Path *p) { - int i, a; - char *t; - Cname *new; + char *r; - if(s[0]=='.' && s[1]=='\0') - return n; + if(p->s[0] == '#'){ + r = strchr(p->s, '/'); + if(r == nil) + return; + cleanname(r); - if(n->ref > 1){ + /* + * The correct name is #i rather than #i/, + * but the correct name of #/ is #/. + */ + if(strcmp(r, "/")==0 && p->s[1] != '/') + *r = '\0'; + }else + cleanname(p->s); + p->len = strlen(p->s); + } + + static Path* + uniquepath(Path *p) + { + Path *new; + + if(p->ref > 1){ /* copy on write */ - new = newcname(n->s); - cnameclose(n); - n = new; + new = copypath(p); + pathclose(p); + p = new; } + return p; + } + static Path* + addelem(Path *p, char *s, Chan *from) + { + char *t; + int a, i; + Chan *c, **tt; + + if(s[0]=='.' && s[1]=='\0') + return p; + + p = uniquepath(p); + i = strlen(s); - if(n->len+1+i+1 > n->alen){ - a = n->len+1+i+1 + CNAMESLOP; + if(p->len+1+i+1 > p->alen){ + a = p->len+1+i+1 + PATHSLOP; t = smalloc(a); - memmove(t, n->s, n->len+1); - free(n->s); - n->s = t; - n->alen = a; + memmove(t, p->s, p->len+1); + free(p->s); + p->s = t; + p->alen = a; } - if(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/') /* don't insert extra slash if one is present */ - n->s[n->len++] = '/'; - memmove(n->s+n->len, s, i+1); - n->len += i; - if(isdotdot(s)) - cleancname(n); - return n; + /* don't insert extra slash if one is present */ + if(p->len>0 && p->s[p->len-1]!='/' && s[0]!='/') + p->s[p->len++] = '/'; + memmove(p->s+p->len, s, i+1); + p->len += i; + if(isdotdot(s)){ + fixdotdotname(p); + DBG("addelem %s .. => rm %p\n", p->s, p->mtpt[p->mlen-1]); + if(p->mlen>0 && (c = p->mtpt[--p->mlen])){ + p->mtpt[p->mlen] = nil; + cclose(c); + } + }else{ + if(p->mlen >= p->malen){ + p->malen = p->mlen+1+PATHMSLOP; + tt = smalloc(p->malen*sizeof tt[0]); + memmove(tt, p->mtpt, p->mlen*sizeof tt[0]); + free(p->mtpt); + p->mtpt = tt; + } + DBG("addelem %s %s => add %p\n", p->s, s, from); + p->mtpt[p->mlen++] = from; + if(from) + incref(from); + } + return p; } void /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:355,361 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:460,467 c->mchan = nil; } - cnameclose(c->name); + pathclose(c->path); + c->path = nil; lock(&chanalloc); c->next = chanalloc.free; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:369,374 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:475,481 if(c->flag&CFREE) panic("cclose %lux", getcallerpc(&c)); + DBG("cclose %p name=%s ref=%ld\n", c, c->path->s, c->ref); if(decref(c)) return; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:387,393 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:494,500 { Chan *nc; - if(c->ref != 1) { + if(c->ref != 1){ nc = cclone(c); cclose(c); c = nc; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:403,413 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:510,520 } int - eqchan(Chan *a, Chan *b, int pathonly) + eqchan(Chan *a, Chan *b, int skipvers) { if(a->qid.path != b->qid.path) return 0; - if(!pathonly && a->qid.vers!=b->qid.vers) + if(!skipvers && a->qid.vers!=b->qid.vers) return 0; if(a->type != b->type) return 0; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:417,427 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:524,534 } int - eqchantdqid(Chan *a, int type, int dev, Qid qid, int pathonly) + eqchantdqid(Chan *a, int type, int dev, Qid qid, int skipvers) { if(a->qid.path != qid.path) return 0; - if(!pathonly && a->qid.vers!=qid.vers) + if(!skipvers && a->qid.vers!=qid.vers) return 0; if(a->type != type) return 0; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:439,452 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:546,551 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; } /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:453,468 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:552,568 int cmount(Chan **newp, Chan *old, int flag, char *spec) { - Pgrp *pg; int order, flg; + Chan *new; Mhead *m, **l, *mh; Mount *nm, *f, *um, **h; - Chan *new; + Pgrp *pg; if(QTDIR & (old->qid.type^(*newp)->qid.type)) error(Emount); - if(old->umh)print("cmount old extra umh\n"); + if(old->umh) + print("cmount: unexpected umh, caller %.8lux\n", getcallerpc(&newp)); order = flag&MORDER; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:473,492 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:573,594 mh = new->umh; /* - * 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.) + * 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 + * work. + * + * The check of mount->mflag allows 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 + * see an easier way at the moment. */ if((flag&MCREATE) && mh && mh->mount && (mh->mount->next || !(mh->mount->mflag&MCREATE))) /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:496,508 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:598,610 wlock(&pg->ns); l = &MOUNTH(pg, old->qid); - for(m = *l; m; m = m->hash) { + for(m = *l; m; m = m->hash){ if(eqchan(m->from, old, 1)) break; l = &m->hash; } - if(m == nil) { + if(m == nil){ /* * nothing mounted here yet. create a mount * head and add to the hash table. /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:525,531 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:627,633 wunlock(&pg->ns); nm = newmount(m, new, flag, spec); - if(mh != nil && mh->mount != nil) { + if(mh != nil && mh->mount != nil){ /* * copy a union when binding it onto a directory */ /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:534,540 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:636,642 flg = MAFTER; h = &nm->next; um = mh->mount; - for(um = um->next; um; um = um->next) { + for(um = um->next; um; um = um->next){ f = newmount(m, um->to, flg, um->spec); *h = f; h = &f->next; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:541,547 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:643,649 } } - if(m->mount && order == MREPL) { + if(m->mount && order == MREPL){ mountfree(m->mount); m->mount = 0; } /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:549,560 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:651,661 if(flag & MCREATE) nm->mflag |= MCREATE; - if(m->mount && order == MAFTER) { + if(m->mount && order == MAFTER){ for(f = m->mount; f->next; f = f->next) ; f->next = nm; - } - else { + }else{ for(f = nm; f->next; f = f->next) ; f->next = m->mount; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:589,607 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:690,708 wlock(&pg->ns); l = &MOUNTH(pg, mnt->qid); - for(m = *l; m; m = m->hash) { + for(m = *l; m; m = m->hash){ if(eqchan(m->from, mnt, 1)) break; l = &m->hash; } - if(m == 0) { + if(m == 0){ wunlock(&pg->ns); error(Eunmount); } wlock(&m->lock); - if(mounted == 0) { + if(mounted == 0){ *l = m->hash; wunlock(&pg->ns); mountfree(m->mount); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:613,626 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:714,727 } p = &m->mount; - for(f = *p; f; f = f->next) { + for(f = *p; f; f = f->next){ /* BUG: Needs to be 2 pass */ if(eqchan(f->to, mounted, 1) || - (f->to->mchan && eqchan(f->to->mchan, mounted, 1))) { + (f->to->mchan && eqchan(f->to->mchan, mounted, 1))){ *p = f->next; f->next = 0; mountfree(f); - if(m->mount == nil) { + if(m->mount == nil){ *l = m->hash; cclose(m->from); wunlock(&m->lock); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:650,661 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:751,763 error("clone failed"); nc = wq->clone; free(wq); - nc->name = c->name; - if(c->name) - incref(c->name); + nc->path = c->path; + if(c->path) + incref(c->path); return nc; } + /* also used by sysfile.c:/^mountfix */ int findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid) { /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:693,750 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:795,855 return 0; } - int - domount(Chan **cp, Mhead **mp) + /* + * Calls findmount but also updates path. + */ + static int + domount(Chan **cp, Mhead **mp, Path **path) { - return findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid); + Chan **lc; + Path *p; + + if(findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid) == 0) + return 0; + + if(path){ + p = *path; + p = uniquepath(p); + if(p->mlen <= 0) + print("domount: path %s has mlen==%d\n", p->s, p->mlen); + else{ + lc = &p->mtpt[p->mlen-1]; + DBG("domount %p %s => add %p (was %p)\n", p, p->s, (*mp)->from, p->mtpt[p->mlen-1]); + incref((*mp)->from); + if(*lc) + cclose(*lc); + *lc = (*mp)->from; + } + *path = p; + } + return 1; } - Chan* - undomount(Chan *c, Cname *name) + /* + * If c is the right-hand-side of a mount point, returns the left hand side. + * Changes name to reflect the fact that we've uncrossed the mountpoint, + * so name had better be ours to change! + */ + static Chan* + undomount(Chan *c, Path *path) { Chan *nc; - Pgrp *pg; - Mount *t; - Mhead **h, **he, *f; - pg = up->pgrp; - rlock(&pg->ns); - if(waserror()) { - runlock(&pg->ns); - nexterror(); - } + if(path->ref != 1 || path->mlen == 0) + print("undomount: path %s ref %ld mlen %d caller %lux\n", + path->s, path->ref, path->mlen, getcallerpc(&c)); - he = &pg->mnthash[MNTHASH]; - for(h = pg->mnthash; h < he; h++) { - for(f = *h; f; f = f->hash) { - if(strcmp(f->from->name->s, name->s) != 0) - continue; - for(t = f->mount; t; t = t->next) { - if(eqchan(c, t->to, 1)) { - /* - * 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, name->s) != 0) - continue; - nc = t->head->from; - incref(nc); - cclose(c); - c = nc; - break; - } - } - } + if(path->mlen>0 && (nc=path->mtpt[path->mlen-1]) != nil){ + DBG("undomount %p %s => remove %p\n", path, path->s, nc); + cclose(c); + path->mtpt[path->mlen-1] = nil; + c = nc; } - poperror(); - runlock(&pg->ns); return c; } /* - * Walk but catch errors and return nil instead. + * Call dev walk but catch errors. */ static Walkqid* ewalk(Chan *c, Chan *nc, char **name, int nname) /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:767,782 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:872,887 walk(Chan **cp, char **names, int nnames, int nomount, int *nerror) { int dev, dotdot, i, n, nhave, ntry, type; - Chan *c, *nc; - Cname *cname; - Mount *f; + Chan *c, *nc, *mtpt; + Path *path; Mhead *mh, *nmh; + Mount *f; Walkqid *wq; c = *cp; incref(c); - cname = c->name; - incref(cname); + path = c->path; + incref(path); mh = nil; /* /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:787,799 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:892,904 * 4. repeat. * * An invariant is that each time through the loop, c is on the undomount - * side of the mount point, and c's name is cname. + * side of the mount point, and c's full path is path. */ for(nhave=0; nhaveqid.type&QTDIR)==0){ if(nerror) *nerror = nhave; - cnameclose(cname); + pathclose(path); cclose(c); strcpy(up->errstr, Enotdir); if(mh != nil) /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:816,823 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:921,928 } if(!dotdot && !nomount) - domount(&c, &mh); - + domount(&c, &mh, &path); + type = c->type; dev = c->dev; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:839,845 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:944,950 } if(wq == nil){ cclose(c); - cnameclose(cname); + pathclose(path); if(nerror) *nerror = nhave+1; if(mh != nil) /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:853,863 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:958,969 assert(wq->nqid == 1); assert(wq->clone != nil); - cname = addelem(cname, ".."); - nc = undomount(wq->clone, cname); + path = addelem(path, "..", nil); + nc = undomount(wq->clone, path); n = 1; }else{ nc = nil; + nmh = nil; if(!nomount) for(i=0; inqid && iqid[i])) /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:865,871 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:971,977 if(nc == nil){ /* no mount points along path */ if(wq->clone == nil){ cclose(c); - cnameclose(cname); + pathclose(path); if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){ if(nerror) *nerror = nhave+wq->nqid+1; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:889,896 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:995,1006 } n = i+1; } - for(i=0; ifrom; + path = addelem(path, names[nhave+i], mtpt); + } } cclose(c); c = nc; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:909,916 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1019,1026 c->umh = nil; } - cnameclose(c->name); - c->name = cname; + pathclose(c->path); + c->path = path; cclose(*cp); *cp = c; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:929,940 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1039,1050 Mount *f; rlock(&m->lock); - if(waserror()) { + if(waserror()){ runlock(&m->lock); nexterror(); } - for(f = m->mount; f; f = f->next) { - if(f->mflag&MCREATE) { + for(f = m->mount; f; f = f->next){ + if(f->mflag&MCREATE){ nc = cclone(f->to); runlock(&m->lock); poperror(); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:951,981 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1061,1066 { } - /* - * In place, rewrite name to compress multiple /, eliminate ., and process .. - */ - void - cleancname(Cname *n) - { - char *p; - - if(n->s[0] == '#'){ - p = strchr(n->s, '/'); - if(p == nil) - return; - cleanname(p); - - /* - * 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); - } - static void growparse(Elemlist *e) { /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1035,1041 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1120,1126 name = slash; } - if(chandebug){ + if(0 && chandebug){ int i; print("parsename %s:", e->name); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1129,1135 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1214,1220 { int len, n, t, nomount; Chan *c, *cnew; - Cname *cname; + Path *path; Elemlist e; Rune r; Mhead *m; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1143,1148 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1228,1234 free(aname); nexterror(); } + DBG("namec %s %d %d\n", aname, amode, omode); name = aname; /* /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1217,1223 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1303,1309 if(e.off[e.nerror]==0) print("nerror=%d but off=%d\n", e.nerror, e.off[e.nerror]); - if(chandebug) + if(0 && chandebug) print("showing %d+%d/%d (of %d) of %s (%d %d)\n", e.prefix, e.off[e.nerror], e.nerror, e.nelems, aname, e.off[0], e.off[1]); len = e.prefix+e.off[e.nerror]; free(e.off); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1225,1231 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1311,1317 } /* - * Build a list of elements in the path. + * Build a list of elements in the name. */ parsename(name, &e); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1261,1269 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1347,1356 switch(amode){ case Abind: + /* no need to maintain path - cannot dotdot an Abind */ m = nil; if(!nomount) - domount(&c, &m); + domount(&c, &m, nil); if(c->umh != nil) putmhead(c->umh); c->umh = m; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1273,1291 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1360,1378 case Aremove: case Aopen: Open: - /* save the name; domount might change c */ - cname = c->name; - incref(cname); + /* save&update the name; domount might change c */ + path = c->path; + incref(path); m = nil; if(!nomount) - domount(&c, &m); + domount(&c, &m, &path); /* 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; + pathclose(c->path); + c->path = path; /* record whether c is on a mount point */ c->ismtpt = m!=nil; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1414,1422 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1501,1509 * if findmount gave us a new Chan. */ cnew = cunique(cnew); - cnameclose(cnew->name); - cnew->name = c->name; - incref(cnew->name); + pathclose(cnew->path); + cnew->path = c->path; + incref(cnew->path); devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm); poperror(); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1428,1434 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1515,1521 putmhead(m); cclose(c); c = cnew; - c->name = addelem(c->name, e.elems[e.nelems-1]); + c->path = addelem(c->path, e.elems[e.nelems-1], nil); break; }else{ /* create failed */ cclose(cnew); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/chan.c:1513,1524 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/chan.c:1600,1611 Rune r; name = aname; - if(((ulong)name & KZERO) != KZERO) { + if(((ulong)name & KZERO) != KZERO){ if(!dup) print("warning: validname called from %lux with user pointer", pc); p = name; t = BY2PG-((ulong)p&(BY2PG-1)); - while((ename=vmemchr(p, 0, t)) == nil) { + while((ename=vmemchr(p, 0, t)) == nil){ p += t; t = BY2PG; } [rsc] --rw-rw-r-- M 57833 glenda sys 8246 Sep 13 00:36 sys/src/9/port/dev.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/dev.c:135,141 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/dev.c:135,141 spec = ""; buf = smalloc(4+strlen(spec)+1); sprint(buf, "#%C%s", tc, spec); - c->name = newcname(buf); + c->path = newpath(buf); free(buf); return c; } /n/sourcesdump/2005/0913/plan9/sys/src/9/port/dev.c:269,280 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/dev.c:269,280 switch((*gen)(c, nil, tab, ntab, i, &dir)){ case -1: if(c->qid.type & QTDIR){ - if(c->name == nil) + if(c->path == nil) elem = "???"; - else if(strcmp(c->name->s, "/") == 0) + else if(strcmp(c->path->s, "/") == 0) elem = "/"; else - for(elem=p=c->name->s; *p; p++) + for(elem=p=c->path->s; *p; p++) if(*p == '/') elem = p+1; devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir); [rsc] --rw-rw-r-- M 57833 glenda sys 21545 Sep 13 00:36 sys/src/9/port/devmnt.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/devmnt.c:771,781 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/devmnt.c:771,781 if(t == r->request.type+1) break; sn = "?"; - if(m->c->name != nil) - sn = m->c->name->s; + if(m->c->path != nil) + sn = m->c->path->s; cn = "?"; - if(r->c != nil && r->c->name != nil) - cn = r->c->name->s; + if(r->c != nil && r->c->path != nil) + cn = r->c->path->s; print("mnt: proc %s %lud: mismatch from %s %s rep 0x%lux tag %d fid %d T%d R%d rp %d\n", up->text, up->pid, sn, cn, r, r->request.tag, r->request.fid, r->request.type, /n/sourcesdump/2005/0913/plan9/sys/src/9/port/devmnt.c:1150,1161 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/devmnt.c:1150,1161 /* This routine is mostly vestiges of prior lives; now it's just sanity checking */ if(c->mchan == nil) - panic("mntchk 1: nil mchan c %s\n", channame(c)); + panic("mntchk 1: nil mchan c %s\n", chanpath(c)); m = c->mchan->mux; if(m == nil) - print("mntchk 2: nil mux c %s c->mchan %s \n", channame(c), channame(c->mchan)); + print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan)); /* * Was it closed and reused (was error(Eshutdown); now, it cannot happen) [rsc] --rw-rw-r-- M 57833 glenda sys 28465 Sep 13 00:36 sys/src/9/port/devproc.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/devproc.c:539,545 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/devproc.c:539,545 &"r w rw"[(c->mode&3)<<1], devtab[c->type]->dc, c->dev, c->qid.path, w, c->qid.vers, c->qid.type, - c->iounit, c->offset, c->name->s); + c->iounit, c->offset, c->path->s); return n; } /n/sourcesdump/2005/0913/plan9/sys/src/9/port/devproc.c:570,576 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/devproc.c:570,576 nexterror(); } - n = readstr(0, a, count, p->dot->name->s); + n = readstr(0, a, count, p->dot->path->s); n += snprint(a+n, count-n, "\n"); offset = procoffset(offset, a, &n); /* compute width of qid.path */ /n/sourcesdump/2005/0913/plan9/sys/src/9/port/devproc.c:935,955 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/devproc.c:935,955 mntscan(mw, p); if(mw->mh == 0){ mw->cddone = 1; - i = snprint(a, n, "cd %s\n", p->dot->name->s); + i = snprint(a, n, "cd %s\n", p->dot->path->s); qunlock(&p->debug); poperror(); return i; } int2flag(mw->cm->mflag, flag); - if(strcmp(mw->cm->to->name->s, "#M") == 0){ + if(strcmp(mw->cm->to->path->s, "#M") == 0){ srv = srvname(mw->cm->to->mchan); i = snprint(a, n, "mount %s %s %s %s\n", flag, - srv==nil? mw->cm->to->mchan->name->s : srv, - mw->mh->from->name->s, mw->cm->spec? mw->cm->spec : ""); + srv==nil? mw->cm->to->mchan->path->s : srv, + mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : ""); free(srv); }else i = snprint(a, n, "bind %s %s %s\n", flag, - mw->cm->to->name->s, mw->mh->from->name->s); + mw->cm->to->path->s, mw->mh->from->path->s); qunlock(&p->debug); poperror(); return i; [rsc] --rw-rw-r-- M 57833 glenda sys 7282 Sep 13 00:36 sys/src/9/port/fault.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/fault.c:44,51 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/fault.c:44,51 { char buf[ERRMAX]; - if(c && c->name){ - snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->name->s, up->errstr); + if(c && c->path){ + snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->path->s, up->errstr); s = buf; } if(up->nerrlab) { [rsc] --rw-rw-r-- M 57833 glenda sys 22608 Sep 13 00:35 sys/src/9/port/portdat.h /n/sourcesdump/2005/0913/plan9/sys/src/9/port/portdat.h:3,9 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/portdat.h:3,8 typedef struct Chan Chan; typedef struct Cmdbuf Cmdbuf; typedef struct Cmdtab Cmdtab; - typedef struct Cname Cname; typedef struct Dev Dev; typedef struct Dirtab Dirtab; typedef struct Edf Edf; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/portdat.h:22,27 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/portdat.h:21,27 typedef struct Mhead Mhead; typedef struct Note Note; typedef struct Page Page; + typedef struct Path Path; typedef struct Palloc Palloc; typedef struct Perf Perf; typedef struct PhysUart PhysUart; /n/sourcesdump/2005/0913/plan9/sys/src/9/port/portdat.h:186,200 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/portdat.h:186,203 }; Chan* mchan; /* channel to mounted server */ Qid mqid; /* qid of root of mount point */ - Cname* name; + Path* path; }; - struct Cname + struct Path { Ref; - int alen; /* allocated length */ - int len; /* strlen(s) */ char *s; + Chan **mtpt; /* mtpt history */ + int len; /* strlen(s) */ + int alen; /* allocated length of s */ + int mlen; /* number of path elements */ + int malen; /* allocated length of mtpt */ }; struct Dev [rsc] --rw-rw-r-- M 57833 glenda sys 11002 Sep 13 00:35 sys/src/9/port/portfns.h /n/sourcesdump/2005/0913/plan9/sys/src/9/port/portfns.h:18,24 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/portfns.h:18,24 void cachedel(Image*, ulong); void cachepage(Page*, Image*); void callwithureg(void(*)(Ureg*)); - char* channame(Chan*); + char* chanpath(Chan*); int canlock(Lock*); int canpage(Proc*); int canqlock(QLock*); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/portfns.h:39,45 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/portfns.h:39,44 long clrfpintr(void); void cmderror(Cmdbuf*, char*); int cmount(Chan**, Chan*, int, char*); - void cnameclose(Cname*); void confinit(void); int consactive(void); void (*consdebug)(void); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/portfns.h:192,202 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/portfns.h:191,201 Mhead* newmhead(Chan*); Mount* newmount(Mhead*, Chan*, int, char*); Page* newpage(int, Segment **, ulong); + Path* newpath(char*); Pgrp* newpgrp(void); Rgrp* newrgrp(void); Proc* newproc(void); void nexterror(void); - Cname* newcname(char*); int notify(Ureg*); int nrand(int); uvlong ns2fastticks(uvlong); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/portfns.h:209,214 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/portfns.h:208,214 void pagersummary(void); void panic(char*, ...); Cmdbuf* parsecmd(char *a, int n); + void pathclose(Path*); ulong perfticks(void); void pexit(char*, int); int preempted(void); [rsc] --rw-rw-r-- M 57833 glenda sys 22173 Sep 13 00:36 sys/src/9/port/sysfile.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/sysfile.c:178,188 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/sysfile.c:178,184 validaddr(arg[1], arg[2], 1); c = fdtochan(arg[0], -1, 0, 1); - - if(c->name == nil) - snprint((char*)arg[1], arg[2], ""); - else - snprint((char*)arg[1], arg[2], "%s", c->name->s); + snprint((char*)arg[1], arg[2], "%s", chanpath(c)); cclose(c); return 0; } /n/sourcesdump/2005/0913/plan9/sys/src/9/port/sysfile.c:918,935 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/sysfile.c:914,931 } static char* - cnamelast(Cname *n) + pathlast(Path *p) { char *s; - if(n == nil) + if(p == nil) return nil; - if(n->len == 0) + if(p->len == 0) return nil; - s = strrchr(n->s, '/'); + s = strrchr(p->s, '/'); if(s) return s+1; - return n->s; + return p->s; } long /n/sourcesdump/2005/0913/plan9/sys/src/9/port/sysfile.c:967,973 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/sysfile.c:963,969 nexterror(); } l = devtab[c->type]->stat(c, (uchar*)arg[1], l); - name = cnamelast(c->name); + name = pathlast(c->path); if(name) l = dirsetname(name, strlen(name), (uchar*)arg[1], l, arg[2]); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/sysfile.c:1199,1209 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/sysfile.c:1195,1205 if(c->ismtpt){ /* * Renaming mount points is disallowed to avoid surprises - * (which should be renamed: the mount point or the mounted Chan?). + * (which should be renamed? the mount point or the mounted Chan?). */ dirname(d, &namelen); if(namelen) - nameerror(channame(c), Eismtpt); + nameerror(chanpath(c), Eismtpt); } l = devtab[c->type]->wstat(c, d, nd); poperror(); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/sysfile.c:1293,1299 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/sysfile.c:1289,1295 /* buf contains a new stat buf; convert to old. yuck. */ if(l <= BIT16SZ) /* buffer too small; time to face reality */ error(old); - name = cnamelast(c->name); + name = pathlast(c->path); if(name) l = dirsetname(name, strlen(name), buf, l, sizeof buf); l = convM2D(buf, l, &d, strs); /n/sourcesdump/2005/0913/plan9/sys/src/9/port/sysfile.c:1327,1333 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/sysfile.c:1323,1329 /* buf contains a new stat buf; convert to old. yuck. */ if(l <= BIT16SZ) /* buffer too small; time to face reality */ error(old); - name = cnamelast(c->name); + name = pathlast(c->path); if(name) l = dirsetname(name, strlen(name), buf, l, sizeof buf); l = convM2D(buf, l, &d, strs); [rsc] --rw-rw-r-- M 57833 glenda sys 15164 Sep 13 00:36 sys/src/9/port/sysproc.c /n/sourcesdump/2005/0913/plan9/sys/src/9/port/sysproc.c:16,21 - /n/sourcesdump/2005/0914/plan9/sys/src/9/port/sysproc.c:16,24 long sysr1(ulong*) { + extern int chandebug; + + chandebug = !chandebug; checkpages(); return 0; } [rsc] --rw-rw-r-- M 57833 presotto sys 9039 Sep 13 00:37 sys/src/9/ppc/main.c /n/sourcesdump/2005/0913/plan9/sys/src/9/ppc/main.c:160,167 - /n/sourcesdump/2005/0914/plan9/sys/src/9/ppc/main.c:160,167 * Then early kproc's will have a root and dot. */ up->slash = namec("#/", Atodir, 0, 0); - cnameclose(up->slash->name); - up->slash->name = newcname("/"); + pathclose(up->slash->path); + up->slash->path = newpath("/"); up->dot = cclone(up->slash); chandevinit();