plan 9 kernel history: overview | file list | diff list

1992/0226/port/devsrv.c (diff list | history)

1990/0227/sys/src/9/port/devsrv.c:83,891990/0725/sys/src/9/port/devsrv.c:83,89 (short | long)
1990/0227    
	f = srv.chan[c->qid]; 
	if(f == 0) 
		error(0, Eshutdown); 
	if(omode&OTRUNC) 
1990/0725    
	if(omode & OTRUNC) 
1990/0227    
		error(0, Eperm); 
	if(omode!=f->mode && f->mode!=ORDWR) 
		error(0, Eperm); 
1990/0725/sys/src/9/port/devsrv.c:4,311990/1002/sys/src/9/port/devsrv.c:4,30 (short | long)
1990/0227    
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
                 
#include	"devtab.h" 
1990/1002    
#include	"fcall.h" 
1990/0227    
 
typedef struct	Srv Srv; 
struct Srv{ 
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; 
	char	*name; 
	Chan	**chan; 
}srv; 
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    
 
int 
srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 
{ 
                 
	if(s >= conf.nsrv) 
		return -1; 
	if(srv.chan[s] == 0) 
		return 0; 
	devdir(c, s, &srv.name[s*NAMELEN], 0, 0666, dp); 
	return 1; 
} 
                 
void 
srvinit(void) 
{ 
1990/0725/sys/src/9/port/devsrv.c:34,741990/1002/sys/src/9/port/devsrv.c:33,125
1990/0227    
void 
srvreset(void) 
{ 
	srv.chan = ialloc(conf.nsrv*sizeof(Chan*), 0); 
	srv.name = ialloc(conf.nsrv*NAMELEN, 0); 
} 
 
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) 
{ 
	return devattach('s', 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) 
{ 
	return devclone(c, nc); 
1990/1002    
	nc = devclone(c, nc); 
	nc->aux = c->aux; 
	return nc; 
1990/0227    
} 
 
int 
srvwalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, (Dirtab *)0, 0, srvgen); 
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) 
{ 
	devstat(c, db, (Dirtab *)0, 0L, srvgen); 
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; 
 
	if(c->qid == CHDIR){ 
		if(omode != OREAD) 
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,961990/1002/sys/src/9/port/devsrv.c:126,141
1990/0227    
		c->offset = 0; 
		return c; 
	} 
	lock(&srv); 
	if(waserror()){ 
		unlock(&srv); 
		nexterror(); 
	} 
	f = srv.chan[c->qid]; 
	if(f == 0) 
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    
	if(omode & OTRUNC) 
1990/1002    
	if (omode & OTRUNC) 
1990/0227    
		error(0, Eperm); 
	if(omode!=f->mode && f->mode!=ORDWR) 
1990/1002    
	if (omode != f->mode && f->mode != ORDWR) 
1990/0227    
		error(0, Eperm); 
	close(c); 
	incref(f); 
	unlock(&srv); 
	poperror(); 
	return f; 
} 
 
1990/0725/sys/src/9/port/devsrv.c:97,1521990/1002/sys/src/9/port/devsrv.c:142,201
1990/0227    
void 
srvcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	int j, i; 
1990/1002    
	struct entry *parent = c->aux, *e; 
1990/0227    
 
	if(omode != OWRITE) 
		error(0, Eperm); 
	lock(&srv); 
	if(waserror()){ 
		unlock(&srv); 
1990/1002    
	isdir(c); 
	lock(parent); 
	if (waserror()) { 
		unlock(parent); 
1990/0227    
		nexterror(); 
	} 
	j = -1; 
	for(i=0; i<conf.nsrv; i++){ 
		if(srv.chan[i] == 0){ 
			if(j == -1) 
				j = i; 
		}else if(strcmp(name, &srv.name[i*NAMELEN]) == 0){ 
			print("reuse of srv name\n"); 
1990/1002    
	for (e = parent->entries; e != 0; e = e->next) 
		if (strcmp(name, e->dir.name) == 0) 
1990/0227    
			error(0, Einuse); 
		} 
	} 
	if(j == -1) 
		error(0, Enosrv); 
	srv.chan[j] = c; 
	unlock(&srv); 
	strcpy(&srv.name[j*NAMELEN], name); 
	c->qid = j; 
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; 
	c->mode = OWRITE; 
1990/1002    
	c->mode = omode; 
1990/0227    
} 
 
void 
srvremove(Chan *c) 
{ 
	Chan *f; 
1990/1002    
	struct entry *e = c->aux; 
1990/0227    
 
	if(c->qid == CHDIR) 
1990/1002    
	if (e->parent == 0) 
1990/0227    
		error(0, Eperm); 
	lock(&srv); 
	if(waserror()){ 
		unlock(&srv); 
1990/1002    
	lock(e->parent); 
	if (waserror()) { 
		unlock(e->parent); 
1990/0227    
		nexterror(); 
	} 
	f = srv.chan[c->qid]; 
	if(f == 0) 
		error(0, Eshutdown); 
	if(strcmp(&srv.name[c->qid*NAMELEN], "boot") == 0) 
		error(0, Eperm); 
	srv.chan[c->qid] = 0; 
	unlock(&srv); 
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(); 
	close(f); 
1990/1002    
	free(e); 
1990/0227    
} 
 
void 
1990/0725/sys/src/9/port/devsrv.c:160,1921990/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) 
{ 
	char *a = va; 
1990/1002    
	struct entry *dir = c->aux, *e; 
	int offset = c->offset; 
1990/0227    
 
	if(c->qid != CHDIR) 
		panic("srvread"); 
	return devdirread(c, a, n, (Dirtab *)0, 0L, srvgen); 
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]; 
 
	i = c->qid; 
	if(srv.chan[i] != c)	/* already been written to */ 
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); 
	if(n >= sizeof buf) 
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 */ 
	srv.chan[i] = u->fd[fd]; 
	incref(u->fd[fd]); 
1990/1002    
	e->chan = u->fd[fd]; 
	incref(e->chan); 
	unlock(e); 
	poperror(); 
1990/0227    
	return n; 
} 
 
1990/1002/sys/src/9/port/devsrv.c:7,271990/1110/sys/src/9/port/devsrv.c:7,28 (short | long)
1990/0227    
#include	"devtab.h" 
1990/1002    
#include	"fcall.h" 
1990/0227    
 
1990/1002    
void *calloc(unsigned int, unsigned int); 
1990/1110    
void *calloc(unsigned, unsigned); 
1990/1002    
void free(void *); 
 
/* This structure holds the contents of a directory entry.  Entries are kept 
 * in a linked list. 
 */ 
