1*37da2899SCharles.Forsyth #include "dat.h"
2*37da2899SCharles.Forsyth #include "fns.h"
3*37da2899SCharles.Forsyth #include "error.h"
4*37da2899SCharles.Forsyth #include <interp.h>
5*37da2899SCharles.Forsyth
6*37da2899SCharles.Forsyth #define NETTYPE(x) ((ulong)(x)&0x1f)
7*37da2899SCharles.Forsyth #define NETID(x) (((ulong)(x))>>5)
8*37da2899SCharles.Forsyth #define NETQID(i,t) (((i)<<5)|(t))
9*37da2899SCharles.Forsyth
10*37da2899SCharles.Forsyth typedef struct Pipe Pipe;
11*37da2899SCharles.Forsyth struct Pipe
12*37da2899SCharles.Forsyth {
13*37da2899SCharles.Forsyth QLock l;
14*37da2899SCharles.Forsyth Pipe* next;
15*37da2899SCharles.Forsyth int ref;
16*37da2899SCharles.Forsyth ulong path;
17*37da2899SCharles.Forsyth Queue* q[2];
18*37da2899SCharles.Forsyth int qref[2];
19*37da2899SCharles.Forsyth Dirtab* pipedir;
20*37da2899SCharles.Forsyth char* user;
21*37da2899SCharles.Forsyth };
22*37da2899SCharles.Forsyth
23*37da2899SCharles.Forsyth static struct
24*37da2899SCharles.Forsyth {
25*37da2899SCharles.Forsyth Lock l;
26*37da2899SCharles.Forsyth ulong path;
27*37da2899SCharles.Forsyth int pipeqsize;
28*37da2899SCharles.Forsyth } pipealloc;
29*37da2899SCharles.Forsyth
30*37da2899SCharles.Forsyth enum
31*37da2899SCharles.Forsyth {
32*37da2899SCharles.Forsyth Qdir,
33*37da2899SCharles.Forsyth Qdata0,
34*37da2899SCharles.Forsyth Qdata1
35*37da2899SCharles.Forsyth };
36*37da2899SCharles.Forsyth
37*37da2899SCharles.Forsyth Dirtab pipedir[] =
38*37da2899SCharles.Forsyth {
39*37da2899SCharles.Forsyth ".", {Qdir,0,QTDIR}, 0, DMDIR|0500,
40*37da2899SCharles.Forsyth "data", {Qdata0}, 0, 0660,
41*37da2899SCharles.Forsyth "data1", {Qdata1}, 0, 0660,
42*37da2899SCharles.Forsyth };
43*37da2899SCharles.Forsyth
44*37da2899SCharles.Forsyth static void
freepipe(Pipe * p)45*37da2899SCharles.Forsyth freepipe(Pipe *p)
46*37da2899SCharles.Forsyth {
47*37da2899SCharles.Forsyth if(p != nil){
48*37da2899SCharles.Forsyth free(p->user);
49*37da2899SCharles.Forsyth free(p->q[0]);
50*37da2899SCharles.Forsyth free(p->q[1]);
51*37da2899SCharles.Forsyth free(p->pipedir);
52*37da2899SCharles.Forsyth free(p);
53*37da2899SCharles.Forsyth }
54*37da2899SCharles.Forsyth }
55*37da2899SCharles.Forsyth
56*37da2899SCharles.Forsyth static void
pipeinit(void)57*37da2899SCharles.Forsyth pipeinit(void)
58*37da2899SCharles.Forsyth {
59*37da2899SCharles.Forsyth pipealloc.pipeqsize = 32*1024;
60*37da2899SCharles.Forsyth }
61*37da2899SCharles.Forsyth
62*37da2899SCharles.Forsyth /*
63*37da2899SCharles.Forsyth * create a pipe, no streams are created until an open
64*37da2899SCharles.Forsyth */
65*37da2899SCharles.Forsyth static Chan*
pipeattach(char * spec)66*37da2899SCharles.Forsyth pipeattach(char *spec)
67*37da2899SCharles.Forsyth {
68*37da2899SCharles.Forsyth Pipe *p;
69*37da2899SCharles.Forsyth Chan *c;
70*37da2899SCharles.Forsyth
71*37da2899SCharles.Forsyth c = devattach('|', spec);
72*37da2899SCharles.Forsyth p = malloc(sizeof(Pipe));
73*37da2899SCharles.Forsyth if(p == 0)
74*37da2899SCharles.Forsyth error(Enomem);
75*37da2899SCharles.Forsyth if(waserror()){
76*37da2899SCharles.Forsyth freepipe(p);
77*37da2899SCharles.Forsyth nexterror();
78*37da2899SCharles.Forsyth }
79*37da2899SCharles.Forsyth p->pipedir = malloc(sizeof(pipedir));
80*37da2899SCharles.Forsyth if (p->pipedir == 0)
81*37da2899SCharles.Forsyth error(Enomem);
82*37da2899SCharles.Forsyth memmove(p->pipedir, pipedir, sizeof(pipedir));
83*37da2899SCharles.Forsyth kstrdup(&p->user, up->env->user);
84*37da2899SCharles.Forsyth p->ref = 1;
85*37da2899SCharles.Forsyth
86*37da2899SCharles.Forsyth p->q[0] = qopen(pipealloc.pipeqsize, 0, 0, 0);
87*37da2899SCharles.Forsyth if(p->q[0] == 0)
88*37da2899SCharles.Forsyth error(Enomem);
89*37da2899SCharles.Forsyth p->q[1] = qopen(pipealloc.pipeqsize, 0, 0, 0);
90*37da2899SCharles.Forsyth if(p->q[1] == 0)
91*37da2899SCharles.Forsyth error(Enomem);
92*37da2899SCharles.Forsyth poperror();
93*37da2899SCharles.Forsyth
94*37da2899SCharles.Forsyth lock(&pipealloc.l);
95*37da2899SCharles.Forsyth p->path = ++pipealloc.path;
96*37da2899SCharles.Forsyth unlock(&pipealloc.l);
97*37da2899SCharles.Forsyth
98*37da2899SCharles.Forsyth c->qid.path = NETQID(2*p->path, Qdir);
99*37da2899SCharles.Forsyth c->qid.vers = 0;
100*37da2899SCharles.Forsyth c->qid.type = QTDIR;
101*37da2899SCharles.Forsyth c->aux = p;
102*37da2899SCharles.Forsyth c->dev = 0;
103*37da2899SCharles.Forsyth return c;
104*37da2899SCharles.Forsyth }
105*37da2899SCharles.Forsyth
106*37da2899SCharles.Forsyth static int
pipegen(Chan * c,char * name,Dirtab * tab,int ntab,int i,Dir * dp)107*37da2899SCharles.Forsyth pipegen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
108*37da2899SCharles.Forsyth {
109*37da2899SCharles.Forsyth int id, len;
110*37da2899SCharles.Forsyth Qid qid;
111*37da2899SCharles.Forsyth Pipe *p;
112*37da2899SCharles.Forsyth
113*37da2899SCharles.Forsyth USED(name);
114*37da2899SCharles.Forsyth if(i == DEVDOTDOT){
115*37da2899SCharles.Forsyth devdir(c, c->qid, "#|", 0, eve, 0555, dp);
116*37da2899SCharles.Forsyth return 1;
117*37da2899SCharles.Forsyth }
118*37da2899SCharles.Forsyth i++; /* skip . */
119*37da2899SCharles.Forsyth if(tab==0 || i>=ntab)
120*37da2899SCharles.Forsyth return -1;
121*37da2899SCharles.Forsyth tab += i;
122*37da2899SCharles.Forsyth p = c->aux;
123*37da2899SCharles.Forsyth switch(NETTYPE(tab->qid.path)){
124*37da2899SCharles.Forsyth case Qdata0:
125*37da2899SCharles.Forsyth len = qlen(p->q[0]);
126*37da2899SCharles.Forsyth break;
127*37da2899SCharles.Forsyth case Qdata1:
128*37da2899SCharles.Forsyth len = qlen(p->q[1]);
129*37da2899SCharles.Forsyth break;
130*37da2899SCharles.Forsyth default:
131*37da2899SCharles.Forsyth len = tab->length;
132*37da2899SCharles.Forsyth break;
133*37da2899SCharles.Forsyth }
134*37da2899SCharles.Forsyth id = NETID(c->qid.path);
135*37da2899SCharles.Forsyth qid.path = NETQID(id, tab->qid.path);
136*37da2899SCharles.Forsyth qid.vers = 0;
137*37da2899SCharles.Forsyth qid.type = QTFILE;
138*37da2899SCharles.Forsyth devdir(c, qid, tab->name, len, eve, tab->perm, dp);
139*37da2899SCharles.Forsyth return 1;
140*37da2899SCharles.Forsyth }
141*37da2899SCharles.Forsyth
142*37da2899SCharles.Forsyth static Walkqid*
pipewalk(Chan * c,Chan * nc,char ** name,int nname)143*37da2899SCharles.Forsyth pipewalk(Chan *c, Chan *nc, char **name, int nname)
144*37da2899SCharles.Forsyth {
145*37da2899SCharles.Forsyth Walkqid *wq;
146*37da2899SCharles.Forsyth Pipe *p;
147*37da2899SCharles.Forsyth
148*37da2899SCharles.Forsyth p = c->aux;
149*37da2899SCharles.Forsyth wq = devwalk(c, nc, name, nname, p->pipedir, nelem(pipedir), pipegen);
150*37da2899SCharles.Forsyth if(wq != nil && wq->clone != nil && wq->clone != c){
151*37da2899SCharles.Forsyth qlock(&p->l);
152*37da2899SCharles.Forsyth p->ref++;
153*37da2899SCharles.Forsyth if(c->flag & COPEN){
154*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
155*37da2899SCharles.Forsyth case Qdata0:
156*37da2899SCharles.Forsyth p->qref[0]++;
157*37da2899SCharles.Forsyth break;
158*37da2899SCharles.Forsyth case Qdata1:
159*37da2899SCharles.Forsyth p->qref[1]++;
160*37da2899SCharles.Forsyth break;
161*37da2899SCharles.Forsyth }
162*37da2899SCharles.Forsyth }
163*37da2899SCharles.Forsyth qunlock(&p->l);
164*37da2899SCharles.Forsyth }
165*37da2899SCharles.Forsyth return wq;
166*37da2899SCharles.Forsyth }
167*37da2899SCharles.Forsyth
168*37da2899SCharles.Forsyth static int
pipestat(Chan * c,uchar * db,int n)169*37da2899SCharles.Forsyth pipestat(Chan *c, uchar *db, int n)
170*37da2899SCharles.Forsyth {
171*37da2899SCharles.Forsyth Pipe *p;
172*37da2899SCharles.Forsyth Dir dir;
173*37da2899SCharles.Forsyth Dirtab *tab;
174*37da2899SCharles.Forsyth
175*37da2899SCharles.Forsyth p = c->aux;
176*37da2899SCharles.Forsyth tab = p->pipedir;
177*37da2899SCharles.Forsyth
178*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
179*37da2899SCharles.Forsyth case Qdir:
180*37da2899SCharles.Forsyth devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir);
181*37da2899SCharles.Forsyth break;
182*37da2899SCharles.Forsyth case Qdata0:
183*37da2899SCharles.Forsyth devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, tab[1].perm, &dir);
184*37da2899SCharles.Forsyth break;
185*37da2899SCharles.Forsyth case Qdata1:
186*37da2899SCharles.Forsyth devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, tab[2].perm, &dir);
187*37da2899SCharles.Forsyth break;
188*37da2899SCharles.Forsyth default:
189*37da2899SCharles.Forsyth panic("pipestat");
190*37da2899SCharles.Forsyth }
191*37da2899SCharles.Forsyth n = convD2M(&dir, db, n);
192*37da2899SCharles.Forsyth if(n < BIT16SZ)
193*37da2899SCharles.Forsyth error(Eshortstat);
194*37da2899SCharles.Forsyth return n;
195*37da2899SCharles.Forsyth }
196*37da2899SCharles.Forsyth
197*37da2899SCharles.Forsyth /*
198*37da2899SCharles.Forsyth * if the stream doesn't exist, create it
199*37da2899SCharles.Forsyth */
200*37da2899SCharles.Forsyth static Chan*
pipeopen(Chan * c,int omode)201*37da2899SCharles.Forsyth pipeopen(Chan *c, int omode)
202*37da2899SCharles.Forsyth {
203*37da2899SCharles.Forsyth Pipe *p;
204*37da2899SCharles.Forsyth
205*37da2899SCharles.Forsyth if(c->qid.type & QTDIR){
206*37da2899SCharles.Forsyth if(omode != OREAD)
207*37da2899SCharles.Forsyth error(Ebadarg);
208*37da2899SCharles.Forsyth c->mode = omode;
209*37da2899SCharles.Forsyth c->flag |= COPEN;
210*37da2899SCharles.Forsyth c->offset = 0;
211*37da2899SCharles.Forsyth return c;
212*37da2899SCharles.Forsyth }
213*37da2899SCharles.Forsyth
214*37da2899SCharles.Forsyth openmode(omode); /* check it */
215*37da2899SCharles.Forsyth
216*37da2899SCharles.Forsyth p = c->aux;
217*37da2899SCharles.Forsyth qlock(&p->l);
218*37da2899SCharles.Forsyth if(waserror()){
219*37da2899SCharles.Forsyth qunlock(&p->l);
220*37da2899SCharles.Forsyth nexterror();
221*37da2899SCharles.Forsyth }
222*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
223*37da2899SCharles.Forsyth case Qdata0:
224*37da2899SCharles.Forsyth devpermcheck(p->user, p->pipedir[1].perm, omode);
225*37da2899SCharles.Forsyth p->qref[0]++;
226*37da2899SCharles.Forsyth break;
227*37da2899SCharles.Forsyth case Qdata1:
228*37da2899SCharles.Forsyth devpermcheck(p->user, p->pipedir[2].perm, omode);
229*37da2899SCharles.Forsyth p->qref[1]++;
230*37da2899SCharles.Forsyth break;
231*37da2899SCharles.Forsyth }
232*37da2899SCharles.Forsyth poperror();
233*37da2899SCharles.Forsyth qunlock(&p->l);
234*37da2899SCharles.Forsyth
235*37da2899SCharles.Forsyth c->mode = openmode(omode);
236*37da2899SCharles.Forsyth c->flag |= COPEN;
237*37da2899SCharles.Forsyth c->offset = 0;
238*37da2899SCharles.Forsyth c->iounit = qiomaxatomic;
239*37da2899SCharles.Forsyth return c;
240*37da2899SCharles.Forsyth }
241*37da2899SCharles.Forsyth
242*37da2899SCharles.Forsyth static void
pipeclose(Chan * c)243*37da2899SCharles.Forsyth pipeclose(Chan *c)
244*37da2899SCharles.Forsyth {
245*37da2899SCharles.Forsyth Pipe *p;
246*37da2899SCharles.Forsyth
247*37da2899SCharles.Forsyth p = c->aux;
248*37da2899SCharles.Forsyth qlock(&p->l);
249*37da2899SCharles.Forsyth
250*37da2899SCharles.Forsyth if(c->flag & COPEN){
251*37da2899SCharles.Forsyth /*
252*37da2899SCharles.Forsyth * closing either side hangs up the stream
253*37da2899SCharles.Forsyth */
254*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
255*37da2899SCharles.Forsyth case Qdata0:
256*37da2899SCharles.Forsyth p->qref[0]--;
257*37da2899SCharles.Forsyth if(p->qref[0] == 0){
258*37da2899SCharles.Forsyth qhangup(p->q[1], 0);
259*37da2899SCharles.Forsyth qclose(p->q[0]);
260*37da2899SCharles.Forsyth }
261*37da2899SCharles.Forsyth break;
262*37da2899SCharles.Forsyth case Qdata1:
263*37da2899SCharles.Forsyth p->qref[1]--;
264*37da2899SCharles.Forsyth if(p->qref[1] == 0){
265*37da2899SCharles.Forsyth qhangup(p->q[0], 0);
266*37da2899SCharles.Forsyth qclose(p->q[1]);
267*37da2899SCharles.Forsyth }
268*37da2899SCharles.Forsyth break;
269*37da2899SCharles.Forsyth }
270*37da2899SCharles.Forsyth }
271*37da2899SCharles.Forsyth
272*37da2899SCharles.Forsyth
273*37da2899SCharles.Forsyth /*
274*37da2899SCharles.Forsyth * if both sides are closed, they are reusable
275*37da2899SCharles.Forsyth */
276*37da2899SCharles.Forsyth if(p->qref[0] == 0 && p->qref[1] == 0){
277*37da2899SCharles.Forsyth qreopen(p->q[0]);
278*37da2899SCharles.Forsyth qreopen(p->q[1]);
279*37da2899SCharles.Forsyth }
280*37da2899SCharles.Forsyth
281*37da2899SCharles.Forsyth /*
282*37da2899SCharles.Forsyth * free the structure on last close
283*37da2899SCharles.Forsyth */
284*37da2899SCharles.Forsyth p->ref--;
285*37da2899SCharles.Forsyth if(p->ref == 0){
286*37da2899SCharles.Forsyth qunlock(&p->l);
287*37da2899SCharles.Forsyth freepipe(p);
288*37da2899SCharles.Forsyth } else
289*37da2899SCharles.Forsyth qunlock(&p->l);
290*37da2899SCharles.Forsyth }
291*37da2899SCharles.Forsyth
292*37da2899SCharles.Forsyth static long
piperead(Chan * c,void * va,long n,vlong junk)293*37da2899SCharles.Forsyth piperead(Chan *c, void *va, long n, vlong junk)
294*37da2899SCharles.Forsyth {
295*37da2899SCharles.Forsyth Pipe *p;
296*37da2899SCharles.Forsyth
297*37da2899SCharles.Forsyth p = c->aux;
298*37da2899SCharles.Forsyth
299*37da2899SCharles.Forsyth USED(junk);
300*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
301*37da2899SCharles.Forsyth case Qdir:
302*37da2899SCharles.Forsyth return devdirread(c, va, n, p->pipedir, nelem(pipedir), pipegen);
303*37da2899SCharles.Forsyth case Qdata0:
304*37da2899SCharles.Forsyth return qread(p->q[0], va, n);
305*37da2899SCharles.Forsyth case Qdata1:
306*37da2899SCharles.Forsyth return qread(p->q[1], va, n);
307*37da2899SCharles.Forsyth default:
308*37da2899SCharles.Forsyth panic("piperead");
309*37da2899SCharles.Forsyth }
310*37da2899SCharles.Forsyth return -1; /* not reached */
311*37da2899SCharles.Forsyth }
312*37da2899SCharles.Forsyth
313*37da2899SCharles.Forsyth static Block*
pipebread(Chan * c,long n,ulong offset)314*37da2899SCharles.Forsyth pipebread(Chan *c, long n, ulong offset)
315*37da2899SCharles.Forsyth {
316*37da2899SCharles.Forsyth Pipe *p;
317*37da2899SCharles.Forsyth
318*37da2899SCharles.Forsyth p = c->aux;
319*37da2899SCharles.Forsyth
320*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
321*37da2899SCharles.Forsyth case Qdata0:
322*37da2899SCharles.Forsyth return qbread(p->q[0], n);
323*37da2899SCharles.Forsyth case Qdata1:
324*37da2899SCharles.Forsyth return qbread(p->q[1], n);
325*37da2899SCharles.Forsyth }
326*37da2899SCharles.Forsyth
327*37da2899SCharles.Forsyth return devbread(c, n, offset);
328*37da2899SCharles.Forsyth }
329*37da2899SCharles.Forsyth
330*37da2899SCharles.Forsyth /*
331*37da2899SCharles.Forsyth * a write to a closed pipe causes an exception to be sent to
332*37da2899SCharles.Forsyth * the prog.
333*37da2899SCharles.Forsyth */
334*37da2899SCharles.Forsyth static long
pipewrite(Chan * c,void * va,long n,vlong junk)335*37da2899SCharles.Forsyth pipewrite(Chan *c, void *va, long n, vlong junk)
336*37da2899SCharles.Forsyth {
337*37da2899SCharles.Forsyth Pipe *p;
338*37da2899SCharles.Forsyth Prog *r;
339*37da2899SCharles.Forsyth
340*37da2899SCharles.Forsyth USED(junk);
341*37da2899SCharles.Forsyth if(waserror()) {
342*37da2899SCharles.Forsyth /* avoid exceptions when pipe is a mounted queue */
343*37da2899SCharles.Forsyth if((c->flag & CMSG) == 0) {
344*37da2899SCharles.Forsyth r = up->iprog;
345*37da2899SCharles.Forsyth if(r != nil && r->kill == nil)
346*37da2899SCharles.Forsyth r->kill = "write on closed pipe";
347*37da2899SCharles.Forsyth }
348*37da2899SCharles.Forsyth nexterror();
349*37da2899SCharles.Forsyth }
350*37da2899SCharles.Forsyth
351*37da2899SCharles.Forsyth p = c->aux;
352*37da2899SCharles.Forsyth
353*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
354*37da2899SCharles.Forsyth case Qdata0:
355*37da2899SCharles.Forsyth n = qwrite(p->q[1], va, n);
356*37da2899SCharles.Forsyth break;
357*37da2899SCharles.Forsyth
358*37da2899SCharles.Forsyth case Qdata1:
359*37da2899SCharles.Forsyth n = qwrite(p->q[0], va, n);
360*37da2899SCharles.Forsyth break;
361*37da2899SCharles.Forsyth
362*37da2899SCharles.Forsyth default:
363*37da2899SCharles.Forsyth panic("pipewrite");
364*37da2899SCharles.Forsyth }
365*37da2899SCharles.Forsyth
366*37da2899SCharles.Forsyth poperror();
367*37da2899SCharles.Forsyth return n;
368*37da2899SCharles.Forsyth }
369*37da2899SCharles.Forsyth
370*37da2899SCharles.Forsyth static long
pipebwrite(Chan * c,Block * bp,ulong junk)371*37da2899SCharles.Forsyth pipebwrite(Chan *c, Block *bp, ulong junk)
372*37da2899SCharles.Forsyth {
373*37da2899SCharles.Forsyth long n;
374*37da2899SCharles.Forsyth Pipe *p;
375*37da2899SCharles.Forsyth Prog *r;
376*37da2899SCharles.Forsyth
377*37da2899SCharles.Forsyth USED(junk);
378*37da2899SCharles.Forsyth if(waserror()) {
379*37da2899SCharles.Forsyth /* avoid exceptions when pipe is a mounted queue */
380*37da2899SCharles.Forsyth if((c->flag & CMSG) == 0) {
381*37da2899SCharles.Forsyth r = up->iprog;
382*37da2899SCharles.Forsyth if(r != nil && r->kill == nil)
383*37da2899SCharles.Forsyth r->kill = "write on closed pipe";
384*37da2899SCharles.Forsyth }
385*37da2899SCharles.Forsyth nexterror();
386*37da2899SCharles.Forsyth }
387*37da2899SCharles.Forsyth
388*37da2899SCharles.Forsyth p = c->aux;
389*37da2899SCharles.Forsyth switch(NETTYPE(c->qid.path)){
390*37da2899SCharles.Forsyth case Qdata0:
391*37da2899SCharles.Forsyth n = qbwrite(p->q[1], bp);
392*37da2899SCharles.Forsyth break;
393*37da2899SCharles.Forsyth
394*37da2899SCharles.Forsyth case Qdata1:
395*37da2899SCharles.Forsyth n = qbwrite(p->q[0], bp);
396*37da2899SCharles.Forsyth break;
397*37da2899SCharles.Forsyth
398*37da2899SCharles.Forsyth default:
399*37da2899SCharles.Forsyth n = 0;
400*37da2899SCharles.Forsyth panic("pipebwrite");
401*37da2899SCharles.Forsyth }
402*37da2899SCharles.Forsyth
403*37da2899SCharles.Forsyth poperror();
404*37da2899SCharles.Forsyth return n;
405*37da2899SCharles.Forsyth }
406*37da2899SCharles.Forsyth
407*37da2899SCharles.Forsyth static int
pipewstat(Chan * c,uchar * dp,int n)408*37da2899SCharles.Forsyth pipewstat(Chan *c, uchar *dp, int n)
409*37da2899SCharles.Forsyth {
410*37da2899SCharles.Forsyth Dir *d;
411*37da2899SCharles.Forsyth Pipe *p;
412*37da2899SCharles.Forsyth int d1;
413*37da2899SCharles.Forsyth
414*37da2899SCharles.Forsyth if (c->qid.type&QTDIR)
415*37da2899SCharles.Forsyth error(Eperm);
416*37da2899SCharles.Forsyth p = c->aux;
417*37da2899SCharles.Forsyth if(strcmp(up->env->user, p->user) != 0)
418*37da2899SCharles.Forsyth error(Eperm);
419*37da2899SCharles.Forsyth d = smalloc(sizeof(*d)+n);
420*37da2899SCharles.Forsyth if(waserror()){
421*37da2899SCharles.Forsyth free(d);
422*37da2899SCharles.Forsyth nexterror();
423*37da2899SCharles.Forsyth }
424*37da2899SCharles.Forsyth n = convM2D(dp, n, d, (char*)&d[1]);
425*37da2899SCharles.Forsyth if(n == 0)
426*37da2899SCharles.Forsyth error(Eshortstat);
427*37da2899SCharles.Forsyth d1 = NETTYPE(c->qid.path) == Qdata1;
428*37da2899SCharles.Forsyth if(!emptystr(d->name)){
429*37da2899SCharles.Forsyth validwstatname(d->name);
430*37da2899SCharles.Forsyth if(strlen(d->name) >= KNAMELEN)
431*37da2899SCharles.Forsyth error(Efilename);
432*37da2899SCharles.Forsyth if(strcmp(p->pipedir[1+!d1].name, d->name) == 0)
433*37da2899SCharles.Forsyth error(Eexist);
434*37da2899SCharles.Forsyth kstrcpy(p->pipedir[1+d1].name, d->name, KNAMELEN);
435*37da2899SCharles.Forsyth }
436*37da2899SCharles.Forsyth if(d->mode != ~0UL)
437*37da2899SCharles.Forsyth p->pipedir[d1 + 1].perm = d->mode & 0777;
438*37da2899SCharles.Forsyth poperror();
439*37da2899SCharles.Forsyth free(d);
440*37da2899SCharles.Forsyth return n;
441*37da2899SCharles.Forsyth }
442*37da2899SCharles.Forsyth
443*37da2899SCharles.Forsyth Dev pipedevtab = {
444*37da2899SCharles.Forsyth '|',
445*37da2899SCharles.Forsyth "pipe",
446*37da2899SCharles.Forsyth
447*37da2899SCharles.Forsyth pipeinit,
448*37da2899SCharles.Forsyth pipeattach,
449*37da2899SCharles.Forsyth pipewalk,
450*37da2899SCharles.Forsyth pipestat,
451*37da2899SCharles.Forsyth pipeopen,
452*37da2899SCharles.Forsyth devcreate,
453*37da2899SCharles.Forsyth pipeclose,
454*37da2899SCharles.Forsyth piperead,
455*37da2899SCharles.Forsyth pipebread,
456*37da2899SCharles.Forsyth pipewrite,
457*37da2899SCharles.Forsyth pipebwrite,
458*37da2899SCharles.Forsyth devremove,
459*37da2899SCharles.Forsyth pipewstat,
460*37da2899SCharles.Forsyth };
461