| plan 9 kernel history: overview | file list | diff list |
1990/1002/port/devsrv.c (diff list | history)
| 1990/0725/sys/src/9/port/devsrv.c:4,31 – 1990/1002/sys/src/9/port/devsrv.c:4,30 (short | long | prev | next) | ||
| 1990/0227 | #include "dat.h" #include "fns.h" #include "errno.h" | |
| 1990/1002 | #include "fcall.h" | |
| 1990/0227 |
| |
| 1990/1002 | void *calloc(unsigned int, unsigned int); void free(void *); /* This structure holds the contents of a directory entry. Entries are kept * in a linked list. */ struct entry { | |
| 1990/0227 | Lock; | |
| 1990/1002 | struct entry *next; /* next entry */ struct entry **back; /* entry pointer */ struct entry *parent; /* parent directory */ Dir dir; /* dir structure */ union { Chan *chan; /* if not a subdirectory */ struct entry *entries; /* directory entries */ }; }; | |
| 1990/0227 |
| |
| 1990/0725/sys/src/9/port/devsrv.c:34,74 – 1990/1002/sys/src/9/port/devsrv.c:33,125 | ||
| 1990/0227 | void srvreset(void) { | |
| 1990/1002 | struct entry *srv_alloc(int mode){ struct entry *e = calloc(1, sizeof(*e)); static Lock qidlock; static nextqid; e->dir.atime = e->dir.mtime = seconds(); lock(&qidlock); /* for qid allocation */ e->dir.qid = mode | nextqid++; unlock(&qidlock); return e; } | |
| 1990/0227 | Chan * srvattach(char *spec) { | |
| 1990/1002 | Chan *c; static Lock rootlock; static struct entry *root; lock(&rootlock); if (root == 0) { root = srv_alloc(CHDIR); root->dir.mode = CHDIR | 0777; } unlock(&rootlock); c = devattach('s', spec); c->qid = root->dir.qid; c->aux = root; return c; | |
| 1990/0227 | } Chan * srvclone(Chan *c, Chan *nc) { | |
| 1990/1002 | nc = devclone(c, nc); nc->aux = c->aux; return nc; | |
| 1990/0227 | } int srvwalk(Chan *c, char *name) { | |
| 1990/1002 | struct entry *dir, *e; isdir(c); if (strcmp(name, ".") == 0) return 1; if ((dir = c->aux) == 0) panic("bad aux pointer in srvwalk"); if (strcmp(name, "..") == 0) e = dir->parent; else { lock(dir); for (e = dir->entries; e != 0; e = e->next) if (strcmp(name, e->dir.name) == 0) break; unlock(dir); } if (e == 0) { u->error.code = Enonexist; u->error.type = 0; u->error.dev = 0; return 0; } c->qid = e->dir.qid; c->aux = e; return 1; | |
| 1990/0227 | } void srvstat(Chan *c, char *db) { | |
| 1990/1002 | struct entry *e = c->aux; convD2M(&e->dir, db); | |
| 1990/0227 | } Chan * srvopen(Chan *c, int omode) { | |
| 1990/1002 | struct entry *e; | |
| 1990/0227 | Chan *f; | |
| 1990/1002 | if (c->qid & CHDIR) { if (omode != OREAD) | |
| 1990/0227 | error(0, Eisdir); c->mode = omode; c->flag |= COPEN; | |
| 1990/0725/sys/src/9/port/devsrv.c:75,96 – 1990/1002/sys/src/9/port/devsrv.c:126,141 | ||
| 1990/0227 | c->offset = 0; return c; } | |
| 1990/1002 | if ((e = c->aux) == 0) panic("bad aux pointer in srvopen"); if ((f = e->chan) == 0) | |
| 1990/0227 | error(0, Eshutdown); | |
| 1990/0725 |
| |
| 1990/1002 | if (omode & OTRUNC) | |
| 1990/0227 | error(0, Eperm); | |
| 1990/1002 | if (omode != f->mode && f->mode != ORDWR) | |
| 1990/0227 | error(0, Eperm); close(c); incref(f); | |
| 1990/0725/sys/src/9/port/devsrv.c:97,152 – 1990/1002/sys/src/9/port/devsrv.c:142,201 | ||
| 1990/0227 | void srvcreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1990/1002 | struct entry *parent = c->aux, *e; | |
| 1990/0227 |
| |
| 1990/1002 | isdir(c); lock(parent); if (waserror()) { unlock(parent); | |
| 1990/0227 | nexterror(); } | |
| 1990/1002 | for (e = parent->entries; e != 0; e = e->next) if (strcmp(name, e->dir.name) == 0) | |
| 1990/0227 | error(0, Einuse); | |
| 1990/1002 | e = srv_alloc(perm & CHDIR); e->parent = parent; strcpy(e->dir.name, name); e->dir.mode = perm & parent->dir.mode; e->dir.gid = parent->dir.gid; if ((e->next = parent->entries) != 0) e->next->back = &e->next; *(e->back = &parent->entries) = e; parent->dir.mtime = e->dir.mtime; unlock(parent); poperror(); c->qid = e->dir.gid; c->aux = e; | |
| 1990/0227 | c->flag |= COPEN; | |
| 1990/1002 | c->mode = omode; | |
| 1990/0227 | } void srvremove(Chan *c) { | |
| 1990/1002 | struct entry *e = c->aux; | |
| 1990/0227 |
| |
| 1990/1002 | if (e->parent == 0) | |
| 1990/0227 | error(0, Eperm); | |
| 1990/1002 | lock(e->parent); if (waserror()) { unlock(e->parent); | |
| 1990/0227 | nexterror(); } | |
| 1990/1002 | if (e->dir.mode & CHDIR) { if (e->entries != 0) error(0, Eperm); } else { if (e->chan == 0) error(0, Eshutdown); close(e->chan); } if ((*e->back = e->next) != 0) e->next->back = e->back; unlock(e->parent); | |
| 1990/0227 | poperror(); | |
| 1990/1002 | free(e); | |
| 1990/0227 | } void | |
| 1990/0725/sys/src/9/port/devsrv.c:160,192 – 1990/1002/sys/src/9/port/devsrv.c:209,280 | ||
| 1990/0227 | { } | |
| 1990/1002 | /* A directory is being read. The entries must be synthesized. e points * to a list of entries in this directory. Count is the size to be * read. */ int srv_direntry(struct entry *e, char *a, long count){ Dir dir; int n = 0; while (n != count && e != 0) { n += convD2M(&e->dir, a + n); e = e->next; } return n; } | |
| 1990/0227 | long srvread(Chan *c, void *va, long n) { | |
| 1990/1002 | struct entry *dir = c->aux, *e; int offset = c->offset; | |
| 1990/0227 |
| |
| 1990/1002 | isdir(c); if (n <= 0) return 0; if ((offset % DIRLEN) != 0 || (n % DIRLEN) != 0) error(0, Egreg); lock(dir); for (e = dir->entries; e != 0; e = e->next) if (offset <= 0) { n = srv_direntry(e, va, n); unlock(dir); c->offset += n; return n; } else offset -= DIRLEN; unlock(dir); return 0; | |
| 1990/0227 | } long srvwrite(Chan *c, void *va, long n) { | |
| 1990/1002 | struct entry *e = c->aux; | |
| 1990/0227 | int i, fd; char buf[32]; | |
| 1990/1002 | if (e->dir.mode & CHDIR) panic("write to directory"); lock(e); if (waserror()) { unlock(e); nexterror(); } if (e->chan != 0) | |
| 1990/0227 | error(0, Egreg); | |
| 1990/1002 | if (n >= sizeof buf) | |
| 1990/0227 | error(0, Egreg); memcpy(buf, va, n); /* so we can NUL-terminate */ buf[n] = 0; fd = strtoul(buf, 0, 0); fdtochan(fd, -1); /* error check only */ | |
| 1990/1002 | e->chan = u->fd[fd]; incref(e->chan); unlock(e); poperror(); | |
| 1990/0227 | return n; } | |