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