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