summaryrefslogtreecommitdiff
path: root/sys/src/9/port/devsegment.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/src/9/port/devsegment.c')
-rw-r--r--sys/src/9/port/devsegment.c85
1 files changed, 41 insertions, 44 deletions
diff --git a/sys/src/9/port/devsegment.c b/sys/src/9/port/devsegment.c
index b712e1878..4f0e6664d 100644
--- a/sys/src/9/port/devsegment.c
+++ b/sys/src/9/port/devsegment.c
@@ -34,8 +34,8 @@ static Globalseg *globalseg[100];
static Lock globalseglock;
- Segment* (*_globalsegattach)(Proc*, char*);
-static Segment* globalsegattach(Proc *p, char *name);
+ Segment* (*_globalsegattach)(char*);
+static Segment* globalsegattach(char *name);
static Segment* fixedseg(uintptr va, ulong len);
@@ -64,7 +64,7 @@ getgseg(Chan *c)
static void
putgseg(Globalseg *g)
{
- if(decref(g) > 0)
+ if(g == nil || decref(g))
return;
if(g->s != nil)
putseg(g->s);
@@ -103,9 +103,9 @@ segmentgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
q.vers = 0;
q.path = PATH(s, Qsegdir);
q.type = QTDIR;
- devdir(c, q, g->name, 0, g->uid, DMDIR|0777, dp);
+ kstrcpy(up->genbuf, g->name, sizeof up->genbuf);
+ devdir(c, q, up->genbuf, 0, g->uid, DMDIR|0777, dp);
unlock(&globalseglock);
-
break;
case Qsegdir:
if(s == DEVDOTDOT){
@@ -183,16 +183,6 @@ segmentopen(Chan *c, int omode)
error(Eisdir);
break;
case Qctl:
- g = getgseg(c);
- if(waserror()){
- putgseg(g);
- nexterror();
- }
- devpermcheck(g->uid, g->perm, omode);
- c->aux = g;
- poperror();
- c->flag |= COPEN;
- break;
case Qdata:
g = getgseg(c);
if(waserror()){
@@ -200,27 +190,31 @@ segmentopen(Chan *c, int omode)
nexterror();
}
devpermcheck(g->uid, g->perm, omode);
- if(g->s == nil)
+ if(TYPE(c) == Qdata && g->s == nil)
error("segment not yet allocated");
c->aux = g;
poperror();
- c->flag |= COPEN;
break;
default:
panic("segmentopen");
}
c->mode = openmode(omode);
c->offset = 0;
+ c->flag |= COPEN;
return c;
}
static void
segmentclose(Chan *c)
{
- if(TYPE(c) == Qtopdir)
- return;
- if(c->flag & COPEN)
- putgseg(c->aux);
+ switch(TYPE(c)){
+ case Qctl:
+ case Qdata:
+ if(c->flag & COPEN){
+ putgseg(c->aux);
+ c->aux = nil;
+ }
+ }
}
static Chan*
@@ -232,8 +226,11 @@ segmentcreate(Chan *c, char *name, int omode, ulong perm)
if(TYPE(c) != Qtopdir)
error(Eperm);
+ if(strlen(name) >= sizeof(up->genbuf))
+ error(Etoolong);
+
if(findphysseg(name) != nil)
- error(Eexist);
+ error("name collision with physical segment");
if((perm & DMDIR) == 0)
error(Ebadarg);
@@ -249,10 +246,8 @@ segmentcreate(Chan *c, char *name, int omode, ulong perm)
if(g == nil){
if(xfree < 0)
xfree = x;
- } else {
- if(strcmp(g->name, name) == 0)
- error(Eexist);
- }
+ } else if(strcmp(g->name, name) == 0)
+ error(Eexist);
}
if(xfree < 0)
error("too many global segments");
@@ -269,7 +264,6 @@ segmentcreate(Chan *c, char *name, int omode, ulong perm)
c->qid.type = QTDIR;
c->qid.vers = 0;
c->mode = openmode(omode);
- c->mode = OWRITE;
return c;
}
@@ -330,13 +324,15 @@ segmentwrite(Chan *c, void *a, long n, vlong voff)
va = va&~(BY2PG-1);
if(va == 0 || top > USTKTOP || top <= va)
error(Ebadarg);
- len = (top - va) / BY2PG;
+ len = top - va;
+ if(len > SEGMAXSIZE)
+ error(Enovmem);
if(cb->nf >= 4 && strcmp(cb->f[3], "fixed") == 0){
if(!iseve())
error(Eperm);
- g->s = fixedseg(va, len);
+ g->s = fixedseg(va, len/BY2PG);
} else
- g->s = newseg(SG_SHARED, va, len);
+ g->s = newseg(SG_SHARED, va, len/BY2PG);
} else
error(Ebadctl);
free(cb);
@@ -359,22 +355,27 @@ segmentwstat(Chan *c, uchar *dp, int n)
if(c->qid.type == QTDIR)
error(Eperm);
+ d = nil;
g = getgseg(c);
if(waserror()){
+ free(d);
putgseg(g);
nexterror();
}
-
if(strcmp(g->uid, up->user) && !iseve())
error(Eperm);
d = smalloc(sizeof(Dir)+n);
n = convM2D(dp, n, &d[0], (char*)&d[1]);
- g->perm = d->mode & 0777;
-
+ if(n == 0)
+ error(Eshortstat);
+ if(!emptystr(d->uid))
+ kstrdup(&g->uid, d->uid);
+ if(d->mode != ~0UL)
+ g->perm = d->mode&0777;
+ free(d);
putgseg(g);
poperror();
- free(d);
return n;
}
@@ -399,13 +400,12 @@ segmentremove(Chan *c)
* called by segattach()
*/
static Segment*
-globalsegattach(Proc *p, char *name)
+globalsegattach(char *name)
{
int x;
Globalseg *g;
Segment *s;
- g = nil;
if(waserror()){
unlock(&globalseglock);
nexterror();
@@ -414,19 +414,16 @@ globalsegattach(Proc *p, char *name)
for(x = 0; x < nelem(globalseg); x++){
g = globalseg[x];
if(g != nil && strcmp(g->name, name) == 0)
- break;
- }
- if(x == nelem(globalseg)){
- unlock(&globalseglock);
- poperror();
- return nil;
+ goto Found;
}
+ unlock(&globalseglock);
+ poperror();
+ return nil;
+Found:
devpermcheck(g->uid, g->perm, ORDWR);
s = g->s;
if(s == nil)
error("global segment not assigned a virtual address");
- if(isoverlap(p, s->base, s->top - s->base) != nil)
- error("overlaps existing segment");
incref(s);
unlock(&globalseglock);
poperror();