## diffname port/devenv.c 1990/0227 ## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/devenv.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "devtab.h" /* * An environment value is kept in some number of contiguous * Envvals, with the Env's val pointing at the first. * Envvals are allocated from the end of a fixed arena, which * is compacted when the arena end is reached. * A `piece' (number of contiguous Envvals) is free to be * reclaimed if its e pointer is 0. * * Locking: an env's val can change by compaction, so lock * an env before using its value. A pgrp env[] slot can go * to 0 and the corresponding env freed (by envremove()), so * lock the pgrp around the use of a value retrieved from a slot. * Lock in order: pgrp, envalloc, env (but ok to skip envalloc * lock if there is no possibility of blocking). */ struct Envval { ulong n; /* number of Envval's (including this) in this piece */ ulong len; /* how much of dat[] is valid */ Env *e; /* the Env whose val points here */ char dat[4]; /* possibly extends into further envvals after this */ }; /* number of contiguous Envvals needed to hold n characters */ #define EVNEEDED(n) ((n)<4? 1 : 1+((n)+(sizeof(Envval))-1-4)/(sizeof(Envval))) struct { Lock; Envval *arena; Envval *vfree; Envval *end; Env *efree; Env *earena; }envalloc; void compactenv(Env *, ulong); void envreset(void) { int i, n; n = EVNEEDED(conf.nenvchar); envalloc.arena = ialloc(n*sizeof(Envval), 0); envalloc.vfree = envalloc.arena; envalloc.end = envalloc.arena+n; envalloc.earena = ialloc(conf.nenv*sizeof(Env), 0); envalloc.efree = envalloc.earena; for(i=0; ival points at a value big enough to hold nchars chars. * The caller should fix e->val->len. * envalloc and e should be locked */ void growenval(Env *e, ulong nchars) { Envval *p; ulong n, nfree; n = EVNEEDED(nchars); if(p = e->val){ /* assign = */ if(p->n < n){ if(p+p->n == envalloc.vfree){ compactenv(e, n - p->n); p = e->val; envalloc.vfree += n - p->n; }else{ compactenv(e, n); p = envalloc.vfree; envalloc.vfree += n; memcpy(p, e->val, e->val->n*sizeof(Envval)); p->e = e; e->val->e = 0; e->val = p; } p->n = n; } }else{ compactenv(e, n); p = envalloc.vfree; envalloc.vfree += n; p->n = n; p->e = e; e->val = p; } } /* * Make sure there is room for n Envval's at the end of envalloc.vfree. * Call this with envalloc and e locked. */ void compactenv(Env *e, ulong n) { Envval *p1, *p2; Env *p2e; if(envalloc.end-envalloc.vfree >= n) return; p1 = envalloc.arena; /* dest */ p2 = envalloc.arena; /* source */ while(p2 < envalloc.vfree){ p2e = p2->e; if(p2e == 0){ Free: p2 += p2->n; continue; } if(p2e=envalloc.earena+conf.nenv){ print("%lux not an env\n", p2e); panic("compactenv"); } if(p1 != p2){ if(p2e != e) lock(p2e); if(p2->e != p2e){ /* freed very recently */ print("compactenv p2e moved\n"); if(p2->e) panic("compactenv p2->e %lux\n", p2->e); unlock(p2e); goto Free; } if(p2+p2->n > envalloc.end) panic("compactpte copying too much"); memcpy(p1, p2, p2->n*sizeof(Envval)); p2e->val = p1; if(p2e != e) unlock(p2e); } p2 += p1->n; p1 += p1->n; } envalloc.vfree = p1; if(envalloc.end-envalloc.vfree < n){ print("env compact failed\n"); error(0, Enoenv); } } /* * Return an env with a copy of e's value. * envalloc and e should be locked, * and the value returned will be locked too. */ Env * copyenv(Env *e, int trunc) { Env *ne; int n; ne = envalloc.efree; if(!ne){ print("out of envs\n"); error(0, Enoenv); } envalloc.efree = ne->next; lock(ne); if(waserror()){ unlock(ne); nexterror(); } ne->next = 0; ne->pgref = 1; strncpy(ne->name, e->name, NAMELEN); if(e->val && !trunc){ n = e->val->len; /* * growenval can't hold the lock on another env * because compactenv assumes only one is held */ unlock(e); growenval(ne, n); lock(e); if(n != e->val->len){ print("e changed in copyenv\n"); if(n > ne->val->len) n = ne->val->len; } if((char*)(ne->val+ne->val->n) < ne->val->dat+n) panic("copyenv corrupt"); memcpy(ne->val->dat, e->val->dat, n); ne->val->len = n; } poperror(); return ne; } int envgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) { Env *e; Pgrp *pg; int ans; pg = u->p->pgrp; lock(pg); if(s >= pg->nenv) ans = -1; else{ e = pg->etab[s].env; if(e == 0) ans = 0; else{ lock(e); devdir(c, s+1, e->name, e->val? e->val->len : 0, 0666, dp); unlock(e); ans = 1; } } unlock(pg); return ans; } Chan* envattach(char *spec) { return devattach('e', spec); } Chan* envclone(Chan *c, Chan *nc) { Pgrp *pg; if(!(c->qid&CHDIR)){ pg = u->p->pgrp; lock(pg); pg->etab[c->qid-1].chref++; unlock(pg); } return devclone(c, nc); } int envwalk(Chan *c, char *name) { Pgrp *pg; if(devwalk(c, name, 0, 0, envgen)){ if(!(c->qid&CHDIR)){ pg = u->p->pgrp; lock(pg); pg->etab[c->qid-1].chref++; unlock(pg); return 1; } } return 0; } void envstat(Chan *c, char *db) { devstat(c, db, 0, 0, envgen); } Chan * envopen(Chan *c, int omode) { Env *e, *ne; Envp *ep; Pgrp *pg; if(omode & (OWRITE|OTRUNC)){ if(c->qid & CHDIR) error(0, Eperm); pg = u->p->pgrp; lock(pg); ep = &pg->etab[c->qid-1]; e = ep->env; if(!e){ unlock(pg); error(0, Egreg); } lock(&envalloc); lock(e); if(waserror()){ unlock(e); unlock(&envalloc); nexterror(); } if(e->pgref == 0) panic("envopen"); if(e->pgref == 1){ if((omode&OTRUNC) && e->val){ e->val->e = 0; e->val = 0; } }else{ ne = copyenv(e, omode&OTRUNC); e->pgref--; /* it will still be positive */ ep->env = ne; unlock(ne); } poperror(); unlock(e); unlock(&envalloc); unlock(pg); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void envcreate(Chan *c, char *name, int omode, ulong perm) { Env *e; Pgrp *pg; int i; if(c->qid != CHDIR) error(0, Eperm); pg = u->p->pgrp; lock(pg); lock(&envalloc); if(waserror()){ unlock(&envalloc); unlock(pg); nexterror(); } e = envalloc.efree; if(e == 0){ print("out of envs\n"); error(0,Enoenv); } envalloc.efree = e->next; e->next = 0; e->pgref = 1; strncpy(e->name, name, NAMELEN); if(pg->nenv == conf.npgenv){ for(i = 0; inenv; i++) if(pg->etab[i].chref == 0) break; if(i == pg->nenv){ print("out of pgroup envs\n"); error(0, Enoenv); } }else i = pg->nenv++; c->qid = i+1; pg->etab[i].env = e; pg->etab[i].chref = 1; unlock(&envalloc); unlock(pg); c->offset = 0; c->mode = openmode(omode); poperror(); c->flag |= COPEN; } void envremove(Chan *c) { Env *e; Envp *ep; Pgrp *pg; if(c->qid & CHDIR) error(0, Eperm); pg = u->p->pgrp; lock(pg); ep = &pg->etab[c->qid-1]; e = ep->env; if(!e){ unlock(pg); error(0, Enonexist); } ep->env = 0; ep->chref--; envpgclose(e); unlock(pg); } void envwstat(Chan *c, char *db) { int dumpenv(void); dumpenv(); /*DEBUG*/ print("envwstat\n"); error(0, Egreg); } void envclose(Chan * c) { Pgrp *pg; if(c->qid & CHDIR) return; pg = u->p->pgrp; lock(pg); pg->etab[c->qid-1].chref--; unlock(pg); } void envpgclose(Env *e) { lock(&envalloc); lock(e); if(--e->pgref <= 0){ if(e->val){ e->val->e = 0; e->val = 0; } e->next = envalloc.efree; envalloc.efree = e; } unlock(e); unlock(&envalloc); } long envread(Chan *c, void *va, long n) { Env *e; Envval *ev; char *p; long vn; Pgrp *pg; char *a = va; if(c->qid & CHDIR) return devdirread(c, a, n, 0, 0, envgen); pg = u->p->pgrp; lock(pg); e = pg->etab[c->qid-1].env; if(!e){ unlock(pg); error(0, Eio); } lock(e); ev = e->val; vn = ev? e->val->len : 0; if(c->offset+n > vn) n = vn - c->offset; if(n <= 0) n = 0; else memcpy(a, ev->dat+c->offset, n); unlock(e); unlock(pg); return n; } long envwrite(Chan *c, void *va, long n) { Env *e; char *p; Envval *ev; long vn; Pgrp *pg; char *a = va; if(n <= 0) return 0; pg = u->p->pgrp; lock(pg); e = pg->etab[c->qid-1].env; /* caller checks for CHDIR */ if(!e){ unlock(pg); error(0, Eio); } lock(&envalloc); lock(e); if(waserror()){ unlock(e); unlock(&envalloc); unlock(pg); nexterror(); } if(e->pgref>1) panic("envwrite to non-duped env"); growenval(e, c->offset+n); ev = e->val; vn = ev? ev->len : 0; if(c->offset > vn) error(0, Egreg); /* perhaps should zero fill */ memcpy(ev->dat+c->offset, a, n); e->val->len = c->offset+n; poperror(); unlock(e); unlock(&envalloc); unlock(pg); return n; } void dumpenv(void) { Env *e; Envp *ep; Envval *ev; Pgrp *pg; int i; char hold; pg = u->p->pgrp; for(ep=pg->etab, i=0; inenv; i++, ep++) print("P%d(%lux %d)",i, ep->env, ep->chref); for(e=envalloc.earena; e<&envalloc.earena[conf.nenv]; e++) if(e->pgref){ print("E{%lux %d '%s'}[", e, e->pgref, e->name); if(e->val){ hold = e->val->dat[e->val->len]; e->val->dat[e->val->len] = 0; print("%s", e->val->dat); e->val->dat[e->val->len] = hold; } print("]"); }else if(e->val) print("whoops, free env %lux has val=%lux\n",e,e->val); for(i=0, e=envalloc.efree; e; e=e->next) i++; print("\n%d free envs", i); for(i=0, ev=envalloc.arena; evn) if(!ev->e) i += ev->n*sizeof(Envval); print(" %d free enval chars\n", i+((char *)envalloc.end-(char*)envalloc.vfree)); } void envuserstr(Error *e, char *buf) { consuserstr(e, buf); } void enverrstr(Error *e, char *buf) { rooterrstr(e, buf); } . ## diffname port/devenv.c 1990/03042 ## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/devenv.c /n/bootesdump/1990/03042/sys/src/9/mips/devenv.c 301a unlock(pg); . ## diffname port/devenv.c 1990/0802 ## diff -e /n/bootesdump/1990/03042/sys/src/9/mips/devenv.c /n/bootesdump/1990/0802/sys/src/9/mips/devenv.c 146c panic("compactenv copying too much"); . ## diffname port/devenv.c 1990/11211 ## diff -e /n/bootesdump/1990/0802/sys/src/9/mips/devenv.c /n/bootesdump/1990/11211/sys/src/9/mips/devenv.c 546,558d 503c error(Egreg); /* perhaps should zero fill */ . 487c error(Eio); . 484c e = pg->etab[c->qid.path-1].env; /* caller checks for CHDIR */ . 454c error(Eio); . 451c e = pg->etab[c->qid.path-1].env; . 447c if(c->qid.path & CHDIR) . 416c pg->etab[c->qid.path-1].chref--; . 412c if(c->qid.path & CHDIR) . 404c error(Egreg); . 391c error(Enonexist); . 387c ep = &pg->etab[c->qid.path-1]; . 383,384c if(c->qid.path & CHDIR) error(Eperm); . 365c c->qid.path = i+1; . 361c error(Enoenv); . 349c error(Enoenv); . 336,337c if(c->qid.path != CHDIR) error(Eperm); . 295c error(Egreg); . 291c ep = &pg->etab[c->qid.path-1]; . 287,288c if(c->qid.path & CHDIR) error(Eperm); . 265c pg->etab[c->qid.path-1].chref++; . 262c if(!(c->qid.path&CHDIR)){ . 250c pg->etab[c->qid.path-1].chref++; . 247c if(!(c->qid.path&CHDIR)){ . 227c devdir(c, (Qid){s+1,0}, e->name, e->val? e->val->len : 0, 0666, dp); . 176c error(Enoenv); . 158c error(Enoenv); . ## diffname port/devenv.c 1991/0318 ## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/devenv.c /n/bootesdump/1991/0318/sys/src/9/port/devenv.c 504c memmove(ev->dat+c->offset, a, n); . 464c memmove(a, ev->dat+c->offset, n); . 203c memmove(ne->val->dat, e->val->dat, n); . 147c memmove(p1, p2, p2->n*sizeof(Envval)); . 93c memmove(p, e->val, e->val->n*sizeof(Envval)); . ## diffname port/devenv.c 1991/0411 ## diff -e /n/bootesdump/1991/0318/sys/src/9/port/devenv.c /n/bootesdump/1991/0411/sys/src/9/port/devenv.c 504,505c memmove(ev->dat+offset, a, n); e->val->len = offset+n; . 502c if(offset > vn) . 499c growenval(e, offset+n); . 471c envwrite(Chan *c, void *va, long n, ulong offset) . 464c memmove(a, ev->dat+offset, n); . 459,460c if(offset+n > vn) n = vn - offset; . 438c envread(Chan *c, void *va, long n, ulong offset) . ## diffname port/devenv.c 1991/0419 ## diff -e /n/bootesdump/1991/0411/sys/src/9/port/devenv.c /n/bootesdump/1991/0419/sys/src/9/port/devenv.c 272a Chan* envclwalk(Chan *c, char *name) { return devclwalk(c, name); } . ## diffname port/devenv.c 1991/0427 ## diff -e /n/bootesdump/1991/0419/sys/src/9/port/devenv.c /n/bootesdump/1991/0427/sys/src/9/port/devenv.c 273,278d ## diffname port/devenv.c 1991/0705 ## diff -e /n/bootesdump/1991/0427/sys/src/9/port/devenv.c /n/bootesdump/1991/0705/sys/src/9/port/devenv.c 523,524c eg = u->p->egrp; for(ep=eg->etab, i=0; inenv; i++, ep++) . 519c Egrp *eg; . 509c unlock(eg); . 494c unlock(eg); . 486c unlock(eg); . 482,484c eg = u->p->egrp; lock(eg); e = eg->etab[c->qid.path-1].env; /* caller checks for CHDIR */ . 477c Egrp *eg; . 466c unlock(eg); . 453c unlock(eg); . 449,451c eg = u->p->egrp; lock(eg); e = eg->etab[c->qid.path-1].env; . 444c Egrp *eg; . 414,417c eg = u->p->egrp; lock(eg); eg->etab[c->qid.path-1].chref--; unlock(eg); . 410c Egrp *eg; . 396c unlock(eg); . 390c unlock(eg); . 385,387c eg = u->p->egrp; lock(eg); ep = &eg->etab[c->qid.path-1]; . 381c Egrp *eg; . 369c unlock(eg); . 366,367c eg->etab[i].env = e; eg->etab[i].chref = 1; . 364c i = eg->nenv++; . 359,360c if(i == eg->nenv){ print("out of egroup envs\n"); . 355,357c if(eg->nenv == conf.npgenv){ for(i = 0; inenv; i++) if(eg->etab[i].chref == 0) . 343c unlock(eg); . 338,339c eg = u->p->egrp; lock(eg); . 333c Egrp *eg; . 321c unlock(eg); . 302c unlock(eg); . 294c unlock(eg); . 289,291c eg = u->p->egrp; lock(eg); ep = &eg->etab[c->qid.path-1]; . 284c Egrp *eg; . 263,266c eg = u->p->egrp; lock(eg); eg->etab[c->qid.path-1].chref++; unlock(eg); . 259c Egrp *eg; . 248,251c eg = u->p->egrp; lock(eg); eg->etab[c->qid.path-1].chref++; unlock(eg); . 245c Egrp *eg; . 232c unlock(eg); . 222c e = eg->etab[s].env; . 217,219c eg = u->p->egrp; lock(eg); if(s >= eg->nenv) . 214c Egrp *eg; . ## diffname port/devenv.c 1991/0927 ## diff -e /n/bootesdump/1991/0705/sys/src/9/port/devenv.c /n/bootesdump/1991/0927/sys/src/9/port/devenv.c 545a /* * to let the kernel set environment variables */ void ksetenv(char *ename, char *eval) { Chan *c; char buf[2*NAMELEN]; sprint(buf, "#e/%s", ename); c = namec(buf, Acreate, OWRITE, 0600); (*devtab[c->type].write)(c, eval, strlen(eval), 0); close(c); } . ## diffname port/devenv.c 1991/1018 ## diff -e /n/bootesdump/1991/0927/sys/src/9/port/devenv.c /n/bootesdump/1991/1018/sys/src/9/port/devenv.c 523,544c h = 0; for(t = (uchar*)s; t - (uchar*)s < n; t++) h = (h << 1) ^ *t; h &= EVHASH - 1; for(ev = evhash[h].next; ev; ev = ev->next) if(ev->len == n && memcmp(ev->val, s, n) == 0){ ev->ref++; return ev; } ev = evalloc(n); ev->len = n; memmove(ev->val, s, n); if(ev->next = evhash[h].next) ev->next->prev = ev; evhash[h].next = ev; ev->prev = &evhash[h]; return ev; } /* * called only from newev */ Envval * evalloc(ulong n) { Envval *ev, **p; char *b, *lim; ulong size; n = (n - 1) / ALIGN; size = (n + 1) * ALIGN; p = &envalloc.free[n < EVFREE ? n : EVFREE]; for(ev = *p; ev; ev = *p){ if(ev->len == size){ *p = ev->next; ev->ref = 1; return ev; } p = &ev->next; } /* * make sure we have enough space to allocate the buffer. * if not, use the remaining space for the smallest buffers */ if(size > MAXENV) panic("evalloc"); b = envalloc.block; lim = envalloc.lim; if(!b || lim < b + size + sizeof *ev){ p = &envalloc.free[0]; while(lim >= b + ALIGN + sizeof *ev){ ev = (Envval*)b; ev->len = ALIGN; ev->val = b + sizeof *ev; ev->next = *p; *p = ev; b += ALIGN + sizeof *ev; } b = (char*)VA(kmap(newpage(0, 0, 0))); envalloc.lim = b + BY2PG; } ev = (Envval*)b; ev->val = b + sizeof *ev; ev->ref = 1; envalloc.block = b + size + sizeof *ev; return ev; } /* * called with evlock qlocked */ void evfree(Envval *ev) { int n; if(--ev->ref > 0) return; if(ev->prev) ev->prev->next = ev->next; if(ev->next) ev->next->prev = ev->prev; n = (ev->len + ALIGN - 1) & ~(ALIGN - 1); ev->len = n; n = (n - 1) / ALIGN; if(n > EVFREE) n = EVFREE; ev->next = envalloc.free[n]; envalloc.free[n] = ev; . 519,521c uchar *t; int h; . 516,517d 513,514c /* * called with evlock qlocked */ Envval * newev(char *s, ulong n) . 501,509c olen = ev ? ev->len : 0; qlock(&evlock); if(offset == 0 && n >= olen) e->val = newev(a, n); else{ if(olen > offset) olen = offset; if(ev) memmove(evscratch, ev->val, olen); if(olen < offset) memset(evscratch + olen, '\0', offset - olen); memmove(evscratch + offset, a, n); e->val = newev(evscratch, offset + n); } if(ev) evfree(ev); qunlock(&evlock); qunlock(&eg->ev); . 489,499d 483,487c qlock(&eg->ev); e = &eg->etab[c->qid.path-1]; if(!e->name){ qunlock(&eg->ev); error(Enonexist); . 481a if(offset + n > MAXENV) error(Etoobig); . 476,478c ulong olen; . 474d 472a Egrp *eg; . 471c envwrite(Chan *c, void *a, long n, ulong offset) . 464,466c memmove(a, ev->val + offset, n); qunlock(&eg->ev); . 458,459c vn = ev ? ev->len : 0; if(offset + n > vn) . 456d 450,454c qlock(&eg->ev); e = &eg->etab[c->qid.path-1]; if(!e->name){ qunlock(&eg->ev); error(Enonexist); . 444,445d 442d 439a Egrp *eg; . 438c envread(Chan *c, void *a, long n, ulong offset) . 423,434c qlock(&evlock); if(e->name) evfree(e->name); if(e->val) evfree(e->val); e->name = e->val = 0; qunlock(&evlock); . 412,417c void envpgcopy(Env *t, Env *f) { qlock(&evlock); if(t->name = f->name) t->name->ref++; if(t->val = f->val) t->val->ref++; qunlock(&evlock); . 410c } . 401,404c { error(Eperm); . 396c qunlock(&eg->ev); . 393,394d 386,390c qlock(&eg->ev); e = &eg->etab[c->qid.path-1]; if(!e->name){ qunlock(&eg->ev); . 381a Env *e; . 379,380d 371,372c c->mode = omode; . 351,369c i = e - eg->etab + 1; e->val = 0; qlock(&evlock); e->name = newev(name, strlen(name)+1); qunlock(&evlock); if(i > eg->nenv) eg->nenv = i; qunlock(&eg->ev); c->qid = (Qid){i, 0}; . 339,348c qlock(&eg->ev); e = eg->etab; ne = 0; for(i = 0; i < eg->nenv; i++, e++) if(e->name == 0) ne = e; else if(strcmp(e->name->val, name) == 0){ qunlock(&eg->ev); error(Einuse); } if(ne) e = ne; else if(eg->nenv == conf.npgenv){ print("out of egroup envs\n"); qunlock(&eg->ev); . 337a omode = openmode(omode); . 333a Env *e, *ne; . 332d 323c c->mode = mode; . 305,321c qunlock(&eg->ev); . 297,303c if(omode == (OWRITE|OTRUNC) && e->val){ qlock(&evlock); evfree(e->val); qunlock(&evlock); e->val = 0; . 290,295c qlock(&eg->ev); e = &eg->etab[c->qid.path-1]; if(!e->name){ qunlock(&eg->ev); error(Enonexist); . 288a }else{ . 286,287c mode = openmode(omode); if(c->qid.path & CHDIR){ if(omode != OREAD) . 284a Env *e; int mode; . 282,283d 261,270c return devwalk(c, name, 0, 0, envgen); . 259d 245,252d 232c qunlock(&eg->ev); . 226,228c devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, 0666, dp); . 222,223c e = &eg->etab[s]; if(!e->name) . 218c qlock(&eg->ev); . 214a Env *e; . 213d 71,209d 52,63c evscratch = ialloc(BY2PG, 0); . 48a Envval *newev(char*, ulong); Envval *evalloc(ulong); void evfree(Envval*); . 47c QLock evlock; Envval evhash[EVHASH]; char *evscratch; /* for constructing the contents of a file */ . 39,44c Envval *free[EVFREE+1]; char *block; /* the free page we are allocating from */ char *lim; /* end of block */ . 34,35c enum{ MAXENV = (BY2PG - sizeof(Envval)), EVHASH = 64, EVFREE = 16, ALIGN = 16, }; . 28,31c Envval *next; /* for hashing & easy deletion from hash list */ Envval *prev; ulong len; /* length of val that is valid */ int ref; char *val; . 10,25d ## diffname port/devenv.c 1991/1022 ## diff -e /n/bootesdump/1991/1018/sys/src/9/port/devenv.c /n/bootesdump/1991/1022/sys/src/9/port/devenv.c 400a } void envdump(void) { Envval *ev; int i, j; qlock(&evlock); print("pages allocated: %d\n", envalloc.npage); print("bytes left in page: %d\n", envalloc.lim - envalloc.block); for(i = 0; i < EVFREE + 1; i++){ j = 0; if(i == EVFREE) print("big blocks:\n"); else print("%d byte blocks:\n", (i + 1) * ALIGN); for(ev = envalloc.free[i]; ev; ev = ev->next){ if(j++ == 1000){ print("circular\n"); break; } if(j < 10) print("\tenv %d %lux n%lux p%lux r%d\n", ev->len, ev, ev->next, ev->prev, ev->ref); } } for(i = 0; i < EVHASH; i++){ j = 0; for(ev = evhash[i].next; ev; ev = ev->next){ if(j++ == 1000){ print("hash bucket %d circular\n", i); break; } } } qunlock(&evlock); . 371c . 368a envalloc.npage++; . 30a int npage; /* total pages gotten from newpage() */ . ## diffname port/devenv.c 1991/1024 ## diff -e /n/bootesdump/1991/1022/sys/src/9/port/devenv.c /n/bootesdump/1991/1024/sys/src/9/port/devenv.c 401a ev->prev = 0; . 393a else panic("evfree"); . ## diffname port/devenv.c 1991/1030 ## diff -e /n/bootesdump/1991/1024/sys/src/9/port/devenv.c /n/bootesdump/1991/1030/sys/src/9/port/devenv.c 435a uchar *t, *s; int h, n; s = (uchar*)ev->val; n = ev->len; h = 0; for(t = s; t - s < n; t++) h = (h << 1) ^ *t; h &= EVHASH - 1; if(h != i) print("hash conflict: %d %d\n", i, h); . ## diffname port/devenv.c 1991/1102 ## diff -e /n/bootesdump/1991/1030/sys/src/9/port/devenv.c /n/bootesdump/1991/1102/sys/src/9/port/devenv.c 469a void ksetterm(char *f) { char buf[2*NAMELEN]; sprint(buf, f, conffile); ksetenv("terminal", buf); } . ## diffname port/devenv.c 1991/1105 ## diff -e /n/bootesdump/1991/1102/sys/src/9/port/devenv.c /n/bootesdump/1991/1105/sys/src/9/port/devenv.c 160a print("out of egroup envs\n"); . 159d ## diffname port/devenv.c 1991/1108 ## diff -e /n/bootesdump/1991/1105/sys/src/9/port/devenv.c /n/bootesdump/1991/1108/sys/src/9/port/devenv.c 408,455d ## diffname port/devenv.c 1991/1109 ## diff -e /n/bootesdump/1991/1108/sys/src/9/port/devenv.c /n/bootesdump/1991/1109/sys/src/9/port/devenv.c 69c devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); . ## diffname port/devenv.c 1991/1115 ## diff -e /n/bootesdump/1991/1109/sys/src/9/port/devenv.c /n/bootesdump/1991/1115/sys/src/9/port/devenv.c 204a USED(c); . 198a USED(c, db); . ## diffname port/devenv.c 1991/1121 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devenv.c /n/bootesdump/1991/1121/sys/src/9/port/devenv.c 341,342c size = (n + ALIGN - 1) & ~(ALIGN - 1); n = (size - 1) / ALIGN; . 271c olen = (offset + n + ALIGN - 1) & ~(ALIGN - 1); if(olen > MAXENV) . ## diffname port/devenv.c 1992/0111 ## diff -e /n/bootesdump/1991/1121/sys/src/9/port/devenv.c /n/bootesdump/1992/0111/sys/src/9/port/devenv.c 6c #include "../port/error.h" . ## diffname port/devenv.c 1992/0321 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devenv.c /n/bootesdump/1992/0321/sys/src/9/port/devenv.c 2c #include "../port/lib.h" . ## diffname port/devenv.c 1992/0331 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/devenv.c /n/bootesdump/1992/0331/sys/src/9/port/devenv.c 69c devdir(c, (Qid){s+1, (ulong)e->name}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); . ## diffname port/devenv.c 1992/0622 ## diff -e /n/bootesdump/1992/0331/sys/src/9/port/devenv.c /n/bootesdump/1992/0622/sys/src/9/port/devenv.c 45c evscratch = xalloc(BY2PG); . ## diffname port/devenv.c 1992/0623 ## diff -e /n/bootesdump/1992/0622/sys/src/9/port/devenv.c /n/bootesdump/1992/0623/sys/src/9/port/devenv.c 353,408c memmove(e->value+offset, a, n); qunlock(eg); return n; . 303,351c if(vend > e->len) { s = smalloc(offset+n); memmove(s, e->value, e->len); if(e->value) free(e->value); e->value = s; e->len = vend; . 281,301d 275,278c qlock(eg); for(e = eg->entries; e; e = e->link) if(e->path == c->qid.path) break; if(e == 0) { qunlock(eg); . 273a . 271,272c vend = offset+n; if(vend > Maxenvsize) . 265,267c Evalue *e; . 263a char *s; int vend; . 256,257c memmove(a, e->value+offset, n); qunlock(eg); . 249,252c if(offset + n > e->len) n = e->len - offset; . 243,246c qlock(eg); for(e = eg->entries; e; e = e->link) if(e->path == c->qid.path) break; if(e == 0) { qunlock(eg); . 241a . 236,238c Evalue *e; . 209,231d 192,193c *l = e->link; qunlock(eg); free(e->name); if(e->value) free(e->value); free(e); . 186,189c qlock(eg); l = &eg->entries; for(e = *l; e; e = e->link) { if(e->path == c->qid.path) break; l = &e->link; } if(e == 0) { qunlock(eg); . 184a . 181c Evalue *e, **l; . 163,171c for(e = eg->entries; e; e = e->link) if(strcmp(e->name, name) == 0) error(Einuse); e = smalloc(sizeof(Evalue)); e->name = smalloc(strlen(name)+1); strcpy(e->name, name); e->path = ++eg->path; e->link = eg->entries; eg->entries = e; c->qid = (Qid){e->path, 0}; qunlock(eg); poperror(); . 146,161c qlock(eg); if(waserror()) { qunlock(eg); nexterror(); . 143a . 139,140c Evalue *e; . 129c c->mode = openmode(omode); . 127c qunlock(eg); . 121,125c if(omode == (OWRITE|OTRUNC) && e->value) { free(e->value); e->value = 0; e->len = 0; . 113,118c } else { qlock(eg); for(e = eg->entries; e; e = e->link) if(e->path == c->qid.path) break; if(e == 0) { qunlock(eg); . 106,109c Evalue *e; eg = u->p->egrp; . 73,74c devdir(c, (Qid){e->path, 0}, e->name, e->len, eve, 0666, dp); qunlock(eg); return 1; . 61,71c qlock(eg); for(e = eg->entries; e && s; e = e->link) s--; if(e == 0) { qunlock(eg); return -1; . 57,58c Evalue *e; . 45d 19,41d 12,16c Maxenvsize = 16300, . 10c enum . ## diffname port/devenv.c 1992/0625 ## diff -e /n/bootesdump/1992/0623/sys/src/9/port/devenv.c /n/bootesdump/1992/0625/sys/src/9/port/devenv.c 256a } void envcpy(Egrp *to, Egrp *from) { Evalue **l, *ne, *e; l = &to->entries; qlock(from); for(e = from->entries; e; e = e->link) { ne = smalloc(sizeof(Evalue)); ne->name = smalloc(strlen(e->name)+1); strcpy(ne->name, e->name); if(e->value) { ne->value = smalloc(e->len); memmove(ne->value, e->value, e->len); ne->len = e->len; } ne->path = ++to->path; *l = ne; l = &ne->link; } qunlock(from); } void closeegrp(Egrp *eg) { Evalue *e, *next; if(decref(eg) == 0) { for(e = eg->entries; e; e = next) { next = e->link; free(e->name); if(e->value) free(e->value); free(e); } free(eg); } . 79c if(c->qid.path & CHDIR) { . ## diffname port/devenv.c 1992/0711 ## diff -e /n/bootesdump/1992/0625/sys/src/9/port/devenv.c /n/bootesdump/1992/0711/sys/src/9/port/devenv.c 111a USED(perm); . 30a USED(tab); USED(ntab); . ## diffname port/devenv.c 1992/1107 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/devenv.c /n/bootesdump/1992/1107/sys/src/9/port/devenv.c 270a if(e->name == 0) panic("e->name == 0"); for(p = e->name; *p; p++) if(p - e->name >= NAMELEN) panic("e->name %.*s", NAMELEN, e->name); . 266a char *p; . ## diffname port/devenv.c 1993/0123 ## diff -e /n/bootesdump/1992/1107/sys/src/9/port/devenv.c /n/bootesdump/1993/0123/sys/src/9/port/devenv.c 272,273d 267d ## diffname port/devenv.c 1993/0501 ## diff -e /n/bootesdump/1993/0123/sys/src/9/port/devenv.c /n/fornaxdump/1993/0501/sys/src/brazil/port/devenv.c 316,324d 239c eg = up->egrp; . 203c eg = up->egrp; . 158c eg = up->egrp; . 120c eg = up->egrp; . 81c eg = up->egrp; . 65d 34c eg = up->egrp; . ## diffname port/devenv.c 1995/0108 ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/devenv.c /n/fornaxdump/1995/0108/sys/src/brazil/port/devenv.c 259a } long envbwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); . 222a Block* envbread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } . ## diffname port/devenv.c 1995/0726 ## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/port/devenv.c /n/fornaxdump/1995/0726/sys/src/brazil/port/devenv.c 114d 109c envcreate(Chan *c, char *name, int omode, ulong) . ## diffname port/devenv.c 1995/0804 ## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/port/devenv.c /n/fornaxdump/1995/0804/sys/src/brazil/port/devenv.c 189d 187c envclose(Chan*) . 182d 180c envwstat(Chan*, char*) . 31,33d 26c envgen(Chan *c, Dirtab*, int, int s, Dir *dp) . ## diffname port/devenv.c 1996/0223 ## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/devenv.c /n/fornaxdump/1996/0223/sys/src/brazil/port/devenv.c 8d ## diffname port/devenv.c 1997/0327 ## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/port/devenv.c /n/emeliedump/1997/0327/sys/src/brazil/port/devenv.c 318,319c devtab[c->type]->write(c, eval, strlen(eval), 0); cclose(c); . 261,265c Dev envdevtab = { devreset, devinit, envattach, devclone, envwalk, envstat, envopen, envcreate, envclose, envread, devbread, envwrite, devbwrite, envremove, devwstat, }; . 216,222c static long . 186c static long . 175,181c static void . 143c static void . 104c static void . 70c static Chan* . 64c static void . 52,58c static int . 46c static Chan* . 14,24c static int . ## diffname port/devenv.c 1997/0408 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/devenv.c /n/emeliedump/1997/0408/sys/src/brazil/port/devenv.c 233a 'e', "env", . ## diffname port/devenv.c 1998/0319 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/devenv.c /n/emeliedump/1998/0319/sys/src/brazil/port/devenv.c 200a ulong offset = off; . 195c envwrite(Chan *c, void *a, long n, vlong off) . 168a ulong offset = off; . 165c envread(Chan *c, void *a, long n, vlong off) . ## diffname port/devenv.c 1998/0512 ## diff -e /n/emeliedump/1998/0319/sys/src/brazil/port/devenv.c /n/emeliedump/1998/0512/sys/src/brazil/port/devenv.c 118c . 59c . ## diffname port/devenv.c 1999/0122 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/devenv.c /n/emeliedump/1999/0122/sys/src/brazil/port/devenv.c 272c ne->qid.path = ++to->path; . 230a e->qid.vers++; eg->vers++; . 213,216c e = envlookup(eg, nil, c->qid.path); . 176,179c e = envlookup(eg, nil, c->qid.path); . 161a /* * close can't fail, so errors from remove will be ignored anyway. * since permissions aren't checked, * envremove can't not remove it if its there. */ if(c->flag & CRCLOSE) envremove(c); . 160c envclose(Chan *c) . 151a eg->vers++; . 141c if(e->qid.path == c->qid.path) . 138d 117c c->qid = e->qid; . 114c e->qid.path = ++eg->path; e->qid.vers = 0; eg->vers++; . 106,108c if(envlookup(eg, name, -1)) error(Eexist); . 75c if((omode & OTRUNC) && e->value) { e->qid.vers++; . 67,70c e = envlookup(eg, nil, c->qid.path); . 50a if(c->qid.path & CHDIR) c->qid.vers = up->egrp->vers; . 35a static Evalue* envlookup(Egrp *eg, char *name, ulong qidpath) { Evalue *e; for(e = eg->entries; e; e = e->link) if(e->qid.path == qidpath || (name && strcmp(e->name, name) == 0)) return e; return nil; } . 31c devdir(c, e->qid, e->name, e->len, eve, 0666, dp); . ## diffname port/devenv.c 1999/1230 ## diff -e /n/emeliedump/1999/0122/sys/src/brazil/port/devenv.c /n/emeliedump/1999/1230/sys/src/9/port/devenv.c 19a if(s == DEVDOTDOT){ devdir(c, c->qid, "#e", 0, eve, 0775, dp); return 1; } . ## diffname port/devenv.c 2000/0121 ## diff -e /n/emeliedump/1999/1230/sys/src/9/port/devenv.c /n/emeliedump/2000/0121/sys/src/9/port/devenv.c 243a } . 241,242c if(e->value){ memmove(s, e->value, e->len); . ## diffname port/devenv.c 2001/0510 ## diff -e /n/emeliedump/2000/0121/sys/src/9/port/devenv.c /n/emeliedump/2001/0510/sys/src/9/port/devenv.c 60c Evalue *e; Egrp *eg; int rv; if(c->qid.path == CHDIR && name[0] != '.'){ rv = 0; eg = up->egrp; qlock(eg); for(e = eg->entries; e; e = e->link) if(strcmp(e->name, name) == 0){ rv = 1; c->qid = e->qid; } qunlock(eg); return rv; } else return devwalk(c, name, 0, 0, envgen); . ## diffname port/devenv.c 2001/0527 ## diff -e /n/emeliedump/2001/0510/sys/src/9/port/devenv.c /n/emeliedump/2001/0527/sys/src/9/port/devenv.c 339c char buf[2*KNAMELEN]; . 278d 210c if(c->qid.type & QTDIR) . 165c if(c->qid.type & QTDIR) . 125c if(c->qid.type != QTDIR) . 94c if(c->qid.type & QTDIR) { . 84c return devstat(c, db, n, 0, 0, envgen); . 82c if(c->qid.type & QTDIR) . 79,80c static int envstat(Chan *c, uchar *db, int n) . 60,76c return devwalk(c, nc, name, nname, 0, 0, envgen); . 57,58c static Walkqid* envwalk(Chan *c, Chan *nc, char **name, int nname) . 36c /* make sure name string continues to exist after we release lock */ kstrcpy(up->genbuf, e->name, sizeof up->genbuf); devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp); . 21c devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp); . 15c envgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) . ## diffname port/devenv.c 2001/1204 ## diff -e /n/emeliedump/2001/0527/sys/src/9/port/devenv.c /n/emeliedump/2001/1204/sys/src/9/port/devenv.c 181c * cclose can't fail, so errors from remove will be ignored. . ## diffname port/devenv.c 2002/0109 ## diff -e /n/emeliedump/2001/1204/sys/src/9/port/devenv.c /n/emeliedump/2002/0109/sys/src/9/port/devenv.c 329a } /* * Return a copy of configuration environment as a sequence of strings. * The strings alternate between name and value. A zero length name string * indicates the end of the list */ char * getconfenv(void) { Egrp *eg = &confegrp; Evalue *e; char *p, *q; int n; qlock(eg); if(waserror()) { qunlock(eg); nexterror(); } /* determine size */ n = 0; for(e=eg->entries; e; e=e->link) n += strlen(e->name) + e->len + 2; p = malloc(n + 1); if(p == nil) error(Enomem); q = p; for(e=eg->entries; e; e=e->link) { strcpy(q, e->name); q += strlen(q) + 1; memmove(q, e->value, e->len); q[e->len] = 0; /* move up to the first null */ q += strlen(q) + 1; } *q = 0; poperror(); qunlock(eg); return p; . 325,326c snprint(buf, sizeof(buf), "#e%s/%s", conf?"c":"", ename); . 321c ksetenv(char *ename, char *eval, int conf) . 316a static Egrp* envgrp(Chan *c) { if(c->aux == nil) return up->egrp; return c->aux; } static int envwriteable(Chan *c) { return iseve() || c->aux == nil; } . 262a devshutdown, . 233c eg = envgrp(c); . 199c eg = envgrp(c); . 154c eg = envgrp(c); . 115c eg = envgrp(c); . 84a if(omode != OREAD && !envwriteable(c)) error(Eperm); . 79c eg = envgrp(c); . 69c c->qid.vers = envgrp(c)->vers; . 56c Chan *c; Egrp *egrp = nil; if(spec && *spec) { if(strcmp(spec, "c") == 0) egrp = &confegrp; if(egrp == nil) error(Ebadarg); } c = devattach('e', spec); c->aux = egrp; return c; . 25c eg = envgrp(c); . 13a static Egrp *envgrp(Chan *c); static int envwriteable(Chan *c); static Egrp confegrp; /* global environment group containing the kernel configuration */ . 8d ## diffname port/devenv.c 2002/0405 ## diff -e /n/emeliedump/2002/0109/sys/src/9/port/devenv.c /n/emeliedump/2002/0405/sys/src/9/port/devenv.c 403c runlock(eg); . 380c runlock(eg); . 378c rlock(eg); . 316c runlock(from); . 302c rlock(from); . 271c wunlock(eg); . 255c wunlock(eg); . 252c wlock(eg); . 231c runlock(eg); . 221c rlock(eg); . 218c rlock(eg); . 188c wunlock(eg); . 182c wunlock(eg); . 173c wlock(eg); . 155c wunlock(eg); . 137c wunlock(eg); . 135c wlock(eg); . 115c runlock(eg); . 106c runlock(eg); . 103c rlock(eg); . 43c runlock(eg); . 36c runlock(eg); . 30,31c rlock(eg); . ## diffname port/devenv.c 2002/0407 ## diff -e /n/emeliedump/2002/0405/sys/src/9/port/devenv.c /n/emeliedump/2002/0407/sys/src/9/port/devenv.c 114c if(trunc) wunlock(eg); else runlock(eg); . 108c if(trunc && e->value) { . 105c if(trunc) wunlock(eg); else runlock(eg); . 102c if(trunc) wlock(eg); else rlock(eg); . 99a trunc = omode & OTRUNC; . 92a int trunc; . ## diffname port/devenv.c 2002/0409 ## diff -e /n/emeliedump/2002/0407/sys/src/9/port/devenv.c /n/emeliedump/2002/0409/sys/src/9/port/devenv.c 235c if(offset > e->len) /* protects against overflow converting vlong to ulong */ n = 0; else if(offset + n > e->len) . ## diffname port/devenv.c 2002/0426 ## diff -e /n/emeliedump/2002/0409/sys/src/9/port/devenv.c /n/emeliedump/2002/0426/sys/src/9/port/devenv.c 231c runlock(eg); . ## diffname port/devenv.c 2003/0325 ## diff -e /n/emeliedump/2002/0426/sys/src/9/port/devenv.c /n/emeliedump/2003/0325/sys/src/9/port/devenv.c 404c for(i=0; inent; i++){ e = eg->ent[i]; . 399a } . 398c for(i=0; inent; i++){ e = eg->ent[i]; . 388c int i, n; . 343a free(eg->ent); . 336,338c if(decref(eg) == 0){ for(i=0; inent; i++){ e = eg->ent[i]; . 334c int i; Evalue *e; . 327a to->nent = from->nent; . 325,326c to->ent[i] = ne; . 319c if(e->value){ . 315c to->ment = (from->nent+31)&~31; to->ent = smalloc(to->ment*sizeof(to->ent[0])); for(i=0; inent; i++){ e = from->ent[i]; . 313d 311c int i; Evalue *ne, *e; . 198a if(e == 0) error(Enonexist); . 190,197d 188c } . 184,186c e = 0; for(i=0; inent; i++){ if(eg->ent[i]->qid.path == c->qid.path){ e = eg->ent[i]; eg->nent--; eg->ent[i] = eg->ent[eg->nent]; eg->vers++; . 177c Evalue *e; . 175a int i; . 161,162c eg->ent[eg->nent++] = e; . 157a if(eg->nent == eg->ment){ eg->ment += 32; ent = smalloc(sizeof(eg->ent[0])*eg->ment); if(eg->nent) memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent); free(eg->ent); eg->ent = ent; } . 137a Evalue **ent; . 46,55d 31,32c e = 0; if(name) e = envlookup(eg, name, -1); else if(s < eg->nent) e = eg->ent[s]; . 19c envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) . 17a static Evalue* envlookup(Egrp *eg, char *name, ulong qidpath) { Evalue *e; int i; for(i=0; inent; i++){ e = eg->ent[i]; if(e->qid.path == qidpath || (name && e->name[0]==name[0] && strcmp(e->name, name) == 0)) return e; } return nil; } .