1/*
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)fifo_vnops.c 8.2 (Berkeley) 1/4/94
34 * $Id: fifo_vnops.c,v 1.12 1995/11/09 08:15:27 bde Exp $
35 */
36
37#include <sys/param.h>
38#include <sys/kernel.h>
39#include <sys/proc.h>
40#include <sys/time.h>
41#include <sys/namei.h>
42#include <sys/vnode.h>
43#include <sys/socket.h>
44#include <sys/socketvar.h>
45#include <sys/stat.h>
46#include <sys/systm.h>
47#include <sys/ioctl.h>
48#include <sys/file.h>
49#include <sys/errno.h>
50#include <sys/malloc.h>
51#include <sys/un.h>
52#include <miscfs/fifofs/fifo.h>
53
54/*
55 * This structure is associated with the FIFO vnode and stores
56 * the state associated with the FIFO.
57 */
58struct fifoinfo {
59 struct socket *fi_readsock;
60 struct socket *fi_writesock;
61 long fi_readers;
62 long fi_writers;
63};
64
65vop_t **fifo_vnodeop_p;
66static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
67 { &vop_default_desc, (vop_t *)vn_default_error },
68 { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
69 { &vop_create_desc, (vop_t *)fifo_create }, /* create */
70 { &vop_mknod_desc, (vop_t *)fifo_mknod }, /* mknod */
71 { &vop_open_desc, (vop_t *)fifo_open }, /* open */
72 { &vop_close_desc, (vop_t *)fifo_close }, /* close */
73 { &vop_access_desc, (vop_t *)fifo_access }, /* access */
74 { &vop_getattr_desc, (vop_t *)fifo_getattr }, /* getattr */
75 { &vop_setattr_desc, (vop_t *)fifo_setattr }, /* setattr */
76 { &vop_read_desc, (vop_t *)fifo_read }, /* read */
77 { &vop_write_desc, (vop_t *)fifo_write }, /* write */
78 { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
79 { &vop_select_desc, (vop_t *)fifo_select }, /* select */
80 { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
81 { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
82 { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
83 { &vop_remove_desc, (vop_t *)fifo_remove }, /* remove */
84 { &vop_link_desc, (vop_t *)fifo_link }, /* link */
85 { &vop_rename_desc, (vop_t *)fifo_rename }, /* rename */
86 { &vop_mkdir_desc, (vop_t *)fifo_mkdir }, /* mkdir */
87 { &vop_rmdir_desc, (vop_t *)fifo_rmdir }, /* rmdir */
88 { &vop_symlink_desc, (vop_t *)fifo_symlink }, /* symlink */
89 { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
90 { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
91 { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
92 { &vop_inactive_desc, (vop_t *)fifo_inactive }, /* inactive */
93 { &vop_reclaim_desc, (vop_t *)fifo_reclaim }, /* reclaim */
94 { &vop_lock_desc, (vop_t *)fifo_lock }, /* lock */
95 { &vop_unlock_desc, (vop_t *)fifo_unlock }, /* unlock */
96 { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
97 { &vop_strategy_desc, (vop_t *)fifo_strategy }, /* strategy */
98 { &vop_print_desc, (vop_t *)fifo_print }, /* print */
99 { &vop_islocked_desc, (vop_t *)fifo_islocked }, /* islocked */
100 { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
101 { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
102 { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
103 { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
104 { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
105 { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
106 { &vop_update_desc, (vop_t *)fifo_update }, /* update */
107 { &vop_bwrite_desc, (vop_t *)fifo_bwrite }, /* bwrite */
108 { NULL, NULL }
109};
110static struct vnodeopv_desc fifo_vnodeop_opv_desc =
111 { &fifo_vnodeop_p, fifo_vnodeop_entries };
112
113VNODEOP_SET(fifo_vnodeop_opv_desc);
114
115/*
116 * Trivial lookup routine that always fails.
117 */
118/* ARGSUSED */
119int
120fifo_lookup(ap)
121 struct vop_lookup_args /* {
122 struct vnode * a_dvp;
123 struct vnode ** a_vpp;
124 struct componentname * a_cnp;
125 } */ *ap;
126{
127
128 *ap->a_vpp = NULL;
129 return (ENOTDIR);
130}
131
132/*
133 * Open called to set up a new instance of a fifo or
134 * to find an active instance of a fifo.
135 */
136/* ARGSUSED */
137int
138fifo_open(ap)
139 struct vop_open_args /* {
140 struct vnode *a_vp;
141 int a_mode;
142 struct ucred *a_cred;
143 struct proc *a_p;
144 } */ *ap;
145{
146 register struct vnode *vp = ap->a_vp;
147 register struct fifoinfo *fip;
148 struct socket *rso, *wso;
149 int error;
150 static char openstr[] = "fifo";
151
152 if ((fip = vp->v_fifoinfo) == NULL) {
153 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
154 vp->v_fifoinfo = fip;
155 error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
156 if (error) {
157 free(fip, M_VNODE);
158 vp->v_fifoinfo = NULL;
159 return (error);
160 }
161 fip->fi_readsock = rso;
162 error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
163 if (error) {
164 (void)soclose(rso);
165 free(fip, M_VNODE);
166 vp->v_fifoinfo = NULL;
167 return (error);
168 }
169 fip->fi_writesock = wso;
170 error = unp_connect2(wso, rso);
171 if (error) {
172 (void)soclose(wso);
173 (void)soclose(rso);
174 free(fip, M_VNODE);
175 vp->v_fifoinfo = NULL;
176 return (error);
177 }
178 fip->fi_readers = fip->fi_writers = 0;
179 wso->so_state |= SS_CANTRCVMORE;
180 rso->so_state |= SS_CANTSENDMORE;
181 }
182 error = 0;
183 if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
184 if (fip->fi_readers == 0) {
185 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
186 if (fip->fi_writers > 0)
187 wakeup((caddr_t)&fip->fi_writers);
188 }
189 if (fip->fi_writers == 0) {
190 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
191 if (fip->fi_readers > 0)
192 wakeup((caddr_t)&fip->fi_readers);
193 }
194 fip->fi_readers++;
195 fip->fi_writers++;
196 }
197 else if (ap->a_mode & FREAD) {
198 fip->fi_readers++;
199 if (fip->fi_readers == 1) {
200 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
201 if (fip->fi_writers > 0)
202 wakeup((caddr_t)&fip->fi_writers);
203 }
204 if (!(ap->a_mode & O_NONBLOCK))
205 while (fip->fi_writers == 0) {
206 VOP_UNLOCK(vp);
207 error = tsleep((caddr_t)&fip->fi_readers,
208 PCATCH | PSOCK, openstr, 0);
209 VOP_LOCK(vp);
210 if (error)
211 break;
212 }
213 }
214 else {
215 fip->fi_writers++;
216 if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) {
217 error = ENXIO;
218 } else {
219 if (fip->fi_writers == 1) {
220 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
221 if (fip->fi_readers > 0)
222 wakeup((caddr_t)&fip->fi_readers);
223 }
224 while (fip->fi_readers == 0) {
225 VOP_UNLOCK(vp);
226 error = tsleep((caddr_t)&fip->fi_writers,
227 PCATCH | PSOCK, openstr, 0);
228 VOP_LOCK(vp);
229 if (error)
230 break;
231 }
232 }
233 }
234 if (error)
235 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
236 return (error);
237}
238
239/*
240 * Vnode op for read
241 */
242/* ARGSUSED */
243int
244fifo_read(ap)
245 struct vop_read_args /* {
246 struct vnode *a_vp;
247 struct uio *a_uio;
248 int a_ioflag;
249 struct ucred *a_cred;
250 } */ *ap;
251{
252 register struct uio *uio = ap->a_uio;
253 register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
254 int error, startresid;
255
256#ifdef DIAGNOSTIC
257 if (uio->uio_rw != UIO_READ)
258 panic("fifo_read mode");
259#endif
260 if (uio->uio_resid == 0)
261 return (0);
262 if (ap->a_ioflag & IO_NDELAY)
263 rso->so_state |= SS_NBIO;
264 startresid = uio->uio_resid;
265 VOP_UNLOCK(ap->a_vp);
266 error = soreceive(rso, (struct mbuf **)0, uio,
267 (struct mbuf **)0, (struct mbuf **)0, (int*)0);
268 VOP_LOCK(ap->a_vp);
269 /*
270 * Clear EOF indication after first such return.
271 */
272 if (uio->uio_resid == startresid)
273 rso->so_state &= ~SS_CANTRCVMORE;
274 if (ap->a_ioflag & IO_NDELAY)
275 rso->so_state &= ~SS_NBIO;
276 return (error);
277}
278
279/*
280 * Vnode op for write
281 */
282/* ARGSUSED */
283int
284fifo_write(ap)
285 struct vop_write_args /* {
286 struct vnode *a_vp;
287 struct uio *a_uio;
288 int a_ioflag;
289 struct ucred *a_cred;
290 } */ *ap;
291{
292 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
293 int error;
294
295#ifdef DIAGNOSTIC
296 if (ap->a_uio->uio_rw != UIO_WRITE)
297 panic("fifo_write mode");
298#endif
299 if (ap->a_ioflag & IO_NDELAY)
300 wso->so_state |= SS_NBIO;
301 VOP_UNLOCK(ap->a_vp);
302 error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0);
303 VOP_LOCK(ap->a_vp);
304 if (ap->a_ioflag & IO_NDELAY)
305 wso->so_state &= ~SS_NBIO;
306 return (error);
307}
308
309/*
310 * Device ioctl operation.
311 */
312/* ARGSUSED */
313int
314fifo_ioctl(ap)
315 struct vop_ioctl_args /* {
316 struct vnode *a_vp;
317 int a_command;
318 caddr_t a_data;
319 int a_fflag;
320 struct ucred *a_cred;
321 struct proc *a_p;
322 } */ *ap;
323{
324 struct file filetmp;
325
326 if (ap->a_command == FIONBIO)
327 return (0);
328 if (ap->a_fflag & FREAD)
329 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
330 else
331 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
332 return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p));
333}
334
335/* ARGSUSED */
336int
337fifo_select(ap)
338 struct vop_select_args /* {
339 struct vnode *a_vp;
340 int a_which;
341 int a_fflags;
342 struct ucred *a_cred;
343 struct proc *a_p;
344 } */ *ap;
345{
346 struct file filetmp;
347
348 if (ap->a_fflags & FREAD)
349 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
350 else
351 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
352 return (soo_select(&filetmp, ap->a_which, ap->a_p));
353}
354
355/*
356 * This is a noop, simply returning what one has been given.
357 */
358int
359fifo_bmap(ap)
360 struct vop_bmap_args /* {
361 struct vnode *a_vp;
362 daddr_t a_bn;
363 struct vnode **a_vpp;
364 daddr_t *a_bnp;
365 int *a_runp;
366 int *a_runb;
367 } */ *ap;
368{
369
370 if (ap->a_vpp != NULL)
371 *ap->a_vpp = ap->a_vp;
372 if (ap->a_bnp != NULL)
373 *ap->a_bnp = ap->a_bn;
374 if (ap->a_runp != NULL)
375 *ap->a_runp = 0;
376 if (ap->a_runb != NULL)
377 *ap->a_runb = 0;
378 return (0);
379}
380
381/*
382 * At the moment we do not do any locking.
383 */
384/* ARGSUSED */
385static int
386fifo_lock(ap)
387 struct vop_lock_args /* {
388 struct vnode *a_vp;
389 } */ *ap;
390{
391
392 return (0);
393}
394
395/* ARGSUSED */
396static int
397fifo_unlock(ap)
398 struct vop_unlock_args /* {
399 struct vnode *a_vp;
400 } */ *ap;
401{
402
403 return (0);
404}
405
406/*
407 * Device close routine
408 */
409/* ARGSUSED */
410int
411fifo_close(ap)
412 struct vop_close_args /* {
413 struct vnode *a_vp;
414 int a_fflag;
415 struct ucred *a_cred;
416 struct proc *a_p;
417 } */ *ap;
418{
419 register struct vnode *vp = ap->a_vp;
420 register struct fifoinfo *fip = vp->v_fifoinfo;
421 int error1, error2;
422
423 if (ap->a_fflag & FWRITE) {
424 fip->fi_writers--;
425 if (fip->fi_writers == 0)
426 socantrcvmore(fip->fi_readsock);
427 }
428 if (ap->a_fflag & FREAD) {
429 fip->fi_readers--;
430 if (fip->fi_readers == 0)
431 socantsendmore(fip->fi_writesock);
432 }
433 if (vp->v_usecount > 1)
434 return (0);
435 error1 = soclose(fip->fi_readsock);
436 error2 = soclose(fip->fi_writesock);
437 FREE(fip, M_VNODE);
438 vp->v_fifoinfo = NULL;
439 if (error1)
440 return (error1);
441 return (error2);
442}
443
444
445/*
446 * Print out internal contents of a fifo vnode.
447 */
448int
449fifo_printinfo(vp)
450 struct vnode *vp;
451{
452 register struct fifoinfo *fip = vp->v_fifoinfo;
453
454 printf(", fifo with %ld readers and %ld writers",
455 fip->fi_readers, fip->fi_writers);
456 return (0);
457}
458
459/*
460 * Print out the contents of a fifo vnode.
461 */
462static int
463fifo_print(ap)
464 struct vop_print_args /* {
465 struct vnode *a_vp;
466 } */ *ap;
467{
468
469 printf("tag VT_NON");
470 fifo_printinfo(ap->a_vp);
471 printf("\n");
472 return (0);
473}
474
475/*
476 * Return POSIX pathconf information applicable to fifo's.
477 */
478int
479fifo_pathconf(ap)
480 struct vop_pathconf_args /* {
481 struct vnode *a_vp;
482 int a_name;
483 int *a_retval;
484 } */ *ap;
485{
486
487 switch (ap->a_name) {
488 case _PC_LINK_MAX:
489 *ap->a_retval = LINK_MAX;
490 return (0);
491 case _PC_PIPE_BUF:
492 *ap->a_retval = PIPE_BUF;
493 return (0);
494 case _PC_CHOWN_RESTRICTED:
495 *ap->a_retval = 1;
496 return (0);
497 default:
498 return (EINVAL);
499 }
500 /* NOTREACHED */
501}
502
503/*
504 * Fifo failed operation
505 */
506static int
507fifo_ebadf()
508{
509
510 return (EBADF);
511}
512
513/*
514 * Fifo advisory byte-level locks.
515 */
516/* ARGSUSED */
517int
518fifo_advlock(ap)
519 struct vop_advlock_args /* {
520 struct vnode *a_vp;
521 caddr_t a_id;
522 int a_op;
523 struct flock *a_fl;
524 int a_flags;
525 } */ *ap;
526{
527
528 return (EOPNOTSUPP);
529}
530
531/*
532 * Fifo bad operation
533 */
534int
535fifo_badop()
536{
537
538 panic("fifo_badop called");
539 /* NOTREACHED */
540}
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)fifo_vnops.c 8.2 (Berkeley) 1/4/94
34 * $Id: fifo_vnops.c,v 1.12 1995/11/09 08:15:27 bde Exp $
35 */
36
37#include <sys/param.h>
38#include <sys/kernel.h>
39#include <sys/proc.h>
40#include <sys/time.h>
41#include <sys/namei.h>
42#include <sys/vnode.h>
43#include <sys/socket.h>
44#include <sys/socketvar.h>
45#include <sys/stat.h>
46#include <sys/systm.h>
47#include <sys/ioctl.h>
48#include <sys/file.h>
49#include <sys/errno.h>
50#include <sys/malloc.h>
51#include <sys/un.h>
52#include <miscfs/fifofs/fifo.h>
53
54/*
55 * This structure is associated with the FIFO vnode and stores
56 * the state associated with the FIFO.
57 */
58struct fifoinfo {
59 struct socket *fi_readsock;
60 struct socket *fi_writesock;
61 long fi_readers;
62 long fi_writers;
63};
64
65vop_t **fifo_vnodeop_p;
66static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
67 { &vop_default_desc, (vop_t *)vn_default_error },
68 { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
69 { &vop_create_desc, (vop_t *)fifo_create }, /* create */
70 { &vop_mknod_desc, (vop_t *)fifo_mknod }, /* mknod */
71 { &vop_open_desc, (vop_t *)fifo_open }, /* open */
72 { &vop_close_desc, (vop_t *)fifo_close }, /* close */
73 { &vop_access_desc, (vop_t *)fifo_access }, /* access */
74 { &vop_getattr_desc, (vop_t *)fifo_getattr }, /* getattr */
75 { &vop_setattr_desc, (vop_t *)fifo_setattr }, /* setattr */
76 { &vop_read_desc, (vop_t *)fifo_read }, /* read */
77 { &vop_write_desc, (vop_t *)fifo_write }, /* write */
78 { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
79 { &vop_select_desc, (vop_t *)fifo_select }, /* select */
80 { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
81 { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
82 { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
83 { &vop_remove_desc, (vop_t *)fifo_remove }, /* remove */
84 { &vop_link_desc, (vop_t *)fifo_link }, /* link */
85 { &vop_rename_desc, (vop_t *)fifo_rename }, /* rename */
86 { &vop_mkdir_desc, (vop_t *)fifo_mkdir }, /* mkdir */
87 { &vop_rmdir_desc, (vop_t *)fifo_rmdir }, /* rmdir */
88 { &vop_symlink_desc, (vop_t *)fifo_symlink }, /* symlink */
89 { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
90 { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
91 { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
92 { &vop_inactive_desc, (vop_t *)fifo_inactive }, /* inactive */
93 { &vop_reclaim_desc, (vop_t *)fifo_reclaim }, /* reclaim */
94 { &vop_lock_desc, (vop_t *)fifo_lock }, /* lock */
95 { &vop_unlock_desc, (vop_t *)fifo_unlock }, /* unlock */
96 { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
97 { &vop_strategy_desc, (vop_t *)fifo_strategy }, /* strategy */
98 { &vop_print_desc, (vop_t *)fifo_print }, /* print */
99 { &vop_islocked_desc, (vop_t *)fifo_islocked }, /* islocked */
100 { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
101 { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
102 { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
103 { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
104 { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
105 { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
106 { &vop_update_desc, (vop_t *)fifo_update }, /* update */
107 { &vop_bwrite_desc, (vop_t *)fifo_bwrite }, /* bwrite */
108 { NULL, NULL }
109};
110static struct vnodeopv_desc fifo_vnodeop_opv_desc =
111 { &fifo_vnodeop_p, fifo_vnodeop_entries };
112
113VNODEOP_SET(fifo_vnodeop_opv_desc);
114
115/*
116 * Trivial lookup routine that always fails.
117 */
118/* ARGSUSED */
119int
120fifo_lookup(ap)
121 struct vop_lookup_args /* {
122 struct vnode * a_dvp;
123 struct vnode ** a_vpp;
124 struct componentname * a_cnp;
125 } */ *ap;
126{
127
128 *ap->a_vpp = NULL;
129 return (ENOTDIR);
130}
131
132/*
133 * Open called to set up a new instance of a fifo or
134 * to find an active instance of a fifo.
135 */
136/* ARGSUSED */
137int
138fifo_open(ap)
139 struct vop_open_args /* {
140 struct vnode *a_vp;
141 int a_mode;
142 struct ucred *a_cred;
143 struct proc *a_p;
144 } */ *ap;
145{
146 register struct vnode *vp = ap->a_vp;
147 register struct fifoinfo *fip;
148 struct socket *rso, *wso;
149 int error;
150 static char openstr[] = "fifo";
151
152 if ((fip = vp->v_fifoinfo) == NULL) {
153 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
154 vp->v_fifoinfo = fip;
155 error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
156 if (error) {
157 free(fip, M_VNODE);
158 vp->v_fifoinfo = NULL;
159 return (error);
160 }
161 fip->fi_readsock = rso;
162 error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
163 if (error) {
164 (void)soclose(rso);
165 free(fip, M_VNODE);
166 vp->v_fifoinfo = NULL;
167 return (error);
168 }
169 fip->fi_writesock = wso;
170 error = unp_connect2(wso, rso);
171 if (error) {
172 (void)soclose(wso);
173 (void)soclose(rso);
174 free(fip, M_VNODE);
175 vp->v_fifoinfo = NULL;
176 return (error);
177 }
178 fip->fi_readers = fip->fi_writers = 0;
179 wso->so_state |= SS_CANTRCVMORE;
180 rso->so_state |= SS_CANTSENDMORE;
181 }
182 error = 0;
183 if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
184 if (fip->fi_readers == 0) {
185 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
186 if (fip->fi_writers > 0)
187 wakeup((caddr_t)&fip->fi_writers);
188 }
189 if (fip->fi_writers == 0) {
190 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
191 if (fip->fi_readers > 0)
192 wakeup((caddr_t)&fip->fi_readers);
193 }
194 fip->fi_readers++;
195 fip->fi_writers++;
196 }
197 else if (ap->a_mode & FREAD) {
198 fip->fi_readers++;
199 if (fip->fi_readers == 1) {
200 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
201 if (fip->fi_writers > 0)
202 wakeup((caddr_t)&fip->fi_writers);
203 }
204 if (!(ap->a_mode & O_NONBLOCK))
205 while (fip->fi_writers == 0) {
206 VOP_UNLOCK(vp);
207 error = tsleep((caddr_t)&fip->fi_readers,
208 PCATCH | PSOCK, openstr, 0);
209 VOP_LOCK(vp);
210 if (error)
211 break;
212 }
213 }
214 else {
215 fip->fi_writers++;
216 if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) {
217 error = ENXIO;
218 } else {
219 if (fip->fi_writers == 1) {
220 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
221 if (fip->fi_readers > 0)
222 wakeup((caddr_t)&fip->fi_readers);
223 }
224 while (fip->fi_readers == 0) {
225 VOP_UNLOCK(vp);
226 error = tsleep((caddr_t)&fip->fi_writers,
227 PCATCH | PSOCK, openstr, 0);
228 VOP_LOCK(vp);
229 if (error)
230 break;
231 }
232 }
233 }
234 if (error)
235 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
236 return (error);
237}
238
239/*
240 * Vnode op for read
241 */
242/* ARGSUSED */
243int
244fifo_read(ap)
245 struct vop_read_args /* {
246 struct vnode *a_vp;
247 struct uio *a_uio;
248 int a_ioflag;
249 struct ucred *a_cred;
250 } */ *ap;
251{
252 register struct uio *uio = ap->a_uio;
253 register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
254 int error, startresid;
255
256#ifdef DIAGNOSTIC
257 if (uio->uio_rw != UIO_READ)
258 panic("fifo_read mode");
259#endif
260 if (uio->uio_resid == 0)
261 return (0);
262 if (ap->a_ioflag & IO_NDELAY)
263 rso->so_state |= SS_NBIO;
264 startresid = uio->uio_resid;
265 VOP_UNLOCK(ap->a_vp);
266 error = soreceive(rso, (struct mbuf **)0, uio,
267 (struct mbuf **)0, (struct mbuf **)0, (int*)0);
268 VOP_LOCK(ap->a_vp);
269 /*
270 * Clear EOF indication after first such return.
271 */
272 if (uio->uio_resid == startresid)
273 rso->so_state &= ~SS_CANTRCVMORE;
274 if (ap->a_ioflag & IO_NDELAY)
275 rso->so_state &= ~SS_NBIO;
276 return (error);
277}
278
279/*
280 * Vnode op for write
281 */
282/* ARGSUSED */
283int
284fifo_write(ap)
285 struct vop_write_args /* {
286 struct vnode *a_vp;
287 struct uio *a_uio;
288 int a_ioflag;
289 struct ucred *a_cred;
290 } */ *ap;
291{
292 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
293 int error;
294
295#ifdef DIAGNOSTIC
296 if (ap->a_uio->uio_rw != UIO_WRITE)
297 panic("fifo_write mode");
298#endif
299 if (ap->a_ioflag & IO_NDELAY)
300 wso->so_state |= SS_NBIO;
301 VOP_UNLOCK(ap->a_vp);
302 error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0);
303 VOP_LOCK(ap->a_vp);
304 if (ap->a_ioflag & IO_NDELAY)
305 wso->so_state &= ~SS_NBIO;
306 return (error);
307}
308
309/*
310 * Device ioctl operation.
311 */
312/* ARGSUSED */
313int
314fifo_ioctl(ap)
315 struct vop_ioctl_args /* {
316 struct vnode *a_vp;
317 int a_command;
318 caddr_t a_data;
319 int a_fflag;
320 struct ucred *a_cred;
321 struct proc *a_p;
322 } */ *ap;
323{
324 struct file filetmp;
325
326 if (ap->a_command == FIONBIO)
327 return (0);
328 if (ap->a_fflag & FREAD)
329 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
330 else
331 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
332 return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p));
333}
334
335/* ARGSUSED */
336int
337fifo_select(ap)
338 struct vop_select_args /* {
339 struct vnode *a_vp;
340 int a_which;
341 int a_fflags;
342 struct ucred *a_cred;
343 struct proc *a_p;
344 } */ *ap;
345{
346 struct file filetmp;
347
348 if (ap->a_fflags & FREAD)
349 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
350 else
351 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
352 return (soo_select(&filetmp, ap->a_which, ap->a_p));
353}
354
355/*
356 * This is a noop, simply returning what one has been given.
357 */
358int
359fifo_bmap(ap)
360 struct vop_bmap_args /* {
361 struct vnode *a_vp;
362 daddr_t a_bn;
363 struct vnode **a_vpp;
364 daddr_t *a_bnp;
365 int *a_runp;
366 int *a_runb;
367 } */ *ap;
368{
369
370 if (ap->a_vpp != NULL)
371 *ap->a_vpp = ap->a_vp;
372 if (ap->a_bnp != NULL)
373 *ap->a_bnp = ap->a_bn;
374 if (ap->a_runp != NULL)
375 *ap->a_runp = 0;
376 if (ap->a_runb != NULL)
377 *ap->a_runb = 0;
378 return (0);
379}
380
381/*
382 * At the moment we do not do any locking.
383 */
384/* ARGSUSED */
385static int
386fifo_lock(ap)
387 struct vop_lock_args /* {
388 struct vnode *a_vp;
389 } */ *ap;
390{
391
392 return (0);
393}
394
395/* ARGSUSED */
396static int
397fifo_unlock(ap)
398 struct vop_unlock_args /* {
399 struct vnode *a_vp;
400 } */ *ap;
401{
402
403 return (0);
404}
405
406/*
407 * Device close routine
408 */
409/* ARGSUSED */
410int
411fifo_close(ap)
412 struct vop_close_args /* {
413 struct vnode *a_vp;
414 int a_fflag;
415 struct ucred *a_cred;
416 struct proc *a_p;
417 } */ *ap;
418{
419 register struct vnode *vp = ap->a_vp;
420 register struct fifoinfo *fip = vp->v_fifoinfo;
421 int error1, error2;
422
423 if (ap->a_fflag & FWRITE) {
424 fip->fi_writers--;
425 if (fip->fi_writers == 0)
426 socantrcvmore(fip->fi_readsock);
427 }
428 if (ap->a_fflag & FREAD) {
429 fip->fi_readers--;
430 if (fip->fi_readers == 0)
431 socantsendmore(fip->fi_writesock);
432 }
433 if (vp->v_usecount > 1)
434 return (0);
435 error1 = soclose(fip->fi_readsock);
436 error2 = soclose(fip->fi_writesock);
437 FREE(fip, M_VNODE);
438 vp->v_fifoinfo = NULL;
439 if (error1)
440 return (error1);
441 return (error2);
442}
443
444
445/*
446 * Print out internal contents of a fifo vnode.
447 */
448int
449fifo_printinfo(vp)
450 struct vnode *vp;
451{
452 register struct fifoinfo *fip = vp->v_fifoinfo;
453
454 printf(", fifo with %ld readers and %ld writers",
455 fip->fi_readers, fip->fi_writers);
456 return (0);
457}
458
459/*
460 * Print out the contents of a fifo vnode.
461 */
462static int
463fifo_print(ap)
464 struct vop_print_args /* {
465 struct vnode *a_vp;
466 } */ *ap;
467{
468
469 printf("tag VT_NON");
470 fifo_printinfo(ap->a_vp);
471 printf("\n");
472 return (0);
473}
474
475/*
476 * Return POSIX pathconf information applicable to fifo's.
477 */
478int
479fifo_pathconf(ap)
480 struct vop_pathconf_args /* {
481 struct vnode *a_vp;
482 int a_name;
483 int *a_retval;
484 } */ *ap;
485{
486
487 switch (ap->a_name) {
488 case _PC_LINK_MAX:
489 *ap->a_retval = LINK_MAX;
490 return (0);
491 case _PC_PIPE_BUF:
492 *ap->a_retval = PIPE_BUF;
493 return (0);
494 case _PC_CHOWN_RESTRICTED:
495 *ap->a_retval = 1;
496 return (0);
497 default:
498 return (EINVAL);
499 }
500 /* NOTREACHED */
501}
502
503/*
504 * Fifo failed operation
505 */
506static int
507fifo_ebadf()
508{
509
510 return (EBADF);
511}
512
513/*
514 * Fifo advisory byte-level locks.
515 */
516/* ARGSUSED */
517int
518fifo_advlock(ap)
519 struct vop_advlock_args /* {
520 struct vnode *a_vp;
521 caddr_t a_id;
522 int a_op;
523 struct flock *a_fl;
524 int a_flags;
525 } */ *ap;
526{
527
528 return (EOPNOTSUPP);
529}
530
531/*
532 * Fifo bad operation
533 */
534int
535fifo_badop()
536{
537
538 panic("fifo_badop called");
539 /* NOTREACHED */
540}