Ejemplo n.º 1
0
static int pipetapfd(struct chan *chan, struct fd_tap *tap, int cmd)
{
	int ret;
	Pipe *p;
	int which = 1;
	uint64_t kludge;

	p = chan->aux;
	kludge = (uint64_t)p;
#define DEVPIPE_LEGAL_DATA_TAPS (FDTAP_FILT_READABLE | FDTAP_FILT_WRITABLE | \
                                 FDTAP_FILT_HANGUP | FDTAP_FILT_ERROR)

	switch (NETTYPE(chan->qid.path)) {
	case Qdata0:
		which = 0;
		/* fall through */
	case Qdata1:
		kludge |= which;

		if (tap->filter & ~DEVPIPE_LEGAL_DATA_TAPS) {
			set_errno(ENOSYS);
			set_errstr("Unsupported #%s data tap %p, must be %p", devname(),
			           tap->filter, DEVPIPE_LEGAL_DATA_TAPS);
			return -1;
		}
		spin_lock(&p->tap_lock);
		switch (cmd) {
		case (FDTAP_CMD_ADD):
			if (SLIST_EMPTY(&p->data_taps[which]))
				qio_set_wake_cb(p->q[which], pipe_wake_cb, (void *)kludge);
			SLIST_INSERT_HEAD(&p->data_taps[which], tap, link);
			ret = 0;
			break;
		case (FDTAP_CMD_REM):
			SLIST_REMOVE(&p->data_taps[which], tap, fd_tap, link);
			if (SLIST_EMPTY(&p->data_taps[which]))
				qio_set_wake_cb(p->q[which], 0, (void *)kludge);
			ret = 0;
			break;
		default:
			set_errno(ENOSYS);
			set_errstr("Unsupported #%s data tap command %p", devname(), cmd);
			ret = -1;
		}
		spin_unlock(&p->tap_lock);
		return ret;
	default:
		set_errno(ENOSYS);
		set_errstr("Can't tap #%s file type %d", devname(),
		           NETTYPE(chan->qid.path));
		return -1;
	}
}
Ejemplo n.º 2
0
long
netifread(struct netif *nif, struct chan *c, void *a, long n, uint32_t offset)
{
	int i, j;
	struct netfile *f;
	char *p;

	if (c->qid.type & QTDIR)
		return devdirread(c, a, n, (struct dirtab *)nif, 0, netifgen);

	switch (NETTYPE(c->qid.path)) {
		case Ndataqid:
			f = nif->f[NETID(c->qid.path)];
			return qread(f->in, a, n);
		case Nctlqid:
			return readnum(offset, a, n, NETID(c->qid.path), NUMSIZE);
		case Nstatqid:
			p = kzmalloc(READSTR, 0);
			if (p == NULL)
				return 0;
			j = snprintf(p, READSTR, "in: %d\n", nif->inpackets);
			j += snprintf(p + j, READSTR - j, "link: %d\n", nif->link);
			j += snprintf(p + j, READSTR - j, "out: %d\n", nif->outpackets);
			j += snprintf(p + j, READSTR - j, "crc errs: %d\n", nif->crcs);
			j += snprintf(p + j, READSTR - j, "overflows: %d\n",
						  nif->overflows);
			j += snprintf(p + j, READSTR - j, "soft overflows: %d\n",
						  nif->soverflows);
			j += snprintf(p + j, READSTR - j, "framing errs: %d\n",
						  nif->frames);
			j += snprintf(p + j, READSTR - j, "buffer errs: %d\n", nif->buffs);
			j += snprintf(p + j, READSTR - j, "output errs: %d\n", nif->oerrs);
			j += snprintf(p + j, READSTR - j, "prom: %d\n", nif->prom);
			j += snprintf(p + j, READSTR - j, "mbps: %d\n", nif->mbps);
			j += snprintf(p + j, READSTR - j, "addr: ");
			for (i = 0; i < nif->alen; i++)
				j += snprintf(p + j, READSTR - j, "%02.2x", nif->addr[i]);
			snprintf(p + j, READSTR - j, "\n");
			n = readstr(offset, a, n, p);
			kfree(p);
			return n;
		case Naddrqid:
			p = kzmalloc(READSTR, 0);
			if (p == NULL)
				return 0;
			j = 0;
			for (i = 0; i < nif->alen; i++)
				j += snprintf(p + j, READSTR - j, "%02.2x", nif->addr[i]);
			n = readstr(offset, a, n, p);
			kfree(p);
			return n;
		case Ntypeqid:
			f = nif->f[NETID(c->qid.path)];
			return readnum(offset, a, n, f->type, NUMSIZE);
		case Nifstatqid:
			return 0;
	}
	error(Ebadarg);
	return -1;	/* not reached */
}
Ejemplo n.º 3
0
static long pipebwrite(struct chan *c, struct block *bp, uint32_t junk)
{
	long n;
	Pipe *p;
	//Prog *r;

	p = c->aux;
	switch (NETTYPE(c->qid.path)) {
		case Qdata0:
			if (c->flag & O_NONBLOCK)
				n = qbwrite_nonblock(p->q[1], bp);
			else
				n = qbwrite(p->q[1], bp);
			break;

		case Qdata1:
			if (c->flag & O_NONBLOCK)
				n = qbwrite_nonblock(p->q[0], bp);
			else
				n = qbwrite(p->q[0], bp);
			break;

		default:
			n = 0;
			panic("pipebwrite");
	}

	return n;
}
Ejemplo n.º 4
0
static long piperead(struct chan *c, void *va, long n, int64_t ignored)
{
	Pipe *p;

	p = c->aux;

	switch (NETTYPE(c->qid.path)) {
		case Qdir:
			return devdirread(c, va, n, p->pipedir, ARRAY_SIZE(pipedir),
							  pipegen);
		case Qdata0:
			if (c->flag & O_NONBLOCK)
				return qread_nonblock(p->q[0], va, n);
			else
				return qread(p->q[0], va, n);
		case Qdata1:
			if (c->flag & O_NONBLOCK)
				return qread_nonblock(p->q[1], va, n);
			else
				return qread(p->q[1], va, n);
		default:
			panic("piperead");
	}
	return -1;	/* not reached */
}
Ejemplo n.º 5
0
/*
 *  A write to a closed pipe causes an EPIPE error to be thrown.
 */
