| plan 9 kernel history: overview | file list | diff list |
1992/0226/port/devsrv.c (diff list | history)
| port/devsrv.c on 1990/0227 | ||
| 1990/0227 | #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1991/0828 | ||
| 1990/0227 | #include "devtab.h" | |
| 1991/0828 | typedef struct Srv Srv; struct Srv{ | |
| 1991/1219 | char name[NAMELEN]; char owner[NAMELEN]; ulong perm; Chan *chan; }; | |
| 1990/0227 | ||
| 1991/1219 | Lock srvlk; Srv *srv; | |
| 1991/0828 | int srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) { | |
| 1991/1219 | Srv *sp; | |
| 1991/0828 | if(s >= conf.nsrv) return -1; | |
| 1991/1219 | sp = &srv[s]; if(sp->chan == 0) | |
| 1991/0828 | return 0; | |
| 1991/1219 | devdir(c, (Qid){s, 0}, sp->name, 0, sp->owner, sp->perm, dp); | |
| 1991/0828 | return 1; } | |
| 1990/0227 | void srvinit(void) { } void srvreset(void) { | |
| 1991/1219 | srv = ialloc(conf.nsrv*sizeof(Srv), 0); | |
| 1990/0227 | } Chan * srvattach(char *spec) { | |
| 1991/0828 | return devattach('s', spec); | |
| 1990/0227 | } Chan * srvclone(Chan *c, Chan *nc) { | |
| 1991/0828 | return devclone(c, nc); | |
| 1990/0227 | } int srvwalk(Chan *c, char *name) { | |
| 1991/0828 | return devwalk(c, name, 0, 0, srvgen); | |
| 1990/0227 | } void srvstat(Chan *c, char *db) { | |
| 1991/0828 | devstat(c, db, 0, 0, srvgen); | |
| 1990/0227 | } Chan * srvopen(Chan *c, int omode) { Chan *f; | |
| 1991/0828 | if(c->qid.path == CHDIR){ | |
| 1990/1110 | if(omode != OREAD) | |
| 1990/11211 | error(Eisdir); | |
| 1990/0227 | c->mode = omode; c->flag |= COPEN; c->offset = 0; return c; } | |
| 1991/1219 | lock(&srvlk); | |
| 1991/0828 | if(waserror()){ | |
| 1991/1219 | unlock(&srvlk); | |
| 1991/0828 | nexterror(); } | |
| 1991/1219 | f = srv[c->qid.path].chan; | |
| 1991/0828 | if(f == 0) | |
| 1990/11211 | error(Eshutdown); | |
| 1991/0828 | if(omode&OTRUNC) | |
| 1990/11211 | error(Eperm); | |
| 1990/1110 | if(omode!=f->mode && f->mode!=ORDWR) | |
| 1990/11211 | error(Eperm); | |
| 1990/0227 | close(c); incref(f); | |
| 1991/1219 | unlock(&srvlk); | |
| 1991/0828 | poperror(); | |
| 1990/0227 | return f; } void srvcreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1991/0828 | int j, i; | |
| 1991/1219 | Srv *sp; | |
| 1990/0227 | ||
| 1991/0828 | if(omode != OWRITE) error(Eperm); | |
| 1991/1219 | lock(&srvlk); | |
| 1991/0828 | if(waserror()){ | |
| 1991/1219 | unlock(&srvlk); | |
| 1990/0227 | nexterror(); } | |
| 1991/0828 | j = -1; for(i=0; i<conf.nsrv; i++){ | |
| 1991/1219 | if(srv[i].chan == 0){ | |
| 1991/0828 | if(j == -1) j = i; | |
| 1991/1219 | } else if(strcmp(name, srv[i].name) == 0) | |
| 1990/11211 | error(Einuse); | |
| 1991/0828 | } if(j == -1) | |
| 1992/0114 | exhausted("server slots"); | |
| 1991/1219 | sp = &srv[j]; sp->chan = c; unlock(&srvlk); | |
| 1990/1002 | poperror(); | |
| 1991/1219 | strncpy(sp->name, name, NAMELEN); strncpy(sp->owner, u->p->user, NAMELEN); sp->perm = perm&0777; | |
| 1991/0828 | c->qid.path = j; | |
| 1990/0227 | c->flag |= COPEN; | |
| 1991/0828 | c->mode = OWRITE; | |
| 1990/0227 | } void srvremove(Chan *c) { | |
| 1991/0828 | Chan *f; | |
| 1990/0227 | ||
| 1991/0828 | if(c->qid.path == CHDIR) | |
| 1990/11211 | error(Eperm); | |
| 1991/1219 | lock(&srvlk); | |
| 1990/1110 | if(waserror()){ | |
| 1991/1219 | unlock(&srvlk); | |
| 1990/0227 | nexterror(); } | |
| 1991/1219 | f = srv[c->qid.path].chan; | |
| 1991/0828 | if(f == 0) error(Eshutdown); | |
| 1991/1219 | if(strcmp(srv[c->qid.path].name, "boot") == 0) | |
| 1991/0828 | error(Eperm); | |
| 1991/1219 | srv[c->qid.path].chan = 0; unlock(&srvlk); | |
| 1990/0227 | poperror(); | |
| 1991/0828 | close(f); | |
| 1990/0227 | } void srvwstat(Chan *c, char *dp) { | |
| 1991/1115 | USED(c, dp); | |
| 1990/11211 | error(Egreg); | |
| 1990/0227 | } void srvclose(Chan *c) { | |
| 1991/1115 | USED(c); | |
| 1990/0227 | } long | |
| 1991/0411 | srvread(Chan *c, void *va, long n, ulong offset) | |
| 1990/0227 | { | |
| 1990/1002 | isdir(c); | |
| 1991/0828 | return devdirread(c, va, n, 0, 0, srvgen); | |
| 1990/0227 | } long | |
| 1991/0411 | srvwrite(Chan *c, void *va, long n, ulong offset) | |
| 1990/0227 | { | |
| 1991/1127 | Fgrp *f; | |
| 1990/0227 | int i, fd; char buf[32]; | |
| 1991/0828 | i = c->qid.path; | |
| 1991/1219 | if(srv[i].chan != c) /* already been written to */ | |
| 1990/11211 | error(Egreg); | |
| 1990/1110 | if(n >= sizeof buf) | |
| 1990/11211 | error(Egreg); | |
| 1991/0318 | memmove(buf, va, n); /* so we can NUL-terminate */ | |
| 1990/0227 | buf[n] = 0; fd = strtoul(buf, 0, 0); | |
| 1991/1127 | f = u->p->fgrp; lock(f); | |
| 1992/0226 | if(waserror()){ unlock(f); nexterror(); } | |
| 1991/1011 | fdtochan(fd, -1, 0); /* error check only */ | |
| 1991/1219 | srv[i].chan = f->fd[fd]; incref(srv[i].chan); | |
| 1991/1127 | unlock(f); | |
| 1992/0226 | poperror(); | |
| 1990/0227 | return n; } | |