|
|
1.1 root 1: /*
2: * Copyright (c) 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)fifo_vnops.c 7.4 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "time.h"
25: #include "namei.h"
26: #include "vnode.h"
27: #include "socket.h"
28: #include "socketvar.h"
29: #include "stat.h"
30: #include "ioctl.h"
31: #include "file.h"
32: #include "errno.h"
33: #include "malloc.h"
34:
35: /*
36: * This structure is associated with the FIFO vnode and stores
37: * the state associated with the FIFO.
38: */
39: struct fifoinfo {
40: struct socket *fi_readsock;
41: struct socket *fi_writesock;
42: long fi_readers;
43: long fi_writers;
44: };
45:
46: int fifo_lookup(),
47: fifo_open(),
48: fifo_read(),
49: fifo_write(),
50: fifo_strategy(),
51: fifo_bmap(),
52: fifo_ioctl(),
53: fifo_select(),
54: fifo_lock(),
55: fifo_unlock(),
56: fifo_close(),
57: fifo_print(),
58: fifo_ebadf(),
59: fifo_badop(),
60: fifo_nullop();
61:
62: struct vnodeops fifo_vnodeops = {
63: fifo_lookup, /* lookup */
64: fifo_badop, /* create */
65: fifo_badop, /* mknod */
66: fifo_open, /* open */
67: fifo_close, /* close */
68: fifo_ebadf, /* access */
69: fifo_ebadf, /* getattr */
70: fifo_ebadf, /* setattr */
71: fifo_read, /* read */
72: fifo_write, /* write */
73: fifo_ioctl, /* ioctl */
74: fifo_select, /* select */
75: fifo_badop, /* mmap */
76: fifo_nullop, /* fsync */
77: fifo_badop, /* seek */
78: fifo_badop, /* remove */
79: fifo_badop, /* link */
80: fifo_badop, /* rename */
81: fifo_badop, /* mkdir */
82: fifo_badop, /* rmdir */
83: fifo_badop, /* symlink */
84: fifo_badop, /* readdir */
85: fifo_badop, /* readlink */
86: fifo_badop, /* abortop */
87: fifo_nullop, /* inactive */
88: fifo_nullop, /* reclaim */
89: fifo_lock, /* lock */
90: fifo_unlock, /* unlock */
91: fifo_bmap, /* bmap */
92: fifo_badop, /* strategy */
93: fifo_print, /* print */
94: fifo_nullop, /* islocked */
95: };
96:
97: /*
98: * Trivial lookup routine that always fails.
99: */
100: fifo_lookup(vp, ndp)
101: struct vnode *vp;
102: struct nameidata *ndp;
103: {
104:
105: ndp->ni_dvp = vp;
106: ndp->ni_vp = NULL;
107: return (ENOTDIR);
108: }
109:
110: /*
111: * Open called to set up a new instance of a fifo or
112: * to find an active instance of a fifo.
113: */
114: /* ARGSUSED */
115: fifo_open(vp, mode, cred)
116: register struct vnode *vp;
117: int mode;
118: struct ucred *cred;
119: {
120: register struct fifoinfo *fip;
121: struct socket *rso, *wso;
122: int error;
123: static char openstr[] = "fifo";
124:
125: if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
126: return (EINVAL);
127: if ((fip = vp->v_fifoinfo) == NULL) {
128: MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
129: vp->v_fifoinfo = fip;
130: if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
131: free(fip, M_VNODE);
132: vp->v_fifoinfo = NULL;
133: return (error);
134: }
135: fip->fi_readsock = rso;
136: if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
137: (void)soclose(rso);
138: free(fip, M_VNODE);
139: vp->v_fifoinfo = NULL;
140: return (error);
141: }
142: fip->fi_writesock = wso;
143: if (error = unp_connect2(wso, rso)) {
144: (void)soclose(wso);
145: (void)soclose(rso);
146: free(fip, M_VNODE);
147: vp->v_fifoinfo = NULL;
148: return (error);
149: }
150: wso->so_state |= SS_CANTRCVMORE;
151: rso->so_state |= SS_CANTSENDMORE;
152: }
153: error = 0;
154: if (mode & FREAD) {
155: fip->fi_readers++;
156: if (fip->fi_readers == 1) {
157: fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
158: if (fip->fi_writers > 0)
159: wakeup((caddr_t)&fip->fi_writers);
160: }
161: if (mode & O_NONBLOCK)
162: return (0);
163: while (fip->fi_writers == 0)
164: if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
165: openstr, 0))
166: break;
167: } else {
168: fip->fi_writers++;
169: if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
170: error = ENXIO;
171: } else {
172: if (fip->fi_writers == 1) {
173: fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
174: if (fip->fi_readers > 0)
175: wakeup((caddr_t)&fip->fi_readers);
176: }
177: while (fip->fi_readers == 0)
178: if (error = tsleep((caddr_t)&fip->fi_writers,
179: PSOCK, openstr, 0))
180: break;
181: }
182: }
183: if (error)
184: fifo_close(vp, mode, cred);
185: return (error);
186: }
187:
188: /*
189: * Vnode op for read
190: */
191: /* ARGSUSED */
192: fifo_read(vp, uio, ioflag, cred)
193: struct vnode *vp;
194: register struct uio *uio;
195: int ioflag;
196: struct ucred *cred;
197: {
198: register struct socket *rso = vp->v_fifoinfo->fi_readsock;
199: int error, startresid;
200:
201: if (uio->uio_rw != UIO_READ)
202: panic("fifo_read mode");
203: if (uio->uio_resid == 0)
204: return (0);
205: if (ioflag & IO_NDELAY)
206: rso->so_state |= SS_NBIO;
207: startresid = uio->uio_resid;
208: VOP_UNLOCK(vp);
209: error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
210: (struct mbuf **)0, (struct mbuf **)0);
211: VOP_LOCK(vp);
212: /*
213: * Clear EOF indication after first such return.
214: */
215: if (uio->uio_resid == startresid)
216: rso->so_state &= ~SS_CANTRCVMORE;
217: if (ioflag & IO_NDELAY)
218: rso->so_state &= ~SS_NBIO;
219: return (error);
220: }
221:
222: /*
223: * Vnode op for write
224: */
225: /* ARGSUSED */
226: fifo_write(vp, uio, ioflag, cred)
227: struct vnode *vp;
228: register struct uio *uio;
229: int ioflag;
230: struct ucred *cred;
231: {
232: struct socket *wso = vp->v_fifoinfo->fi_writesock;
233: int error;
234:
235: if (uio->uio_rw != UIO_WRITE)
236: panic("fifo_write mode");
237: if (ioflag & IO_NDELAY)
238: wso->so_state |= SS_NBIO;
239: VOP_UNLOCK(vp);
240: error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
241: VOP_LOCK(vp);
242: if (ioflag & IO_NDELAY)
243: wso->so_state &= ~SS_NBIO;
244: return (error);
245: }
246:
247: /*
248: * Device ioctl operation.
249: */
250: /* ARGSUSED */
251: fifo_ioctl(vp, com, data, fflag, cred)
252: struct vnode *vp;
253: int com;
254: caddr_t data;
255: int fflag;
256: struct ucred *cred;
257: {
258: struct file filetmp;
259: int error;
260:
261: if (com == FIONBIO)
262: return (0);
263: if (fflag & FREAD)
264: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
265: else
266: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
267: return (soo_ioctl(&filetmp, com, data));
268: }
269:
270: /* ARGSUSED */
271: fifo_select(vp, which, fflag, cred)
272: struct vnode *vp;
273: int which, fflag;
274: struct ucred *cred;
275: {
276: struct file filetmp;
277: int error;
278:
279: if (fflag & FREAD)
280: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
281: else
282: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
283: return (soo_select(&filetmp, which));
284: }
285:
286: /*
287: * This is a noop, simply returning what one has been given.
288: */
289: fifo_bmap(vp, bn, vpp, bnp)
290: struct vnode *vp;
291: daddr_t bn;
292: struct vnode **vpp;
293: daddr_t *bnp;
294: {
295:
296: if (vpp != NULL)
297: *vpp = vp;
298: if (bnp != NULL)
299: *bnp = bn;
300: return (0);
301: }
302:
303: /*
304: * At the moment we do not do any locking.
305: */
306: /* ARGSUSED */
307: fifo_lock(vp)
308: struct vnode *vp;
309: {
310:
311: return (0);
312: }
313:
314: /* ARGSUSED */
315: fifo_unlock(vp)
316: struct vnode *vp;
317: {
318:
319: return (0);
320: }
321:
322: /*
323: * Device close routine
324: */
325: /* ARGSUSED */
326: fifo_close(vp, fflag, cred)
327: register struct vnode *vp;
328: int fflag;
329: struct ucred *cred;
330: {
331: register struct fifoinfo *fip = vp->v_fifoinfo;
332: int error1, error2;
333:
334: if (fflag & FWRITE) {
335: fip->fi_writers--;
336: if (fip->fi_writers == 0)
337: socantrcvmore(fip->fi_readsock);
338: } else {
339: fip->fi_readers--;
340: if (fip->fi_readers == 0)
341: socantsendmore(fip->fi_writesock);
342: }
343: if (vp->v_usecount > 1)
344: return (0);
345: error1 = soclose(fip->fi_readsock);
346: error2 = soclose(fip->fi_writesock);
347: FREE(fip, M_VNODE);
348: vp->v_fifoinfo = NULL;
349: if (error1)
350: return (error1);
351: return (error2);
352: }
353:
354: /*
355: * Print out the contents of a fifo vnode.
356: */
357: fifo_print(vp)
358: struct vnode *vp;
359: {
360:
361: printf("tag VT_NON");
362: fifo_printinfo(vp);
363: printf("\n");
364: }
365:
366: /*
367: * Print out internal contents of a fifo vnode.
368: */
369: fifo_printinfo(vp)
370: struct vnode *vp;
371: {
372: register struct fifoinfo *fip = vp->v_fifoinfo;
373:
374: printf(", fifo with %d readers and %d writers",
375: fip->fi_readers, fip->fi_writers);
376: }
377:
378: /*
379: * Fifo failed operation
380: */
381: fifo_ebadf()
382: {
383:
384: return (EBADF);
385: }
386:
387: /*
388: * Fifo bad operation
389: */
390: fifo_badop()
391: {
392:
393: panic("fifo_badop called");
394: /* NOTREACHED */
395: }
396:
397: /*
398: * Fifo null operation
399: */
400: fifo_nullop()
401: {
402:
403: return (0);
404: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.