static long pipewrite(struct chan *c, void *va, long n, int64_t ignored)
{
	Pipe *p;
	//Prog *r;

	p = c->aux;

	switch (NETTYPE(c->qid.path)) {
		case Qdata0:
			if (c->flag & O_NONBLOCK)
				n = qwrite_nonblock(p->q[1], va, n);
			else
				n = qwrite(p->q[1], va, n);
			break;

		case Qdata1:
			if (c->flag & O_NONBLOCK)
				n = qwrite_nonblock(p->q[0], va, n);
			else
				n = qwrite(p->q[0], va, n);
			break;

		default:
			panic("pipewrite");
	}

	return n;
}
Ejemplo n.º 6
0
static struct walkqid *pipewalk(struct chan *c, struct chan *nc, char **name,
								int nname)
{
	struct walkqid *wq;
	Pipe *p;

	p = c->aux;
	wq = devwalk(c, nc, name, nname, p->pipedir, ARRAY_SIZE(pipedir), pipegen);
	if (wq != NULL && wq->clone != NULL && wq->clone != c) {
		qlock(&p->qlock);
		kref_get(&p->ref, 1);
		if (c->flag & COPEN) {
			switch (NETTYPE(c->qid.path)) {
				case Qdata0:
					p->qref[0]++;
					break;
				case Qdata1:
					p->qref[1]++;
					break;
			}
		}
		qunlock(&p->qlock);
	}
	return wq;
}
Ejemplo n.º 7
0
static int pipestat(struct chan *c, uint8_t * db, int n)
{
	Pipe *p;
	struct dir dir;
	struct dirtab *tab;
	int perm;

	p = c->aux;
	tab = p->pipedir;

	switch (NETTYPE(c->qid.path)) {
		case Qdir:
			devdir(c, c->qid, ".", 0, eve, DMDIR | 0555, &dir);
			break;
		case Qdata0:
			perm = tab[1].perm;
			perm |= qreadable(p->q[0]) ? DMREADABLE : 0;
			perm |= qwritable(p->q[0]) ? DMWRITABLE : 0;
			devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, perm, &dir);
			break;
		case Qdata1:
			perm = tab[2].perm;
			perm |= qreadable(p->q[1]) ? DMREADABLE : 0;
			perm |= qwritable(p->q[1]) ? DMWRITABLE : 0;
			devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, perm, &dir);
			break;
		default:
			panic("pipestat");
	}
	n = convD2M(&dir, db, n);
	if (n < BIT16SZ)
		error(ENODATA, ERROR_FIXME);
	return n;
}
Ejemplo n.º 8
0
Archivo: devuart.c Proyecto: 8l/inferno
static int
uartstat(Chan *c, uchar *dp, int n)
{
	if(NETTYPE(c->qid.path) == Ndataqid)
		setlength(NETID(c->qid.path));
	return devstat(c, dp, n, uartdir, ndir, devgen);
}
Ejemplo n.º 9
0
Archivo: devuart.c Proyecto: 8l/inferno
static long
uartwrite(Chan *c, void *buf, long n, vlong offset)
{
	Uart *p;
	char cmd[32];

	USED(offset);

	if(c->qid.type & QTDIR)
		error(Eperm);

	p = uart[NETID(c->qid.path)];

	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
		return qwrite(p->oq, buf, n);
	case Nctlqid:

		if(n >= sizeof(cmd))
			n = sizeof(cmd)-1;
		memmove(cmd, buf, n);
		cmd[n] = 0;
		uartctl(p, cmd);
		return n;
	}
}
Ejemplo n.º 10
0
Block*
netifbread(Netif *nif, Chan *c, long n, vlong offset)
{
	Netfile *f;
	Block *bp;

	if((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
		return devbread(c, n, offset);

	f = nif->f[NETID(c->qid.path)];
	if(f->fat){
		/*
		 * Frame at a time (fat) allows us to provide
		 * non-blocking performance with blocking semantics
		 * for consumers that know ahead of time data is
		 * contained within a single frame.  Once empty, we
		 * get in line with other blocking reads and wait our
		 * turn.
		 */
		for(;;){
			if(bp = qget(f->iq))
				return bp;
			if(waserror())
				return nil;
			qsleep(f->iq);
			poperror();
		}
	}
	return qbread(f->iq, n);
}
Ejemplo n.º 11
0
static long
eiawrite(Chan *c, void *buf, long n, vlong offset)
{
	ssize_t cnt;
	char cmd[Maxctl];
	int port = NETID(c->qid.path);

	USED(offset);

	if(c->qid.type & QTDIR)
		error(Eperm);

	switch(NETTYPE(c->qid.path)) {
	case Ndataqid:
	  	osenter(); 
		cnt = write(eia[port].fd, buf, n);
		osleave(); 
		if(cnt == -1)
			oserror();
		return cnt;
	case Nctlqid:
		if(n >= (long)sizeof(cmd))
			n = sizeof(cmd)-1;
		memmove(cmd, buf, n);
		cmd[n] = 0;
		wrctl(port, cmd);
		return n;
	}
	return 0;
}
Ejemplo n.º 12
0
static long
eiaread(Chan *c, void *buf, long n, vlong offset)
{
	ssize_t cnt;
	int port = NETID(c->qid.path);

	if(c->qid.type & QTDIR)
		return devdirread(c, buf, n, eiadir, ndir, devgen);

	switch(NETTYPE(c->qid.path)) {
	case Ndataqid:
	  	osenter(); 
		cnt = read(eia[port].fd, buf, n);
		osleave(); 
		if(cnt == -1)
			oserror();
		return cnt;
	case Nctlqid:
		return readnum(offset, buf, n, port, NUMSIZE);
	case Nstatqid:
		return rdstat(port, buf, n, offset);
	}

	return 0;
}
Ejemplo n.º 13
0
static int pipewstat(struct chan *c, uint8_t *dp, int n)
{
	ERRSTACK(2);
	struct dir *d;
	Pipe *p;
	int d1;

	if (c->qid.type & QTDIR)
		error(EPERM, ERROR_FIXME);
	p = c->aux;
	if (strcmp(current->user, p->user) != 0)
		error(EPERM, ERROR_FIXME);
	d = kzmalloc(sizeof(*d) + n, 0);
	if (waserror()) {
		kfree(d);
		nexterror();
	}
	n = convM2D(dp, n, d, (char *)&d[1]);
	if (n == 0)
		error(ENODATA, ERROR_FIXME);
	d1 = NETTYPE(c->qid.path) == Qdata1;
	if (!emptystr(d->name)) {
		validwstatname(d->name);
		if (strlen(d->name) >= KNAMELEN)
			error(ENAMETOOLONG, ERROR_FIXME);
		if (strncmp(p->pipedir[1 + !d1].name, d->name, KNAMELEN) == 0)
			error(EEXIST, ERROR_FIXME);
		strncpy(p->pipedir[1 + d1].name, d->name, KNAMELEN);
	}
	if (d->mode != ~0UL)
		p->pipedir[d1 + 1].perm = d->mode & 0777;
	poperror();
	kfree(d);
	return n;
}
Ejemplo n.º 14
0
static long
eiaread(Chan *c, void *buf, long n, vlong offset)
{
	DWORD cnt;
	int port = NETID(c->qid.path);
	BOOL good;

	if(c->qid.type & QTDIR)
		return devdirread(c, buf, n, eiadir, ndir, devgen);

	switch(NETTYPE(c->qid.path)) {
	case Ndataqid:
		cnt = 0;
		// if ReadFile timeouts and cnt==0 then just re-read
		// this will give osleave() a chance to detect an
		// interruption (i.e. killprog)
		while(cnt==0) {
  			osenter(); 
			good = ReadFile(eia[port].comfh, buf, n, &cnt, NULL);
			SleepEx(0,FALSE);  //allow another thread access to port
			osleave();
			if(!good)
				oserror();
		}
		return cnt;
	case Nctlqid:
		return readnum(offset, buf, n, eia[port].id, NUMSIZE);
	case Nstatqid:
		return rdstat(port, buf, n, offset);
	}

	return 0;
}
Ejemplo n.º 15
0
static int
pipegen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
{
	int id, len;
	Qid qid;
	Pipe *p;

	USED(name);
	if(i == DEVDOTDOT){
		devdir(c, c->qid, "#|", 0, eve, 0555, dp);
		return 1;
	}
	i++;	/* skip . */
	if(tab==0 || i>=ntab)
		return -1;
	tab += i;
	p = c->aux;
	switch(NETTYPE(tab->qid.path)){
	case Qdata0:
		len = qlen(p->q[0]);
		break;
	case Qdata1:
		len = qlen(p->q[1]);
		break;
	default:
		len = tab->length;
		break;
	}
	id = NETID(c->qid.path);
	qid.path = NETQID(id, tab->qid.path);
	qid.vers = 0;
	qid.type = QTFILE;
	devdir(c, qid, tab->name, len, eve, tab->perm, dp);
	return 1;
}
Ejemplo n.º 16
0
static long
pipebwrite(Chan *c, Block *bp, ulong)
{
	long n;
	Pipe *p;

	if(waserror()) {
		/* avoid notes when pipe is a mounted queue */
		if((c->flag & CMSG) == 0)
			postnote(up, 1, "sys: write on closed pipe", NUser);
		nexterror();
	}

	p = c->aux;
	switch(NETTYPE(c->qid.path)){
	case Qdata0:
		n = qbwrite(p->q[1], bp);
		break;

	case Qdata1:
		n = qbwrite(p->q[0], bp);
		break;

	default:
		n = 0;
		panic("pipebwrite");
	}

	poperror();
	return n;
}
Ejemplo n.º 17
0
/*
 *  if the stream doesn't exist, create it
 */
static Chan*
pipeopen(Chan *c, int omode)
{
	Pipe *p;

	if(c->qid.type & QTDIR){
		if(omode != OREAD)
			error(Ebadarg);
		c->mode = omode;
		c->flag |= COPEN;
		c->offset = 0;
		return c;
	}

	p = c->aux;
	qlock(p);
	switch(NETTYPE(c->qid.path)){
	case Qdata0:
		p->qref[0]++;
		break;
	case Qdata1:
		p->qref[1]++;
		break;
	}
	qunlock(p);

	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	c->iounit = qiomaxatomic;
	return c;
}
Ejemplo n.º 18
0
/*
 *  a write to a closed pipe causes a note to be sent to
 *  the process.
 */
static long
pipewrite(Chan *c, void *va, long n, vlong)
{
	Pipe *p;

	if(!islo())
		print("pipewrite hi %#p\n", getcallerpc(&c));
	if(waserror()) {
		/* avoid notes when pipe is a mounted queue */
		if((c->flag & CMSG) == 0)
			postnote(up, 1, "sys: write on closed pipe", NUser);
		nexterror();
	}

	p = c->aux;

	switch(NETTYPE(c->qid.path)){
	case Qdata0:
		n = qwrite(p->q[1], va, n);
		break;

	case Qdata1:
		n = qwrite(p->q[0], va, n);
		break;

	default:
		panic("pipewrite");
	}

	poperror();
	return n;
}
Ejemplo n.º 19
0
static int
pipestat(Chan *c, uchar *db, int n)
{
	Pipe *p;
	Dir dir;

	p = c->aux;

	switch(NETTYPE(c->qid.path)){
	case Qdir:
		devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir);
		break;
	case Qdata0:
		devdir(c, c->qid, "data", qlen(p->q[0]), eve, p->perm, &dir);
		break;
	case Qdata1:
		devdir(c, c->qid, "data1", qlen(p->q[1]), eve, p->perm, &dir);
		break;
	default:
		panic("pipestat");
	}
	n = convD2M(&dir, db, n);
	if(n < BIT16SZ)
		error(Eshortstat);
	return n;
}
Ejemplo n.º 20
0
static int
pipewstat(Chan* c, uchar* db, int n)
{
	int m;
	Dir *dir;
	Pipe *p;

	p = c->aux;
	if(strcmp(up->user, eve) != 0)
		error(Eperm);
	if(NETTYPE(c->qid.path) == Qdir)
		error(Eisdir);

	dir = smalloc(sizeof(Dir)+n);
	if(waserror()){
		free(dir);
		nexterror();
	}
	m = convM2D(db, n, &dir[0], (char*)&dir[1]);
	if(m == 0)
		error(Eshortstat);
	if(!emptystr(dir[0].uid))
		error("can't change owner");
	if(dir[0].mode != ~0UL)
		p->perm = dir[0].mode;
	poperror();
	free(dir);
	return m;
}
Ejemplo n.º 21
0
static Walkqid*
pipewalk(Chan *c, Chan *nc, char **name, int nname)
{
	Walkqid *wq;
	Pipe *p;

	wq = devwalk(c, nc, name, nname, pipedir, NPIPEDIR, pipegen);
	if(wq != nil && wq->clone != nil && wq->clone != c){
		p = c->aux;
		qlock(p);
		p->ref++;
		if(c->flag & COPEN){
			print("channel open in pipewalk\n");
			switch(NETTYPE(c->qid.path)){
			case Qdata0:
				p->qref[0]++;
				break;
			case Qdata1:
				p->qref[1]++;
				break;
			}
		}
		qunlock(p);
	}
	return wq;
}
Ejemplo n.º 22
0
static int
pipewstat(Chan *c, uchar *dp, int n)
{
	Dir *d;
	Pipe *p;
	int d1;

	if (c->qid.type&QTDIR)
		error(Eperm);
	p = c->aux;
	if(strcmp(up->env->user, p->user) != 0)
		error(Eperm);
	d = smalloc(sizeof(*d)+n);
	if(waserror()){
		free(d);
		nexterror();
	}
	n = convM2D(dp, n, d, (char*)&d[1]);
	if(n == 0)
		error(Eshortstat);
	d1 = NETTYPE(c->qid.path) == Qdata1;
	if(!emptystr(d->name)){
		validwstatname(d->name);
		if(strlen(d->name) >= KNAMELEN)
			error(Efilename);
		if(strcmp(p->pipedir[1+!d1].name, d->name) == 0)
			error(Eexist);
		kstrcpy(p->pipedir[1+d1].name, d->name, KNAMELEN);
	}
	if(d->mode != ~0U)
		p->pipedir[d1 + 1].perm = d->mode & 0777;
	poperror();
	free(d);
	return n;
}
Ejemplo n.º 23
0
static Walkqid*
pipewalk(Chan *c, Chan *nc, char **name, int nname)
{
	Walkqid *wq;
	Pipe *p;

	p = c->aux;
	wq = devwalk(c, nc, name, nname, p->pipedir, nelem(pipedir), pipegen);
	if(wq != nil && wq->clone != nil && wq->clone != c){
		qlock(&p->l);
		p->ref++;
		if(c->flag & COPEN){
			switch(NETTYPE(c->qid.path)){
			case Qdata0:
				p->qref[0]++;
				break;
			case Qdata1:
				p->qref[1]++;
				break;
			}
		}
		qunlock(&p->l);
	}
	return wq;
}
Ejemplo n.º 24
0
static void
uartclose(Chan *c)
{
	Uart *p;

	if(c->qid.type & QTDIR)
		return;
	if((c->flag & COPEN) == 0)
		return;
	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
	case Nctlqid:
		p = uart[NETID(c->qid.path)];
		qlock(p);
		if(--(p->opens) == 0){
			qclose(p->iq);
			ilock(&p->rlock);
			p->ir = p->iw = p->istage;
			iunlock(&p->rlock);

			/*
			 */
			qhangup(p->oq, nil);
			if(!waserror()){
				uartdrainoutput(p);
				poperror();
			}
			qclose(p->oq);
			uartdisable(p);
			p->dcd = p->dsr = p->dohup = 0;
		}
		qunlock(p);
		break;
	}
}
Ejemplo n.º 25
0
Block*
netifbread(Netif *nif, Chan *c, long n, ulong offset)
{
	if((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
		return devbread(c, n, offset);

	return qbread(nif->f[NETID(c->qid.path)]->in, n);
}
Ejemplo n.º 26
0
struct block *netifbread(struct ether *nif, struct chan *c, long n,
						 uint32_t offset)
{
	if ((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
		return devbread(c, n, offset);

	return qbread(nif->f[NETID(c->qid.path)]->in, n);
}
Ejemplo n.º 27
0
Block*
netifbread(Netif *nif, Chan *c, int32_t n, int64_t offset)
{
	if((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
		return devbread(c, n, offset);

	return qbread(nif->f[NETID(c->qid.path)]->iq, n);
}
Ejemplo n.º 28
0
Chan*
netifopen(Netif *nif, Chan *c, int omode)
{
	Proc *up = externup();
	int id;
	Netfile *f;

	id = 0;
	if(c->qid.type & QTDIR){
		if(omode != OREAD)
			error(Eperm);
	} else {
		switch(NETTYPE(c->qid.path)){
		case Ndataqid:
		case Nctlqid:
			id = NETID(c->qid.path);
			openfile(nif, id);
			break;
		case Ncloneqid:
			id = openfile(nif, -1);
			c->qid.path = NETQID(id, Nctlqid);
			break;
		default:
			if(omode != OREAD)
				error(Ebadarg);
		}
		switch(NETTYPE(c->qid.path)){
		case Ndataqid:
		case Nctlqid:
			f = nif->f[id];
			if(netown(f, up->user, omode&7) < 0){
				netifclose(nif, c);
				error(Eperm);
			}
			break;
		}
	}
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	c->iounit = qiomaxatomic;
	return c;
}
Ejemplo n.º 29
0
static int
eiawstat(Chan *c, uchar *dp, int n)
{
	Dir d;
	int i;

	if(!iseve())
		error(Eperm);
	if(c->qid.type & QTDIR)
		error(Eperm);
	if(NETTYPE(c->qid.path) == Nstatqid)
		error(Eperm);

	n = convM2D(dp, n, &d, nil);
	i = Nqid*NETID(c->qid.path)+NETTYPE(c->qid.path)-Ndataqid;
	if(d.mode != ~0UL)
		eiadir[i+1].perm = d.mode&0666;
	return n;
}
Ejemplo n.º 30
0
void
netifclose(Netif *nif, Chan *c)
{
	Netfile *f;
	int t;
	Netaddr *ap;

	if((c->flag & COPEN) == 0)
		return;

	t = NETTYPE(c->qid.path);
	if(t != Ndataqid && t != Nctlqid)
		return;

	f = nif->f[NETID(c->qid.path)];
	qlock(&f->q);
	if(--(f->inuse) == 0){
		if(f->prom){
			qlock(&nif->q);
			if(--(nif->prom) == 0 && nif->promiscuous != nil)
				nif->promiscuous(nif->arg, 0);
			qunlock(&nif->q);
			f->prom = 0;
		}
		if(f->scan){
			qlock(&nif->q);
			if(--(nif->_scan) == 0 && nif->scanbs != nil)
				nif->scanbs(nif->arg, 0);
			qunlock(&nif->q);
			f->prom = 0;
			f->scan = 0;
		}
		if(f->nmaddr){
			qlock(&nif->q);
			t = 0;
			for(ap = nif->maddr; ap; ap = ap->next){
				if(f->maddr[t/8] & (1<<(t%8)))
					netmulti(nif, f, ap->addr, 0);
			}
			qunlock(&nif->q);
			f->nmaddr = 0;
		}
		if(f->type < 0){
			qlock(&nif->q);
			--(nif->all);
			qunlock(&nif->q);
		}
		f->owner[0] = 0;
		f->type = 0;
		f->bridge = 0;
		f->headersonly = 0;
		qclose(f->iq);
	}
	qunlock(&f->q);
}