| plan 9 kernel history: overview | file list | diff list |
1998/0319/port/devsrv.c (diff list | history)
| port/devsrv.c on 1990/0227 | ||
| 1990/0227 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1990/0227 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1991/0828 | ||
| 1990/0227 | ||
| 1992/0620 | typedef struct Srv Srv; | |
| 1992/0622 | struct Srv { | |
| 1991/1219 | char name[NAMELEN]; char owner[NAMELEN]; ulong perm; Chan *chan; | |
| 1992/0622 | Srv *link; ulong path; | |
| 1991/1219 | }; | |
| 1990/0227 | ||
| 1992/0622 | static QLock srvlk; static Srv *srv; | |
| 1993/0501 | static int qidpath; | |
| 1991/1219 | ||
| 1997/0327 | static int | |
| 1995/0804 | srvgen(Chan *c, Dirtab*, int, int s, Dir *dp) | |
| 1991/0828 | { | |
| 1991/1219 | Srv *sp; | |
| 1992/0622 | qlock(&srvlk); for(sp = srv; sp && s; sp = sp->link) s--; | |
| 1991/1219 | ||
| 1992/0622 | if(sp == 0) { qunlock(&srvlk); return -1; } devdir(c, (Qid){sp->path, 0}, sp->name, 0, sp->owner, sp->perm, dp); qunlock(&srvlk); | |
| 1991/0828 | return 1; } | |
| 1997/0327 | static void | |
| 1990/0227 | srvinit(void) { | |
| 1993/0501 | qidpath = 1; | |
| 1990/0227 | } | |
| 1997/0327 | static Chan* | |
| 1990/0227 | srvattach(char *spec) { | |
| 1991/0828 | return devattach('s', spec); | |
| 1990/0227 | } | |
| 1997/0327 | static int | |
| 1990/0227 | srvwalk(Chan *c, char *name) { | |
| 1991/0828 | return devwalk(c, name, 0, 0, srvgen); | |
| 1990/0227 | } | |
| 1997/0327 | static void | |
| 1990/0227 | srvstat(Chan *c, char *db) { | |
| 1991/0828 | devstat(c, db, 0, 0, srvgen); | |
| 1990/0227 | } | |
| 1997/0327 | static Chan* | |
| 1990/0227 | srvopen(Chan *c, int omode) { | |
| 1992/0622 | Srv *sp; | |
| 1990/0227 | ||
| 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; } | |
| 1992/0622 | qlock(&srvlk); | |
| 1991/0828 | if(waserror()){ | |
| 1992/0622 | qunlock(&srvlk); | |
| 1991/0828 | nexterror(); } | |
| 1992/0622 | for(sp = srv; sp; sp = sp->link) if(sp->path == c->qid.path) break; if(sp == 0 || sp->chan == 0) | |
| 1990/11211 | error(Eshutdown); | |
| 1992/0622 | ||
| 1991/0828 | if(omode&OTRUNC) | |
| 1990/11211 | error(Eperm); | |
| 1992/0622 | if(omode!=sp->chan->mode && sp->chan->mode!=ORDWR) | |
| 1990/11211 | error(Eperm); | |
| 1992/0622 | ||
| 1997/0327 | cclose(c); | |
| 1992/0622 | incref(sp->chan); qunlock(&srvlk); | |
| 1991/0828 | poperror(); | |
| 1992/0622 | return sp->chan; | |
| 1990/0227 | } | |
| 1997/0327 | static void | |
| 1990/0227 | srvcreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1991/1219 | Srv *sp; | |
| 1990/0227 | ||
| 1991/0828 | if(omode != OWRITE) error(Eperm); | |
| 1991/1219 | ||
| 1992/0622 | sp = malloc(sizeof(Srv)); if(sp == 0) error(Enomem); qlock(&srvlk); | |
| 1991/0828 | if(waserror()){ | |
| 1992/0622 | qunlock(&srvlk); | |
| 1990/0227 | nexterror(); } | |
| 1993/0501 | sp->path = qidpath++; | |
| 1992/0622 | sp->link = srv; c->qid.path = sp->path; srv = sp; qunlock(&srvlk); | |
| 1990/1002 | poperror(); | |
| 1992/0622 | ||
| 1991/1219 | strncpy(sp->name, name, NAMELEN); | |
| 1993/0501 | strncpy(sp->owner, up->user, NAMELEN); | |
| 1991/1219 | sp->perm = perm&0777; | |
| 1990/0227 | c->flag |= COPEN; | |
| 1991/0828 | c->mode = OWRITE; | |
| 1990/0227 | } | |
| 1997/0327 | static void | |
| 1990/0227 | srvremove(Chan *c) { | |
| 1992/0622 | Srv *sp, **l; | |
| 1990/0227 | ||
| 1991/0828 | if(c->qid.path == CHDIR) | |
| 1990/11211 | error(Eperm); | |
| 1991/1219 | ||
| 1992/0622 | qlock(&srvlk); | |
| 1990/1110 | if(waserror()){ | |
| 1992/0622 | qunlock(&srvlk); | |
| 1990/0227 | nexterror(); } | |
| 1992/0622 | l = &srv; for(sp = *l; sp; sp = sp->link) { if(sp->path == c->qid.path) break; | |
| 1993/0701 | l = &sp->link; | |
| 1992/0622 | } if(sp == 0) error(Enonexist); if(strcmp(sp->name, "boot") == 0) | |
| 1991/0828 | error(Eperm); | |
| 1992/0622 | *l = sp->link; qunlock(&srvlk); | |
| 1990/0227 | poperror(); | |
| 1992/0622 | if(sp->chan) | |
| 1997/0327 | cclose(sp->chan); | |
| 1992/0622 | free(sp); | |
| 1990/0227 | } | |
| 1997/0327 | static void | |
| 1990/0227 | srvwstat(Chan *c, char *dp) { | |
| 1994/1018 | Dir d; Srv *sp; if(!iseve()) error(Eperm); if(CHDIR & c->qid.path) error(Eperm); qlock(&srvlk); if(waserror()){ qunlock(&srvlk); nexterror(); } for(sp = srv; sp; sp = sp->link) if(sp->path == c->qid.path) break; if(sp == 0 || sp->chan == 0) error(Eshutdown); convM2D(dp, &d); d.mode &= 0777; sp->perm = d.mode; qunlock(&srvlk); poperror(); | |
| 1990/0227 | } | |
| 1997/0327 | static void | |
| 1995/0804 | srvclose(Chan*) | |
| 1990/0227 | { } | |
| 1997/0327 | static long | |
| 1998/0319 | srvread(Chan *c, void *va, long n, vlong) | |
| 1990/0227 | { | |
| 1990/1002 | isdir(c); | |
| 1991/0828 | return devdirread(c, va, n, 0, 0, srvgen); | |
| 1990/0227 | } | |
| 1997/0327 | static long | |
| 1998/0319 | srvwrite(Chan *c, void *va, long n, vlong) | |
| 1990/0227 | { | |
| 1992/0622 | Srv *sp; Chan *c1; | |
| 1992/0711 | int fd; | |
| 1990/0227 | char buf[32]; | |
| 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); | |
| 1992/0520 | ||
| 1993/0501 | c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ | |
| 1992/0520 | ||
| 1992/0622 | qlock(&srvlk); if(waserror()) { qunlock(&srvlk); | |
| 1997/0327 | cclose(c1); | |
| 1992/0520 | nexterror(); } | |
| 1992/0622 | for(sp = srv; sp; sp = sp->link) if(sp->path == c->qid.path) break; | |
| 1992/0620 | ||
| 1992/0622 | if(sp == 0) error(Enonexist); if(sp->chan) panic("srvwrite"); sp->chan = c1; qunlock(&srvlk); | |
| 1992/0226 | poperror(); | |
| 1990/0227 | return n; | |
| 1995/0108 | } | |
| 1997/0327 | Dev srvdevtab = { | |
| 1997/0408 | 's', "srv", | |
| 1997/0327 | devreset, srvinit, srvattach, devclone, srvwalk, srvstat, srvopen, srvcreate, srvclose, srvread, devbread, srvwrite, devbwrite, srvremove, srvwstat, }; | |
| 1993/0501 | void srvrecover(Chan *old, Chan *new) { Srv *sp; qlock(&srvlk); for(sp = srv; sp; sp = sp->link) { if(sp->chan == old) { sp->chan = new; incref(new); qunlock(&srvlk); | |
| 1997/0327 | cclose(old); | |
| 1993/0501 | return; } } qunlock(&srvlk); | |
| 1990/0227 | } | |