struct entry { 
1990/1110    
typedef struct Entry Entry; 
struct Entry { 
1990/0227    
	Lock; 
1990/1002    
	struct entry *next;	/* next entry */ 
	struct entry **back;	/* entry pointer */ 
	struct entry *parent;	/* parent directory */ 
1990/1110    
	Entry *next;		/* next entry */ 
	Entry **back;		/* entry pointer */ 
	Entry *parent;		/* parent directory */ 
1990/1002    
	Dir dir;		/* dir structure */ 
	union { 
		Chan *chan;		/* if not a subdirectory */ 
		struct entry *entries;	/* directory entries */ 
1990/1110    
	union{ 
		Chan *chan;	/* if not a subdirectory */ 
		Entry *entries;	/* directory entries */ 
1990/1002    
	}; 
}; 
1990/0227    
 
1990/1002/sys/src/9/port/devsrv.c:35,451990/1110/sys/src/9/port/devsrv.c:36,48
1990/0227    
{ 
} 
 
1990/1002    
struct entry *srv_alloc(int mode){ 
	struct entry *e = calloc(1, sizeof(*e)); 
1990/1110    
Entry * 
srvalloc(int mode){ 
	Entry *e; 
1990/1002    
	static Lock qidlock; 
	static nextqid; 
 
1990/1110    
	e = calloc(1, sizeof(Entry)); 
1990/1002    
	e->dir.atime = e->dir.mtime = seconds(); 
	lock(&qidlock);	/* for qid allocation */ 
	e->dir.qid = mode | nextqid++; 
1990/1002/sys/src/9/port/devsrv.c:52,621990/1110/sys/src/9/port/devsrv.c:55,65
1990/0227    
{ 
1990/1002    
	Chan *c; 
	static Lock rootlock; 
	static struct entry *root; 
1990/1110    
	static Entry *root; 
1990/1002    
 
	lock(&rootlock); 
	if (root == 0) { 
		root = srv_alloc(CHDIR); 
1990/1110    
	if(root==0){ 
		root = srvalloc(CHDIR); 
1990/1002    
		root->dir.mode = CHDIR | 0777; 
	} 
	unlock(&rootlock); 
1990/1002/sys/src/9/port/devsrv.c:77,991990/1110/sys/src/9/port/devsrv.c:80,102
1990/0227    
int 
srvwalk(Chan *c, char *name) 
{ 
1990/1002    
	struct entry *dir, *e; 
1990/1110    
	Entry *dir, *e; 
1990/1002    
 
	isdir(c); 
	if (strcmp(name, ".") == 0) 
1990/1110    
	if(strcmp(name, ".") == 0) 
1990/1002    
		return 1; 
	if ((dir = c->aux) == 0) 
1990/1110    
	if((dir=c->aux) == 0) 
1990/1002    
		panic("bad aux pointer in srvwalk"); 
	if (strcmp(name, "..") == 0) 
1990/1110    
	if(strcmp(name, "..") == 0) 
1990/1002    
		e = dir->parent; 
	else { 
1990/1110    
	else{ 
1990/1002    
		lock(dir); 
		for (e = dir->entries; e != 0; e = e->next) 
1990/1110    
		for(e=dir->entries; e; e=e->next) 
1990/1002    
			if (strcmp(name, e->dir.name) == 0) 
				break; 
		unlock(dir); 
	} 
	if (e == 0) { 
1990/1110    
	if(e==0){ 
1990/1002    
		u->error.code = Enonexist; 
		u->error.type = 0; 
		u->error.dev = 0; 
1990/1002/sys/src/9/port/devsrv.c:107,1141990/1110/sys/src/9/port/devsrv.c:110,118
1990/0227    
void 
srvstat(Chan *c, char *db) 
{ 
1990/1002    
	struct entry *e = c->aux; 
1990/1110    
	Entry *e; 
1990/1002    
 
1990/1110    
	e = c->aux; 
1990/1002    
	convD2M(&e->dir, db); 
1990/0227    
} 
 
1990/1002/sys/src/9/port/devsrv.c:115,1251990/1110/sys/src/9/port/devsrv.c:119,129
1990/0227    
Chan * 
srvopen(Chan *c, int omode) 
{ 
1990/1002    
	struct entry *e; 
1990/1110    
	Entry *e; 
1990/0227    
	Chan *f; 
 
1990/1002    
	if (c->qid & CHDIR) { 
		if (omode != OREAD) 
1990/1110    
	if(c->qid & CHDIR){ 
		if(omode != OREAD) 
1990/0227    
			error(0, Eisdir); 
		c->mode = omode; 
		c->flag |= COPEN; 
1990/1002/sys/src/9/port/devsrv.c:126,1381990/1110/sys/src/9/port/devsrv.c:130,142
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/1110    
	if((e=c->aux) == 0) 
		error(0, Egreg); 
	if((f=e->chan) == 0) 
1990/0227    
		error(0, Eshutdown); 
1990/1002    
	if (omode & OTRUNC) 
1990/1110    
	if(omode & OTRUNC) 
1990/0227    
		error(0, Eperm); 
1990/1002    
	if (omode != f->mode && f->mode != ORDWR) 
1990/1110    
	if(omode!=f->mode && f->mode!=ORDWR) 
1990/0227    
		error(0, Eperm); 
	close(c); 
	incref(f); 
1990/1002/sys/src/9/port/devsrv.c:142,1661990/1110/sys/src/9/port/devsrv.c:146,172
1990/0227    
void 
srvcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1990/1002    
	struct entry *parent = c->aux, *e; 
1990/1110    
	Entry *parent, *e; 
1990/0227    
 
1990/1110    
	parent = c->aux; 
1990/1002    
	isdir(c); 
	lock(parent); 
	if (waserror()) { 
1990/1110    
	if (waserror()){ 
1990/1002    
		unlock(parent); 
1990/0227    
		nexterror(); 
	} 
1990/1002    
	for (e = parent->entries; e != 0; e = e->next) 
		if (strcmp(name, e->dir.name) == 0) 
1990/1110    
	for(e=parent->entries; e; e=e->next) 
		if(strcmp(name, e->dir.name) == 0) 
1990/0227    
			error(0, Einuse); 
1990/1002    
	e = srv_alloc(perm & CHDIR); 
1990/1110    
	e = srvalloc(perm & CHDIR); 
1990/1002    
	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) 
1990/1110    
	if(e->next = parent->entries)	/* assign = */ 
1990/1002    
		e->next->back = &e->next; 
	*(e->back = &parent->entries) = e; 
1990/1110    
	e->back = &parent->entries; 
	*e->back = e; 
1990/1002    
	parent->dir.mtime = e->dir.mtime; 
	unlock(parent); 
	poperror(); 
1990/1002/sys/src/9/port/devsrv.c:173,1971990/1110/sys/src/9/port/devsrv.c:179,203
1990/0227    
void 
srvremove(Chan *c) 
{ 
1990/1002    
	struct entry *e = c->aux; 
1990/1110    
	Entry *e; 
1990/0227    
 
1990/1002    
	if (e->parent == 0) 
1990/1110    
	e = c->aux; 
	if(e->parent == 0) 
1990/0227    
		error(0, Eperm); 
1990/1002    
	lock(e->parent); 
	if (waserror()) { 
1990/1110    
	if(waserror()){ 
1990/1002    
		unlock(e->parent); 
1990/0227    
		nexterror(); 
	} 
1990/1002    
	if (e->dir.mode & CHDIR) { 
1990/1110    
	if(e->dir.mode & CHDIR){ 
1990/1002    
		if (e->entries != 0) 
			error(0, Eperm); 
	} 
	else { 
		if (e->chan == 0) 
1990/1110    
	}else{ 
		if(e->chan == 0) 
1990/1002    
			error(0, Eshutdown); 
		close(e->chan); 
	} 
	if ((*e->back = e->next) != 0) 
1990/1110    
	if(*e->back = e->next)	/* assign = */ 
1990/1002    
		e->next->back = e->back; 
	unlock(e->parent); 
1990/0227    
	poperror(); 
1990/1002/sys/src/9/port/devsrv.c:213,2231990/1110/sys/src/9/port/devsrv.c:219,231
1990/1002    
 * 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){ 
1990/1110    
int 
srvdirentry(Entry *e, char *a, long count){ 
1990/1002    
	Dir dir; 
	int n = 0; 
1990/1110    
	int n; 
1990/1002    
 
	while (n != count && e != 0) { 
1990/1110    
	n = 0; 
	while(n!=count && e!=0){ 
1990/1002    
		n += convD2M(&e->dir, a + n); 
		e = e->next; 
	} 
1990/1002/sys/src/9/port/devsrv.c:227,2491990/1110/sys/src/9/port/devsrv.c:235,258
1990/0227    
long 
srvread(Chan *c, void *va, long n) 
{ 
1990/1002    
	struct entry *dir = c->aux, *e; 
	int offset = c->offset; 
1990/1110    
	Entry *dir, *e; 
	int offset; 
1990/0227    
 
1990/1110    
	dir = c->aux; 
	offset = c->offset; 
1990/1002    
	isdir(c); 
	if (n <= 0) 
1990/1110    
	if(n <= 0) 
1990/1002    
		return 0; 
	if ((offset % DIRLEN) != 0 || (n % DIRLEN) != 0) 
		error(0, Egreg); 
1990/1110    
	if(offset%DIRLEN || n%DIRLEN) 
		error(0, Ebaddirread); 
1990/1002    
	lock(dir); 
	for (e = dir->entries; e != 0; e = e->next) 
		if (offset <= 0) { 
			n = srv_direntry(e, va, n); 
1990/1110    
	for(e=dir->entries; e; e=e->next) 
		if(offset <= 0){ 
			n = srvdirentry(e, va, n); 
1990/1002    
			unlock(dir); 
			c->offset += n; 
			return n; 
		} 
		else 
1990/1110    
		}else 
1990/1002    
			offset -= DIRLEN; 
	unlock(dir); 
	return 0; 
1990/1002/sys/src/9/port/devsrv.c:252,2711990/1110/sys/src/9/port/devsrv.c:261,281
1990/0227    
long 
srvwrite(Chan *c, void *va, long n) 
{ 
1990/1002    
	struct entry *e = c->aux; 
1990/1110    
	Entry *e; 
1990/0227    
	int i, fd; 
	char buf[32]; 
 
1990/1002    
	if (e->dir.mode & CHDIR) 
1990/1110    
	e = c->aux; 
	if(e->dir.mode & CHDIR) 
1990/1002    
		panic("write to directory"); 
	lock(e); 
	if (waserror()) { 
1990/1110    
	if(waserror()){ 
1990/1002    
		unlock(e); 
		nexterror(); 
	} 
	if (e->chan != 0) 
1990/1110    
	if(e->chan) 
1990/0227    
		error(0, Egreg); 
1990/1002    
	if (n >= sizeof buf) 
1990/1110    
	if(n >= sizeof buf) 
1990/0227    
		error(0, Egreg); 
	memcpy(buf, va, n);	/* so we can NUL-terminate */ 
	buf[n] = 0; 
1990/1110/sys/src/9/port/devsrv.c:170,1761990/1121/sys/src/9/port/devsrv.c:170,176 (short | long)
1990/1002    
	parent->dir.mtime = e->dir.mtime; 
	unlock(parent); 
	poperror(); 
	c->qid = e->dir.gid; 
1990/1121    
	c->qid = e->dir.qid; 
1990/1002    
	c->aux = e; 
1990/0227    
	c->flag |= COPEN; 
1990/1002    
	c->mode = omode; 
1990/1121/sys/src/9/port/devsrv.c:45,511990/11211/sys/src/9/port/devsrv.c:45,51 (short | long)
1990/1110    
	e = calloc(1, sizeof(Entry)); 
1990/1002    
	e->dir.atime = e->dir.mtime = seconds(); 
	lock(&qidlock);	/* for qid allocation */ 
	e->dir.qid = mode | nextqid++; 
1990/11211    
	e->dir.qid = (Qid){mode|nextqid++, 0}; 
1990/1002    
	unlock(&qidlock); 
	return e; 
} 
1990/1121/sys/src/9/port/devsrv.c:97,1051990/11211/sys/src/9/port/devsrv.c:97,103
1990/1002    
		unlock(dir); 
	} 
1990/1110    
	if(e==0){ 
1990/1002    
		u->error.code = Enonexist; 
		u->error.type = 0; 
		u->error.dev = 0; 
1990/11211    
		strncpy(u->error, errstrtab[Enonexist], NAMELEN); 
1990/1002    
		return 0; 
	} 
	c->qid = e->dir.qid; 
1990/1121/sys/src/9/port/devsrv.c:122,1301990/11211/sys/src/9/port/devsrv.c:120,128
1990/1110    
	Entry *e; 
1990/0227    
	Chan *f; 
 
1990/1110    
	if(c->qid & CHDIR){ 
1990/11211    
	if(c->qid.path & CHDIR){ 
1990/1110    
		if(omode != OREAD) 
1990/0227    
			error(0, Eisdir); 
1990/11211    
			error(Eisdir); 
1990/0227    
		c->mode = omode; 
		c->flag |= COPEN; 
		c->offset = 0; 
1990/1121/sys/src/9/port/devsrv.c:131,1431990/11211/sys/src/9/port/devsrv.c:129,141
1990/0227    
		return c; 
	} 
1990/1110    
	if((e=c->aux) == 0) 
		error(0, Egreg); 
1990/11211    
		error(Egreg); 
1990/1110    
	if((f=e->chan) == 0) 
1990/0227    
		error(0, Eshutdown); 
1990/11211    
		error(Eshutdown); 
1990/1110    
	if(omode & OTRUNC) 
1990/0227    
		error(0, Eperm); 
1990/11211    
		error(Eperm); 
1990/1110    
	if(omode!=f->mode && f->mode!=ORDWR) 
1990/0227    
		error(0, Eperm); 
1990/11211    
		error(Eperm); 
1990/0227    
	close(c); 
	incref(f); 
	return f; 
1990/1121/sys/src/9/port/devsrv.c:157,1681990/11211/sys/src/9/port/devsrv.c:155,166
1990/0227    
	} 
1990/1110    
	for(e=parent->entries; e; e=e->next) 
		if(strcmp(name, e->dir.name) == 0) 
1990/0227    
			error(0, Einuse); 
1990/11211    
			error(Einuse); 
1990/1110    
	e = srvalloc(perm & CHDIR); 
1990/1002    
	e->parent = parent; 
	strcpy(e->dir.name, name); 
	e->dir.mode = perm & parent->dir.mode; 
	e->dir.gid = parent->dir.gid; 
1990/11211    
	strcpy(e->dir.gid, parent->dir.gid); 
1990/1110    
	if(e->next = parent->entries)	/* assign = */ 
1990/1002    
		e->next->back = &e->next; 
1990/1110    
	e->back = &parent->entries; 
1990/1121/sys/src/9/port/devsrv.c:183,1891990/11211/sys/src/9/port/devsrv.c:181,187
1990/0227    
 
1990/1110    
	e = c->aux; 
	if(e->parent == 0) 
1990/0227    
		error(0, Eperm); 
1990/11211    
		error(Eperm); 
1990/1002    
	lock(e->parent); 
1990/1110    
	if(waserror()){ 
1990/1002    
		unlock(e->parent); 
1990/1121/sys/src/9/port/devsrv.c:191,2001990/11211/sys/src/9/port/devsrv.c:189,198
1990/0227    
	} 
1990/1110    
	if(e->dir.mode & CHDIR){ 
1990/1002    
		if (e->entries != 0) 
			error(0, Eperm); 
1990/11211    
			error(Eperm); 
1990/1110    
	}else{ 
		if(e->chan == 0) 
1990/1002    
			error(0, Eshutdown); 
1990/11211    
			error(Eshutdown); 
1990/1002    
		close(e->chan); 
	} 
1990/1110    
	if(*e->back = e->next)	/* assign = */ 
1990/1121/sys/src/9/port/devsrv.c:207,2131990/11211/sys/src/9/port/devsrv.c:205,211
1990/0227    
void 
srvwstat(Chan *c, char *dp) 
{ 
	error(0, Egreg); 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
void 
1990/1121/sys/src/9/port/devsrv.c:244,2501990/11211/sys/src/9/port/devsrv.c:242,248
1990/1110    
	if(n <= 0) 
1990/1002    
		return 0; 
1990/1110    
	if(offset%DIRLEN || n%DIRLEN) 
		error(0, Ebaddirread); 
1990/11211    
		error(Ebaddirread); 
1990/1002    
	lock(dir); 
1990/1110    
	for(e=dir->entries; e; e=e->next) 
		if(offset <= 0){ 
1990/1121/sys/src/9/port/devsrv.c:274,2821990/11211/sys/src/9/port/devsrv.c:272,280
1990/1002    
		nexterror(); 
	} 
1990/1110    
	if(e->chan) 
1990/0227    
		error(0, Egreg); 
1990/11211    
		error(Egreg); 
1990/1110    
	if(n >= sizeof buf) 
1990/0227    
		error(0, Egreg); 
1990/11211    
		error(Egreg); 
1990/0227    
	memcpy(buf, va, n);	/* so we can NUL-terminate */ 
	buf[n] = 0; 
	fd = strtoul(buf, 0, 0); 
1990/1121/sys/src/9/port/devsrv.c:286,3011990/11211/sys/src/9/port/devsrv.c:284,287
1990/1002    
	unlock(e); 
	poperror(); 
1990/0227    
	return n; 
} 
                 
void 
srverrstr(Error *e, char *buf) 
{ 
	rooterrstr(e, buf); 
} 
                 
void 
srvuserstr(Error *e, char *buf) 
{ 
	consuserstr(e, buf); 
} 
1990/11211/sys/src/9/port/devsrv.c:275,2811991/0318/sys/src/9/port/devsrv.c:275,281 (short | long)
1990/11211    
		error(Egreg); 
1990/1110    
	if(n >= sizeof buf) 
1990/11211    
		error(Egreg); 
1990/0227    
	memcpy(buf, va, n);	/* so we can NUL-terminate */ 
1991/0318    
	memmove(buf, va, n);	/* so we can NUL-terminate */ 
1990/0227    
	buf[n] = 0; 
	fd = strtoul(buf, 0, 0); 
	fdtochan(fd, -1);	/* error check only */ 
1991/0318/sys/src/9/port/devsrv.c:231,2431991/0411/sys/src/9/port/devsrv.c:231,241 (short | long)
1990/1002    
} 
 
1990/0227    
long 
srvread(Chan *c, void *va, long n) 
1991/0411    
srvread(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
1990/1110    
	Entry *dir, *e; 
	int offset; 
1990/0227    
 
1990/1110    
	dir = c->aux; 
	offset = c->offset; 
1990/1002    
	isdir(c); 
1990/1110    
	if(n <= 0) 
1990/1002    
		return 0; 
1991/0318/sys/src/9/port/devsrv.c:257,2631991/0411/sys/src/9/port/devsrv.c:255,261
1990/0227    
} 
 
long 
srvwrite(Chan *c, void *va, long n) 
1991/0411    
srvwrite(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
1990/1110    
	Entry *e; 
1990/0227    
	int i, fd; 
1991/0411/sys/src/9/port/devsrv.c:105,1101991/0419/sys/src/9/port/devsrv.c:105,116 (short | long)
1990/1002    
	return 1; 
1990/0227    
} 
 
1991/0419    
Chan* 
srvclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
 
1990/0227    
void 
srvstat(Chan *c, char *db) 
{ 
1991/0419/sys/src/9/port/devsrv.c:73,791991/0421/sys/src/9/port/devsrv.c:73,78 (short | long)
1990/0227    
srvclone(Chan *c, Chan *nc) 
{ 
1990/1002    
	nc = devclone(c, nc); 
	nc->aux = c->aux; 
	return nc; 
1990/0227    
} 
 
1991/0421/sys/src/9/port/devsrv.c:104,1151991/0427/sys/src/9/port/devsrv.c:104,109 (short | long)
1990/1002    
	return 1; 
1990/0227    
} 
 
1991/0419    
Chan* 
srvclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
                 
1990/0227    
void 
srvstat(Chan *c, char *db) 
{ 
1991/0427/sys/src/9/port/devsrv.c:275,2821991/0705/sys/src/9/port/devsrv.c:275,281 (short | long)
1991/0318    
	memmove(buf, va, n);	/* so we can NUL-terminate */ 
1990/0227    
	buf[n] = 0; 
	fd = strtoul(buf, 0, 0); 
	fdtochan(fd, -1);	/* error check only */ 
1990/1002    
	e->chan = u->fd[fd]; 
1991/0705    
	e->chan = fdtochan(fd, -1); 
1990/1002    
	incref(e->chan); 
	unlock(e); 
	poperror(); 
1991/0705/sys/src/9/port/devsrv.c:4,311991/0828/sys/src/9/port/devsrv.c:4,30 (short | long)
1990/0227    
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1991/0828    
 
1990/0227    
#include	"devtab.h" 
1990/1002    
#include	"fcall.h" 
1990/0227    
 
1990/1110    
void *calloc(unsigned, unsigned); 
1990/1002    
void free(void *); 
                 
/* This structure holds the contents of a directory entry.  Entries are kept 
 * in a linked list. 
 */ 
1990/1110    
typedef struct Entry Entry; 
struct Entry { 
1991/0828    
typedef struct	Srv Srv; 
struct Srv{ 
1990/0227    
	Lock; 
1990/1110    
	Entry *next;		/* next entry */ 
	Entry **back;		/* entry pointer */ 
	Entry *parent;		/* parent directory */ 
1990/1002    
	Dir dir;		/* dir structure */ 
1990/1110    
	union{ 
		Chan *chan;	/* if not a subdirectory */ 
		Entry *entries;	/* directory entries */ 
1990/1002    
	}; 
}; 
1991/0828    
	char	*name; 
	Chan	**chan; 
}srv; 
1990/0227    
 
1991/0828    
int 
srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 
{ 
	if(s >= conf.nsrv) 
		return -1; 
	if(srv.chan[s] == 0) 
		return 0; 
	devdir(c, (Qid){s, 0}, &srv.name[s*NAMELEN], 0, 0666, dp); 
	return 1; 
} 
 
1990/0227    
void 
srvinit(void) 
{ 
1991/0705/sys/src/9/port/devsrv.c:34,1251991/0828/sys/src/9/port/devsrv.c:33,72
1990/0227    
void 
srvreset(void) 
{ 
1991/0828    
	srv.chan = ialloc(conf.nsrv*sizeof(Chan*), 0); 
	srv.name = ialloc(conf.nsrv*NAMELEN, 0); 
1990/0227    
} 
 
1990/1110    
Entry * 
srvalloc(int mode){ 
	Entry *e; 
1990/1002    
	static Lock qidlock; 
	static nextqid; 
                 
1990/1110    
	e = calloc(1, sizeof(Entry)); 
1990/1002    
	e->dir.atime = e->dir.mtime = seconds(); 
	lock(&qidlock);	/* for qid allocation */ 
1990/11211    
	e->dir.qid = (Qid){mode|nextqid++, 0}; 
1990/1002    
	unlock(&qidlock); 
	return e; 
} 
                 
1990/0227    
Chan * 
srvattach(char *spec) 
{ 
1990/1002    
	Chan *c; 
	static Lock rootlock; 
1990/1110    
	static Entry *root; 
1990/1002    
                 
	lock(&rootlock); 
1990/1110    
	if(root==0){ 
		root = srvalloc(CHDIR); 
1990/1002    
		root->dir.mode = CHDIR | 0777; 
	} 
	unlock(&rootlock); 
	c = devattach('s', spec); 
	c->qid = root->dir.qid; 
	c->aux = root; 
	return c; 
1991/0828    
	return devattach('s', spec); 
1990/0227    
} 
 
Chan * 
srvclone(Chan *c, Chan *nc) 
{ 
1990/1002    
	nc = devclone(c, nc); 
	return nc; 
1991/0828    
	return devclone(c, nc); 
1990/0227    
} 
 
int 
srvwalk(Chan *c, char *name) 
{ 
1990/1110    
	Entry *dir, *e; 
1990/1002    
                 
	isdir(c); 
1990/1110    
	if(strcmp(name, ".") == 0) 
1990/1002    
		return 1; 
1990/1110    
	if((dir=c->aux) == 0) 
1990/1002    
		panic("bad aux pointer in srvwalk"); 
1990/1110    
	if(strcmp(name, "..") == 0) 
1990/1002    
		e = dir->parent; 
1990/1110    
	else{ 
1990/1002    
		lock(dir); 
1990/1110    
		for(e=dir->entries; e; e=e->next) 
1990/1002    
			if (strcmp(name, e->dir.name) == 0) 
				break; 
		unlock(dir); 
	} 
1990/1110    
	if(e==0){ 
1990/11211    
		strncpy(u->error, errstrtab[Enonexist], NAMELEN); 
1990/1002    
		return 0; 
	} 
	c->qid = e->dir.qid; 
	c->aux = e; 
	return 1; 
1991/0828    
	return devwalk(c, name, 0, 0, srvgen); 
1990/0227    
} 
 
void 
srvstat(Chan *c, char *db) 
{ 
1990/1110    
	Entry *e; 
1990/1002    
                 
1990/1110    
	e = c->aux; 
1990/1002    
	convD2M(&e->dir, db); 
1991/0828    
	devstat(c, db, 0, 0, srvgen); 
1990/0227    
} 
 
Chan * 
srvopen(Chan *c, int omode) 
{ 
1990/1110    
	Entry *e; 
1990/0227    
	Chan *f; 
 
1990/11211    
	if(c->qid.path & CHDIR){ 
1991/0828    
	if(c->qid.path == CHDIR){ 
1990/1110    
		if(omode != OREAD) 
1990/11211    
			error(Eisdir); 
1990/0227    
		c->mode = omode; 
1991/0705/sys/src/9/port/devsrv.c:127,1421991/0828/sys/src/9/port/devsrv.c:74,95
1990/0227    
		c->offset = 0; 
		return c; 
	} 
1990/1110    
	if((e=c->aux) == 0) 
1990/11211    
		error(Egreg); 
1990/1110    
	if((f=e->chan) == 0) 
1991/0828    
	lock(&srv); 
	if(waserror()){ 
		unlock(&srv); 
		nexterror(); 
	} 
	f = srv.chan[c->qid.path]; 
	if(f == 0) 
1990/11211    
		error(Eshutdown); 
1990/1110    
	if(omode & OTRUNC) 
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/0828    
	unlock(&srv); 
	poperror(); 
1990/0227    
	return f; 
} 
 
1991/0705/sys/src/9/port/devsrv.c:143,2041991/0828/sys/src/9/port/devsrv.c:96,150
1990/0227    
void 
srvcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1990/1110    
	Entry *parent, *e; 
1991/0828    
	int j, i; 
1990/0227    
 
1990/1110    
	parent = c->aux; 
1990/1002    
	isdir(c); 
	lock(parent); 
1990/1110    
	if (waserror()){ 
1990/1002    
		unlock(parent); 
1991/0828    
	if(omode != OWRITE) 
		error(Eperm); 
	lock(&srv); 
	if(waserror()){ 
		unlock(&srv); 
1990/0227    
		nexterror(); 
	} 
1990/1110    
	for(e=parent->entries; e; e=e->next) 
		if(strcmp(name, e->dir.name) == 0) 
1991/0828    
	j = -1; 
	for(i=0; i<conf.nsrv; i++){ 
		if(srv.chan[i] == 0){ 
			if(j == -1) 
				j = i; 
		}else if(strcmp(name, &srv.name[i*NAMELEN]) == 0) 
1990/11211    
			error(Einuse); 
1990/1110    
	e = srvalloc(perm & CHDIR); 
1990/1002    
	e->parent = parent; 
	strcpy(e->dir.name, name); 
	e->dir.mode = perm & parent->dir.mode; 
1990/11211    
	strcpy(e->dir.gid, parent->dir.gid); 
1990/1110    
	if(e->next = parent->entries)	/* assign = */ 
1990/1002    
		e->next->back = &e->next; 
1990/1110    
	e->back = &parent->entries; 
	*e->back = e; 
1990/1002    
	parent->dir.mtime = e->dir.mtime; 
	unlock(parent); 
1991/0828    
	} 
	if(j == -1) 
		error(Enosrv); 
	srv.chan[j] = c; 
	unlock(&srv); 
1990/1002    
	poperror(); 
1990/1121    
	c->qid = e->dir.qid; 
1990/1002    
	c->aux = e; 
1991/0828    
	strcpy(&srv.name[j*NAMELEN], name); 
	c->qid.path = j; 
1990/0227    
	c->flag |= COPEN; 
1990/1002    
	c->mode = omode; 
1991/0828    
	c->mode = OWRITE; 
1990/0227    
} 
 
void 
srvremove(Chan *c) 
{ 
1990/1110    
	Entry *e; 
1991/0828    
	Chan *f; 
1990/0227    
 
1990/1110    
	e = c->aux; 
	if(e->parent == 0) 
1991/0828    
	if(c->qid.path == CHDIR) 
1990/11211    
		error(Eperm); 
1990/1002    
	lock(e->parent); 
1991/0828    
	lock(&srv); 
1990/1110    
	if(waserror()){ 
1990/1002    
		unlock(e->parent); 
1991/0828    
		unlock(&srv); 
1990/0227    
		nexterror(); 
	} 
1990/1110    
	if(e->dir.mode & CHDIR){ 
1990/1002    
		if (e->entries != 0) 
1990/11211    
			error(Eperm); 
1990/1110    
	}else{ 
		if(e->chan == 0) 
1990/11211    
			error(Eshutdown); 
1990/1002    
		close(e->chan); 
	} 
1990/1110    
	if(*e->back = e->next)	/* assign = */ 
1990/1002    
		e->next->back = e->back; 
	unlock(e->parent); 
1991/0828    
	f = srv.chan[c->qid.path]; 
	if(f == 0) 
		error(Eshutdown); 
	if(strcmp(&srv.name[c->qid.path*NAMELEN], "boot") == 0) 
		error(Eperm); 
	srv.chan[c->qid.path] = 0; 
	unlock(&srv); 
1990/0227    
	poperror(); 
1990/1002    
	free(e); 
1991/0828    
	close(f); 
1990/0227    
} 
 
void 
1991/0705/sys/src/9/port/devsrv.c:212,2741991/0828/sys/src/9/port/devsrv.c:158,178
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. 
 */ 
1990/1110    
int 
srvdirentry(Entry *e, char *a, long count){ 
1990/1002    
	Dir dir; 
1990/1110    
	int n; 
1990/1002    
                 
1990/1110    
	n = 0; 
	while(n!=count && e!=0){ 
1990/1002    
		n += convD2M(&e->dir, a + n); 
		e = e->next; 
	} 
	return n; 
} 
                 
1990/0227    
long 
1991/0411    
srvread(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
1990/1110    
	Entry *dir, *e; 
1990/0227    
                 
1990/1110    
	dir = c->aux; 
1990/1002    
	isdir(c); 
1990/1110    
	if(n <= 0) 
1990/1002    
		return 0; 
1990/1110    
	if(offset%DIRLEN || n%DIRLEN) 
1990/11211    
		error(Ebaddirread); 
1990/1002    
	lock(dir); 
1990/1110    
	for(e=dir->entries; e; e=e->next) 
		if(offset <= 0){ 
			n = srvdirentry(e, va, n); 
1990/1002    
			unlock(dir); 
			c->offset += n; 
			return n; 
1990/1110    
		}else 
1990/1002    
			offset -= DIRLEN; 
	unlock(dir); 
	return 0; 
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    
{ 
1990/1110    
	Entry *e; 
1990/0227    
	int i, fd; 
	char buf[32]; 
 
1990/1110    
	e = c->aux; 
	if(e->dir.mode & CHDIR) 
1990/1002    
		panic("write to directory"); 
	lock(e); 
1990/1110    
	if(waserror()){ 
1990/1002    
		unlock(e); 
		nexterror(); 
	} 
1990/1110    
	if(e->chan) 
1991/0828    
	i = c->qid.path; 
	if(srv.chan[i] != c)	/* already been written to */ 
1990/11211    
		error(Egreg); 
1990/1110    
	if(n >= sizeof buf) 
1990/11211    
		error(Egreg); 
1991/0705/sys/src/9/port/devsrv.c:275,2831991/0828/sys/src/9/port/devsrv.c:179,186
1991/0318    
	memmove(buf, va, n);	/* so we can NUL-terminate */ 
1990/0227    
	buf[n] = 0; 
	fd = strtoul(buf, 0, 0); 
1991/0705    
	e->chan = fdtochan(fd, -1); 
1990/1002    
	incref(e->chan); 
	unlock(e); 
	poperror(); 
1991/0828    
	fdtochan(fd, -1);	/* error check only */ 
	srv.chan[i] = u->p->fgrp->fd[fd]; 
	incref(u->p->fgrp->fd[fd]); 
1990/0227    
	return n; 
} 
1991/0828/sys/src/9/port/devsrv.c:181,1861991/0921/sys/src/9/port/devsrv.c:181,186 (short | long)
1990/0227    
	fd = strtoul(buf, 0, 0); 
1991/0828    
	fdtochan(fd, -1);	/* error check only */ 
	srv.chan[i] = u->p->fgrp->fd[fd]; 
	incref(u->p->fgrp->fd[fd]); 
1991/0921    
	incref(srv.chan[i]); 
1990/0227    
	return n; 
} 
1991/0921/sys/src/9/port/devsrv.c:179,1851991/1011/sys/src/9/port/devsrv.c:179,185 (short | long)
1991/0318    
	memmove(buf, va, n);	/* so we can NUL-terminate */ 
1990/0227    
	buf[n] = 0; 
	fd = strtoul(buf, 0, 0); 
1991/0828    
	fdtochan(fd, -1);	/* error check only */ 
1991/1011    
	fdtochan(fd, -1, 0);	/* error check only */ 
1991/0828    
	srv.chan[i] = u->p->fgrp->fd[fd]; 
1991/0921    
	incref(srv.chan[i]); 
1990/0227    
	return n; 
1991/1011/sys/src/9/port/devsrv.c:21,271991/1109/sys/src/9/port/devsrv.c:21,27 (short | long)
1991/0828    
		return -1; 
	if(srv.chan[s] == 0) 
		return 0; 
	devdir(c, (Qid){s, 0}, &srv.name[s*NAMELEN], 0, 0666, dp); 
1991/1109    
	devdir(c, (Qid){s, 0}, &srv.name[s*NAMELEN], 0, eve, 0666, dp); 
1991/0828    
	return 1; 
} 
 
1991/1109/sys/src/9/port/devsrv.c:150,1551991/1115/sys/src/9/port/devsrv.c:150,156 (short | long)
1990/0227    
void 
srvwstat(Chan *c, char *dp) 
{ 
1991/1115    
	USED(c, dp); 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
1991/1109/sys/src/9/port/devsrv.c:156,1611991/1115/sys/src/9/port/devsrv.c:157,163
1990/0227    
void 
srvclose(Chan *c) 
{ 
1991/1115    
	USED(c); 
1990/0227    
} 
 
long 
1991/1115/sys/src/9/port/devsrv.c:170,1751991/1127/sys/src/9/port/devsrv.c:170,176 (short | long)
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/1115/sys/src/9/port/devsrv.c:181,1881991/1127/sys/src/9/port/devsrv.c:182,192
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); 
1991/1011    
	fdtochan(fd, -1, 0);	/* error check only */ 
1991/0828    
	srv.chan[i] = u->p->fgrp->fd[fd]; 
1991/1127    
	srv.chan[i] = f->fd[fd]; 
1991/0921    
	incref(srv.chan[i]); 
1991/1127    
	unlock(f); 
1990/0227    
	return n; 
} 
1991/1127/sys/src/9/port/devsrv.c:9,271991/1219/sys/src/9/port/devsrv.c:9,35 (short | long)
1990/0227    
 
1991/0828    
typedef struct	Srv Srv; 
struct Srv{ 
1990/0227    
	Lock; 
1991/0828    
	char	*name; 
	Chan	**chan; 
}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; 
	if(srv.chan[s] == 0) 
1991/1219    
 
	sp = &srv[s]; 
	if(sp->chan == 0) 
1991/0828    
		return 0; 
1991/1109    
	devdir(c, (Qid){s, 0}, &srv.name[s*NAMELEN], 0, eve, 0666, dp); 
1991/1219    
	devdir(c, (Qid){s, 0}, sp->name, 0, sp->owner, sp->perm, dp); 
1991/0828    
	return 1; 
} 
 
1991/1127/sys/src/9/port/devsrv.c:33,401991/1219/sys/src/9/port/devsrv.c:41,47
1990/0227    
void 
srvreset(void) 
{ 
1991/0828    
	srv.chan = ialloc(conf.nsrv*sizeof(Chan*), 0); 
	srv.name = ialloc(conf.nsrv*NAMELEN, 0); 
1991/1219    
	srv = ialloc(conf.nsrv*sizeof(Srv), 0); 
1990/0227    
} 
 
Chan * 
1991/1127/sys/src/9/port/devsrv.c:74,851991/1219/sys/src/9/port/devsrv.c:81,92
1990/0227    
		c->offset = 0; 
		return c; 
	} 
1991/0828    
	lock(&srv); 
1991/1219    
	lock(&srvlk); 
1991/0828    
	if(waserror()){ 
		unlock(&srv); 
1991/1219    
		unlock(&srvlk); 
1991/0828    
		nexterror(); 
	} 
	f = srv.chan[c->qid.path]; 
1991/1219    
	f = srv[c->qid.path].chan; 
1991/0828    
	if(f == 0) 
1990/11211    
		error(Eshutdown); 
1991/0828    
	if(omode&OTRUNC) 
1991/1127/sys/src/9/port/devsrv.c:88,941991/1219/sys/src/9/port/devsrv.c:95,101
1990/11211    
		error(Eperm); 
1990/0227    
	close(c); 
	incref(f); 
1991/0828    
	unlock(&srv); 
1991/1219    
	unlock(&srvlk); 
1991/0828    
	poperror(); 
1990/0227    
	return f; 
} 
1991/1127/sys/src/9/port/devsrv.c:97,1241991/1219/sys/src/9/port/devsrv.c:104,138
1990/0227    
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); 
	lock(&srv); 
1991/1219    
 
	lock(&srvlk); 
1991/0828    
	if(waserror()){ 
		unlock(&srv); 
1991/1219    
		unlock(&srvlk); 
1990/0227    
		nexterror(); 
	} 
1991/0828    
	j = -1; 
	for(i=0; i<conf.nsrv; i++){ 
		if(srv.chan[i] == 0){ 
1991/1219    
		if(srv[i].chan == 0){ 
1991/0828    
			if(j == -1) 
				j = i; 
		}else if(strcmp(name, &srv.name[i*NAMELEN]) == 0) 
1991/1219    
		} 
		else if(strcmp(name, srv[i].name) == 0) 
1990/11211    
			error(Einuse); 
1991/0828    
	} 
	if(j == -1) 
		error(Enosrv); 
	srv.chan[j] = c; 
	unlock(&srv); 
1991/1219    
	sp = &srv[j]; 
	sp->chan = c; 
	unlock(&srvlk); 
1990/1002    
	poperror(); 
1991/0828    
	strcpy(&srv.name[j*NAMELEN], name); 
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; 
1991/1127/sys/src/9/port/devsrv.c:131,1481991/1219/sys/src/9/port/devsrv.c:145,163
1990/0227    
 
1991/0828    
	if(c->qid.path == CHDIR) 
1990/11211    
		error(Eperm); 
1991/0828    
	lock(&srv); 
1991/1219    
 
	lock(&srvlk); 
1990/1110    
	if(waserror()){ 
1991/0828    
		unlock(&srv); 
1991/1219    
		unlock(&srvlk); 
1990/0227    
		nexterror(); 
	} 
1991/0828    
	f = srv.chan[c->qid.path]; 
1991/1219    
	f = srv[c->qid.path].chan; 
1991/0828    
	if(f == 0) 
		error(Eshutdown); 
	if(strcmp(&srv.name[c->qid.path*NAMELEN], "boot") == 0) 
1991/1219    
	if(strcmp(srv[c->qid.path].name, "boot") == 0) 
1991/0828    
		error(Eperm); 
	srv.chan[c->qid.path] = 0; 
	unlock(&srv); 
1991/1219    
	srv[c->qid.path].chan = 0; 
	unlock(&srvlk); 
1990/0227    
	poperror(); 
1991/0828    
	close(f); 
1990/0227    
} 
1991/1127/sys/src/9/port/devsrv.c:175,1811991/1219/sys/src/9/port/devsrv.c:190,196
1990/0227    
	char buf[32]; 
 
1991/0828    
	i = c->qid.path; 
	if(srv.chan[i] != c)	/* already been written to */ 
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/1127/sys/src/9/port/devsrv.c:185,1921991/1219/sys/src/9/port/devsrv.c:200,207
1991/1127    
	f = u->p->fgrp; 
	lock(f); 
1991/1011    
	fdtochan(fd, -1, 0);	/* error check only */ 
1991/1127    
	srv.chan[i] = f->fd[fd]; 
1991/0921    
	incref(srv.chan[i]); 
1991/1219    
	srv[i].chan = f->fd[fd]; 
	incref(srv[i].chan); 
1991/1127    
	unlock(f); 
1990/0227    
	return n; 
} 
1991/1219/sys/src/9/port/devsrv.c:3,91992/0111/sys/src/9/port/devsrv.c:3,9 (short | long)
Move error.h to ../port. Change errors to actual strings.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1992/0111    
#include	"../port/error.h" 
1991/0828    
 
1990/0227    
#include	"devtab.h" 
 
1992/0111/sys/src/9/port/devsrv.c:124,1301992/0114/sys/src/9/port/devsrv.c:124,130 (short | long)
1990/11211    
			error(Einuse); 
1991/0828    
	} 
	if(j == -1) 
		error(Enosrv); 
1992/0114    
		exhausted("server slots"); 
1991/1219    
	sp = &srv[j]; 
	sp->chan = c; 
	unlock(&srvlk); 
1992/0114/sys/src/9/port/devsrv.c:199,2071992/0226/sys/src/9/port/devsrv.c:199,212 (short | long)
1990/0227    
	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; 
} 
1992/0226/sys/src/9/port/devsrv.c:1,51992/0321/sys/src/9/port/devsrv.c:1,5 (short | long)
Move lib.h to ../port.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0321/sys/src/9/port/devsrv.c:127,1321992/0520/sys/src/9/port/devsrv.c:127,133 (short | long)
1992/0114    
		exhausted("server slots"); 
1991/1219    
	sp = &srv[j]; 
	sp->chan = c; 
1992/0520    
	incref(c); 
1991/1219    
	unlock(&srvlk); 
1990/1002    
	poperror(); 
1991/1219    
	strncpy(sp->name, name, NAMELEN); 
1992/0321/sys/src/9/port/devsrv.c:188,1971992/0520/sys/src/9/port/devsrv.c:189,196
1991/1127    
	Fgrp *f; 
1990/0227    
	int i, fd; 
	char buf[32]; 
1992/0520    
	Chan *c1; 
1990/0227    
 
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 */ 
1992/0321/sys/src/9/port/devsrv.c:198,2031992/0520/sys/src/9/port/devsrv.c:197,203
1990/0227    
	buf[n] = 0; 
	fd = strtoul(buf, 0, 0); 
1991/1127    
	f = u->p->fgrp; 
1992/0520    
 
1991/1127    
	lock(f); 
1992/0226    
	if(waserror()){ 
		unlock(f); 
1992/0321/sys/src/9/port/devsrv.c:204,2121992/0520/sys/src/9/port/devsrv.c:204,226
1992/0226    
		nexterror(); 
	} 
1991/1011    
	fdtochan(fd, -1, 0);	/* error check only */ 
1991/1219    
	srv[i].chan = f->fd[fd]; 
	incref(srv[i].chan); 
1992/0520    
	c1 = f->fd[fd]; 
	incref(c1); 
1991/1127    
	unlock(f); 
1992/0520    
	poperror(); 
 
	lock(&srvlk); 
	if (waserror()) { 
		unlock(&srvlk); 
		close(c1); 
		nexterror(); 
	} 
	i = c->qid.path; 
	if(srv[i].chan != c)	/* already been written to */ 
		error(Egreg); 
	close(c); 
	srv[i].chan = c1; 
	unlock(&srvlk); 
1992/0226    
	poperror(); 
1990/0227    
	return n; 
} 
1992/0520/sys/src/9/port/devsrv.c:218,2241992/0607/sys/src/9/port/devsrv.c:218,223 (short | long)
1992/0520    
	i = c->qid.path; 
	if(srv[i].chan != c)	/* already been written to */ 
		error(Egreg); 
	close(c); 
	srv[i].chan = c1; 
	unlock(&srvlk); 
1992/0226    
	poperror(); 
1992/0607/sys/src/9/port/devsrv.c:7,131992/0620/sys/src/9/port/devsrv.c:7,13 (short | long)
1991/0828    
 
1990/0227    
#include	"devtab.h" 
 
1991/0828    
typedef struct	Srv Srv; 
1992/0620    
typedef struct Srv Srv; 
1991/0828    
struct Srv{ 
1991/1219    
	char	name[NAMELEN]; 
	char	owner[NAMELEN]; 
1992/0607/sys/src/9/port/devsrv.c:196,2031992/0620/sys/src/9/port/devsrv.c:196,203
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; 
1992/0520    
 
1992/0620    
	f = u->p->fgrp; 
1991/1127    
	lock(f); 
1992/0226    
	if(waserror()){ 
		unlock(f); 
1992/0607/sys/src/9/port/devsrv.c:218,2231992/0620/sys/src/9/port/devsrv.c:218,224
1992/0520    
	i = c->qid.path; 
	if(srv[i].chan != c)	/* already been written to */ 
		error(Egreg); 
1992/0620    
 
1992/0520    
	srv[i].chan = c1; 
	unlock(&srvlk); 
1992/0226    
	poperror(); 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)