static int envgen(Chan *c, char *name, Dirtab* dir, int i, int s, Dir *dp) { Proc *up = externup(); Egrp *eg; Evalue *e; if(s == DEVDOTDOT){ devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp); return 1; } eg = envgrp(c); rlock(&eg->rwl); e = 0; if(name) e = envlookup(eg, name, -1); else if(s < eg->nent) e = eg->ent[s]; if(e == 0) { runlock(&eg->rwl); return -1; } /* 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); runlock(&eg->rwl); return 1; }
static int32_t envstat(Chan *c, uint8_t *db, int32_t n) { if(c->qid.type & QTDIR) c->qid.vers = envgrp(c)->vers; return devstat(c, db, n, 0, 0, envgen); }
static int32_t envread(Chan *c, void *a, int32_t n, int64_t off) { Egrp *eg; Evalue *e; int32_t offset; if(c->qid.type & QTDIR) return devdirread(c, a, n, 0, 0, envgen); eg = envgrp(c); rlock(&eg->rwl); e = envlookup(eg, nil, c->qid.path); if(e == 0) { runlock(&eg->rwl); error(Enonexist); } offset = off; if(offset > e->len) /* protects against overflow converting int64_t to long */ n = 0; else if(offset + n > e->len) n = e->len - offset; if(n <= 0) n = 0; else memmove(a, e->value+offset, n); runlock(&eg->rwl); return n; }
static int envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Egrp *eg; Evalue *e; if(s == DEVDOTDOT){ devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp); return 1; } eg = envgrp(c); rlock(eg); if(name != nil) e = envlookup(eg, name, -1); else if(s < eg->nent) e = &eg->ent[s]; else e = nil; if(e == nil || name != nil && (strlen(e->name) >= sizeof(up->genbuf))) { runlock(eg); return -1; } /* 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); runlock(eg); return 1; }
static void envremove(Chan *c) { int i; Egrp *eg; Evalue *e; if(c->qid.type & QTDIR) error(Eperm); eg = envgrp(c); wlock(&eg->rwl); e = 0; for(i=0; i<eg->nent; 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++; break; } } wunlock(&eg->rwl); if(e == 0) error(Enonexist); free(e->name); if(e->value) free(e->value); free(e); }
static long envread(Chan *c, void *a, long n, vlong off) { Egrp *eg; Evalue *e; ulong offset = off; if(c->qid.type & QTDIR) return devdirread(c, a, n, 0, 0, envgen); eg = envgrp(c); rlock(eg); if(waserror()){ runlock(eg); nexterror(); } e = envlookup(eg, nil, c->qid.path); if(e == nil) error(Enonexist); if(offset >= e->len || e->value == nil) n = 0; else if(offset + n > e->len) n = e->len - offset; if(n <= 0) n = 0; else memmove(a, e->value+offset, n); runlock(eg); poperror(); return n; }
static Chan* envcreate(Chan *c, char *name, int omode, ulong) { Egrp *eg; Evalue *e; Evalue **ent; if(c->qid.type != QTDIR || !envwriteable(c)) error(Eperm); if(strlen(name) >= sizeof(up->genbuf)) error(Etoolong); omode = openmode(omode); eg = envgrp(c); wlock(eg); if(waserror()) { wunlock(eg); nexterror(); } if(envlookup(eg, name, -1) != nil) error(Eexist); e = smalloc(sizeof(Evalue)); e->name = smalloc(strlen(name)+1); strcpy(e->name, name); 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; } e->qid.path = ++eg->path; e->qid.vers = 0; eg->vers++; eg->ent[eg->nent++] = e; c->qid = e->qid; wunlock(eg); poperror(); c->offset = 0; c->mode = omode; c->flag |= COPEN; return c; }
static Chan* envcreate(Chan *c, char *name, int omode, ulong) { Egrp *eg; Evalue *e; if(c->qid.type != QTDIR || !envwriteable(c)) error(Eperm); if(strlen(name) >= sizeof(up->genbuf)) error(Etoolong); omode = openmode(omode); eg = envgrp(c); wlock(eg); if(waserror()) { wunlock(eg); nexterror(); } if(envlookup(eg, name, -1) != nil) error(Eexist); if(eg->nent == eg->ment){ Evalue *tmp; eg->ment += DELTAENV; if((tmp = realloc(eg->ent, sizeof(eg->ent[0])*eg->ment)) == nil){ eg->ment -= DELTAENV; error(Enomem); } eg->ent = tmp; } eg->vers++; e = &eg->ent[eg->nent++]; e->value = nil; e->len = 0; e->name = smalloc(strlen(name)+1); strcpy(e->name, name); mkqid(&e->qid, ++eg->path, 0, QTFILE); c->qid = e->qid; wunlock(eg); poperror(); c->offset = 0; c->mode = omode; c->flag |= COPEN; return c; }
static void envcreate(Chan *c, char *name, int omode, int i) { Proc *up = externup(); Egrp *eg; Evalue *e; Evalue **ent; if(c->qid.type != QTDIR) error(Eperm); omode = openmode(omode); eg = envgrp(c); wlock(&eg->rwl); if(waserror()) { wunlock(&eg->rwl); nexterror(); } if(envlookup(eg, name, -1)) error(Eexist); e = smalloc(sizeof(Evalue)); e->name = smalloc(strlen(name)+1); strcpy(e->name, name); 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; } e->qid.path = ++eg->path; e->qid.vers = 0; eg->vers++; eg->ent[eg->nent++] = e; c->qid = e->qid; wunlock(&eg->rwl); poperror(); c->offset = 0; c->mode = omode; c->flag |= COPEN; }
static Chan* envopen(Chan *c, int omode) { Egrp *eg; Evalue *e; int trunc; eg = envgrp(c); if(c->qid.type & QTDIR) { if(omode != OREAD) error(Eperm); } else { trunc = omode & OTRUNC; if(omode != OREAD && !envwriteable(c)) error(Eperm); if(trunc) wlock(&eg->rwl); else rlock(&eg->rwl); e = envlookup(eg, nil, c->qid.path); if(e == 0) { if(trunc) wunlock(&eg->rwl); else runlock(&eg->rwl); error(Enonexist); } if(trunc && e->value) { e->qid.vers++; free(e->value); e->value = 0; e->len = 0; } if(trunc) wunlock(&eg->rwl); else runlock(&eg->rwl); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; }
static long envwrite(Chan *c, void *a, long n, vlong off) { char *s; ulong len; Egrp *eg; Evalue *e; ulong offset = off; if(n <= 0) return 0; if(offset > Maxenvsize || n > (Maxenvsize - offset)) error(Etoobig); eg = envgrp(c); wlock(eg); if(waserror()){ wunlock(eg); nexterror(); } e = envlookup(eg, nil, c->qid.path); if(e == nil) error(Enonexist); len = offset+n; if(len > e->len) { s = realloc(e->value, len); if(s == nil) error(Enomem); memset(s+offset, 0, n); e->value = s; e->len = len; } memmove(e->value+offset, a, n); e->qid.vers++; eg->vers++; wunlock(eg); poperror(); return n; }
static void envremove(Chan *c) { Egrp *eg; Evalue *e; if(c->qid.type & QTDIR || !envwriteable(c)) error(Eperm); eg = envgrp(c); wlock(eg); e = envlookup(eg, nil, c->qid.path); if(e == nil){ wunlock(eg); error(Enonexist); } free(e->name); free(e->value); *e = eg->ent[--eg->nent]; eg->vers++; wunlock(eg); }
static int32_t envwrite(Chan *c, void *a, int32_t n, int64_t off) { char *s; Egrp *eg; Evalue *e; int32_t len, offset; if(n <= 0) return 0; offset = off; if(offset > Maxenvsize || n > (Maxenvsize - offset)) error(Etoobig); eg = envgrp(c); wlock(&eg->rwl); e = envlookup(eg, nil, c->qid.path); if(e == 0) { wunlock(&eg->rwl); error(Enonexist); } len = offset+n; if(len > e->len) { s = smalloc(len); if(e->value){ memmove(s, e->value, e->len); free(e->value); } e->value = s; e->len = len; } memmove(e->value+offset, a, n); e->qid.vers++; eg->vers++; wunlock(&eg->rwl); return n; }