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