]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/lib9p/srv.c
pc: replace duplicated and broken mmu flush code in vunmap()
[plan9front.git] / sys / src / lib9p / srv.c
index 12b1d7fe5bc53001d764e60a9913ea59d2346d30..207c88f618644a9e4f3827995e245abd9309ba79 100644 (file)
@@ -59,7 +59,8 @@ getreq(Srv *s)
        Req *r;
 
        qlock(&s->rlock);
-       if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){
+       n = read9pmsg(s->infd, s->rbuf, s->msize);
+       if(n <= 0){
                qunlock(&s->rlock);
                return nil;
        }
@@ -165,12 +166,13 @@ walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fi
 static void
 sversion(Srv *srv, Req *r)
 {
-       if(srv->rref.ref != 2){
+       if(srv->rref.ref != 1){
                respond(r, Ebotch);
                return;
        }
        if(strncmp(r->ifcall.version, "9P", 2) != 0){
                r->ofcall.version = "unknown";
+               r->ofcall.msize = 256;
                respond(r, nil);
                return;
        }
@@ -363,6 +365,23 @@ rwalk(Req *r, char *error)
        }
 }
 
+static int
+dirwritable(Fid *fid)
+{
+       File *f;
+
+       f = fid->file;
+       if(f){
+               rlock(f);
+               if(f->parent && !hasperm(f->parent, fid->uid, AWRITE)){
+                       runlock(f);
+                       return 0;
+               }
+               runlock(f);
+       }
+       return 1;
+}
+
 static void
 sopen(Srv *srv, Req *r)
 {
@@ -408,9 +427,7 @@ sopen(Srv *srv, Req *r)
                        respond(r, Eperm);
                        return;
                }
-       /* BUG RACE */
-               if((r->ifcall.mode&ORCLOSE)
-               && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
+               if((r->ifcall.mode&ORCLOSE) && !dirwritable(r->fid)){
                        respond(r, Eperm);
                        return;
                }
@@ -496,7 +513,7 @@ sread(Srv *srv, Req *r)
                return;
        }
        if((r->fid->qid.type&QTDIR) && r->fid->file){
-               r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count);
+               r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count, r->ifcall.offset);
                respond(r, nil);
                return;
        }
@@ -509,7 +526,7 @@ static void
 rread(Req *r, char *error)
 {
        if(error==nil && (r->fid->qid.type&QTDIR))
-               r->fid->diroffset += r->ofcall.count;
+               r->fid->diroffset = r->ifcall.offset + r->ofcall.count;
 }
 
 static void
@@ -541,7 +558,7 @@ swrite(Srv *srv, Req *r)
        if(srv->write)
                srv->write(r);
        else
-               respond(r, "no srv->write");
+               respond(r, Enowrite);
 }
 static void
 rwrite(Req *r, char *error)
@@ -572,8 +589,7 @@ sremove(Srv *srv, Req *r)
                respond(r, Eunknownfid);
                return;
        }
-       /* BUG RACE */
-       if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
+       if(!dirwritable(r->fid)){
                respond(r, Eperm);
                return;
        }
@@ -666,25 +682,32 @@ swstat(Srv *srv, Req *r)
                respond(r, Ebaddir);
                return;
        }
-       if((ushort)~r->d.type){
-               respond(r, "wstat -- attempt to change type");
-               return;
-       }
-       if((uint)~r->d.dev){
-               respond(r, "wstat -- attempt to change dev");
-               return;
-       }
-       if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){
-               respond(r, "wstat -- attempt to change qid");
+       if(r->d.qid.path != ~0 && r->d.qid.path != r->fid->qid.path){
+               respond(r, "wstat -- attempt to change qid.path");
                return;
        }
-       if(r->d.muid && r->d.muid[0]){
-               respond(r, "wstat -- attempt to change muid");
+       if(r->d.qid.vers != ~0 && r->d.qid.vers != r->fid->qid.vers){
+               respond(r, "wstat -- attempt to change qid.vers");
                return;
        }
-       if((ulong)~r->d.mode && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){
-               respond(r, "wstat -- attempt to change DMDIR bit");
-               return;
+       if(r->d.mode != ~0){
+               if(r->d.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){
+                       respond(r, "wstat -- unknown bits in mode");
+                       return;
+               }
+               if(r->d.qid.type != (uchar)~0 && r->d.qid.type != ((r->d.mode>>24)&0xFF)){
+                       respond(r, "wstat -- qid.type/mode mismatch");
+                       return;
+               }
+               if(((r->d.mode>>24) ^ r->fid->qid.type) & ~(QTAPPEND|QTEXCL|QTTMP)){
+                       respond(r, "wstat -- attempt to change qid.type");
+                       return;
+               }
+       } else {
+               if(r->d.qid.type != (uchar)~0 && r->d.qid.type != r->fid->qid.type){
+                       respond(r, "wstat -- attempt to change qid.type");
+                       return;
+               }
        }
        srv->wstat(r);
 }
@@ -701,8 +724,6 @@ srvwork(void *v)
        Srv *srv = v;
        Req *r;
 
-       incref(&srv->rref);
-       incref(&srv->sref);
        while(r = getreq(srv)){
                incref(&srv->rref);
                if(r->error){
@@ -728,16 +749,24 @@ srvwork(void *v)
                case Tstat:     sstat(srv, r);  break;
                case Twstat:    swstat(srv, r); break;
                }
+               if(srv->sref.ref > 8 && srv->spid != getpid()){
+                       decref(&srv->sref);
+                       qunlock(&srv->slock);
+                       return;
+               }
                qunlock(&srv->slock);
        }
-       decref(&srv->sref);
-       srvclose(srv);
+
+       if(srv->end && srv->sref.ref == 1)
+               srv->end(srv);
+       if(decref(&srv->sref) == 0)
+               srvclose(srv);
 }
 
 static void
 srvclose(Srv *srv)
 {
-       if(decref(&srv->rref))
+       if(srv->rref.ref || srv->sref.ref)
                return;
 
        if(chatty9p)
@@ -753,8 +782,8 @@ srvclose(Srv *srv)
        freereqpool(srv->rpool);
        srv->rpool = nil;
 
-       if(srv->end)
-               srv->end(srv);
+       if(srv->free)
+               srv->free(srv);
 }
 
 void
@@ -767,8 +796,10 @@ srvacquire(Srv *srv)
 void
 srvrelease(Srv *srv)
 {
-       if(decref(&srv->sref) == 0)
+       if(decref(&srv->sref) == 0){
+               incref(&srv->sref);
                _forker(srvwork, srv, 0);
+       }
        qunlock(&srv->slock);
 }
 
@@ -778,6 +809,7 @@ srv(Srv *srv)
        fmtinstall('D', dirfmt);
        fmtinstall('F', fcallfmt);
 
+       srv->spid = getpid();
        srv->sref.ref = 0;
        srv->rref.ref = 0;
 
@@ -796,6 +828,7 @@ srv(Srv *srv)
        if(srv->start)
                srv->start(srv);
 
+       incref(&srv->sref);
        srvwork(srv);
 }
 
@@ -873,7 +906,8 @@ if(chatty9p)
        else
                free(r);
 
-       srvclose(srv);
+       if(decref(&srv->rref) == 0)
+               srvclose(srv);
 }
 
 void