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

1990/11211/port/devsrv.c (diff list | history)

1990/11211/sys/src/9/port/devsrv.c:1,2871991/0318/sys/src/9/port/devsrv.c:1,287 (short | long | prev | next)
1990/0227    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
#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 { 
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    
	}; 
}; 
1990/0227    
 
void 
srvinit(void) 
{ 
} 
 
void 
srvreset(void) 
{ 
} 
 
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; 
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/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; 
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); 
1990/0227    
} 
 
Chan * 
srvopen(Chan *c, int omode) 
{ 
1990/1110    
	Entry *e; 
1990/0227    
	Chan *f; 
 
1990/11211    
	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; 
	} 
1990/1110    
	if((e=c->aux) == 0) 
1990/11211    
		error(Egreg); 
1990/1110    
	if((f=e->chan) == 0) 
1990/11211    
		error(Eshutdown); 
1990/1110    
	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); 
	return f; 
} 
 
void 
srvcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1990/1110    
	Entry *parent, *e; 
1990/0227    
 
1990/1110    
	parent = c->aux; 
1990/1002    
	isdir(c); 
	lock(parent); 
1990/1110    
	if (waserror()){ 
1990/1002    
		unlock(parent); 
1990/0227    
		nexterror(); 
	} 
1990/1110    
	for(e=parent->entries; e; e=e->next) 
		if(strcmp(name, e->dir.name) == 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); 
	poperror(); 
1990/1121    
	c->qid = e->dir.qid; 
1990/1002    
	c->aux = e; 
1990/0227    
	c->flag |= COPEN; 
1990/1002    
	c->mode = omode; 
1990/0227    
} 
 
void 
srvremove(Chan *c) 
{ 
1990/1110    
	Entry *e; 
1990/0227    
 
1990/1110    
	e = c->aux; 
	if(e->parent == 0) 
1990/11211    
		error(Eperm); 
1990/1002    
	lock(e->parent); 
1990/1110    
	if(waserror()){ 
1990/1002    
		unlock(e->parent); 
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); 
1990/0227    
	poperror(); 
1990/1002    
	free(e); 
1990/0227    
} 
 
void 
srvwstat(Chan *c, char *dp) 
{ 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
void 
srvclose(Chan *c) 
{ 
} 
 
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 
srvread(Chan *c, void *va, long n) 
{ 
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; 
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; 
1990/0227    
} 
 
long 
srvwrite(Chan *c, void *va, long n) 
{ 
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) 
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 */ 
1990/1002    
	e->chan = u->fd[fd]; 
	incref(e->chan); 
	unlock(e); 
	poperror(); 
1990/0227    
	return n; 
} 


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