if(c->flag & COPEN){
/*
* closing either side hangs up the stream
*/
switch(NETTYPE(c->qid.path)){
case Qdata0:
p->qref[0]--;
if(p->qref[0] == 0){
qhangup(p->q[1], 0);
qclose(p->q[0]);
}
break;
case Qdata1:
p->qref[1]--;
if(p->qref[1] == 0){
qhangup(p->q[0], 0);
qclose(p->q[1]);
}
break;
}
}
/*
* if both sides are closed, they are reusable
*/
if(p->qref[0] == 0 && p->qref[1] == 0){
qreopen(p->q[0]);
qreopen(p->q[1]);
}
/*
* free the structure on last close
*/
p->ref--;
if(p->ref == 0){
qunlock(p);
free(p->q[0]);
free(p->q[1]);
free(p);
} else
qunlock(p);
}
static long
piperead(Chan *c, void *va, long n, vlong)
{
Pipe *p;
p = c->aux;
switch(NETTYPE(c->qid.path)){
case Qdir:
return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen);
case Qdata0:
return qread(p->q[0], va, n);
case Qdata1:
return qread(p->q[1], va, n);
default:
panic("piperead");
}
return -1; /* not reached */
}
static Block*
pipebread(Chan *c, long n, ulong offset)
{
Pipe *p;
p = c->aux;
switch(NETTYPE(c->qid.path)){
case Qdata0:
return qbread(p->q[0], n);
case Qdata1:
return qbread(p->q[1], n);
}
return devbread(c, n, offset);
}
/*
* 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 %lux\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;
}
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;