1 /* $OpenBSD: fifo_vnops.c,v 1.51 2016/06/07 06:12:37 deraadt Exp $ */ 2 /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)fifo_vnops.c 8.4 (Berkeley) 8/10/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/time.h> 38 #include <sys/namei.h> 39 #include <sys/vnode.h> 40 #include <sys/lock.h> 41 #include <sys/protosw.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/stat.h> 45 #include <sys/ioctl.h> 46 #include <sys/file.h> 47 #include <sys/event.h> 48 #include <sys/errno.h> 49 #include <sys/malloc.h> 50 #include <sys/poll.h> 51 #include <sys/unpcb.h> 52 #include <sys/unistd.h> 53 54 #include <miscfs/fifofs/fifo.h> 55 56 /* 57 * This structure is associated with the FIFO vnode and stores 58 * the state associated with the FIFO. 59 */ 60 struct fifoinfo { 61 struct socket *fi_readsock; 62 struct socket *fi_writesock; 63 long fi_readers; 64 long fi_writers; 65 }; 66 67 struct vops fifo_vops = { 68 .vop_lookup = vop_generic_lookup, 69 .vop_create = fifo_badop, 70 .vop_mknod = fifo_badop, 71 .vop_open = fifo_open, 72 .vop_close = fifo_close, 73 .vop_access = fifo_ebadf, 74 .vop_getattr = fifo_ebadf, 75 .vop_setattr = fifo_ebadf, 76 .vop_read = fifo_read, 77 .vop_write = fifo_write, 78 .vop_ioctl = fifo_ioctl, 79 .vop_poll = fifo_poll, 80 .vop_kqfilter = fifo_kqfilter, 81 .vop_revoke = vop_generic_revoke, 82 .vop_fsync = nullop, 83 .vop_remove = fifo_badop, 84 .vop_link = fifo_badop, 85 .vop_rename = fifo_badop, 86 .vop_mkdir = fifo_badop, 87 .vop_rmdir = fifo_badop, 88 .vop_symlink = fifo_badop, 89 .vop_readdir = fifo_badop, 90 .vop_readlink = fifo_badop, 91 .vop_abortop = fifo_badop, 92 .vop_inactive = fifo_inactive, 93 .vop_reclaim = fifo_reclaim, 94 .vop_lock = vop_generic_lock, 95 .vop_unlock = vop_generic_unlock, 96 .vop_bmap = vop_generic_bmap, 97 .vop_strategy = fifo_badop, 98 .vop_print = fifo_print, 99 .vop_islocked = vop_generic_islocked, 100 .vop_pathconf = fifo_pathconf, 101 .vop_advlock = fifo_advlock, 102 .vop_bwrite = nullop 103 }; 104 105 void filt_fifordetach(struct knote *kn); 106 int filt_fiforead(struct knote *kn, long hint); 107 void filt_fifowdetach(struct knote *kn); 108 int filt_fifowrite(struct knote *kn, long hint); 109 110 struct filterops fiforead_filtops = 111 { 1, NULL, filt_fifordetach, filt_fiforead }; 112 struct filterops fifowrite_filtops = 113 { 1, NULL, filt_fifowdetach, filt_fifowrite }; 114 115 /* 116 * Open called to set up a new instance of a fifo or 117 * to find an active instance of a fifo. 118 */ 119 /* ARGSUSED */ 120 int 121 fifo_open(void *v) 122 { 123 struct vop_open_args *ap = v; 124 struct vnode *vp = ap->a_vp; 125 struct fifoinfo *fip; 126 struct proc *p = ap->a_p; 127 struct socket *rso, *wso; 128 int error; 129 130 if ((fip = vp->v_fifoinfo) == NULL) { 131 fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK); 132 vp->v_fifoinfo = fip; 133 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) { 134 free(fip, M_VNODE, sizeof *fip); 135 vp->v_fifoinfo = NULL; 136 return (error); 137 } 138 fip->fi_readsock = rso; 139 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) { 140 (void)soclose(rso); 141 free(fip, M_VNODE, sizeof *fip); 142 vp->v_fifoinfo = NULL; 143 return (error); 144 } 145 fip->fi_writesock = wso; 146 if ((error = unp_connect2(wso, rso)) != 0) { 147 (void)soclose(wso); 148 (void)soclose(rso); 149 free(fip, M_VNODE, sizeof *fip); 150 vp->v_fifoinfo = NULL; 151 return (error); 152 } 153 fip->fi_readers = fip->fi_writers = 0; 154 wso->so_state |= SS_CANTSENDMORE; 155 wso->so_snd.sb_lowat = PIPE_BUF; 156 } 157 if (ap->a_mode & FREAD) { 158 fip->fi_readers++; 159 if (fip->fi_readers == 1) { 160 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 161 if (fip->fi_writers > 0) 162 wakeup(&fip->fi_writers); 163 } 164 } 165 if (ap->a_mode & FWRITE) { 166 fip->fi_writers++; 167 if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { 168 error = ENXIO; 169 goto bad; 170 } 171 if (fip->fi_writers == 1) { 172 fip->fi_readsock->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED); 173 if (fip->fi_readers > 0) 174 wakeup(&fip->fi_readers); 175 } 176 } 177 if ((ap->a_mode & O_NONBLOCK) == 0) { 178 if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { 179 VOP_UNLOCK(vp, p); 180 error = tsleep(&fip->fi_readers, 181 PCATCH | PSOCK, "fifor", 0); 182 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 183 if (error) 184 goto bad; 185 } 186 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { 187 VOP_UNLOCK(vp, p); 188 error = tsleep(&fip->fi_writers, 189 PCATCH | PSOCK, "fifow", 0); 190 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 191 if (error) 192 goto bad; 193 } 194 } 195 return (0); 196 bad: 197 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); 198 return (error); 199 } 200 201 /* 202 * Vnode op for read 203 */ 204 /* ARGSUSED */ 205 int 206 fifo_read(void *v) 207 { 208 struct vop_read_args *ap = v; 209 struct uio *uio = ap->a_uio; 210 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 211 struct proc *p = uio->uio_procp; 212 int error; 213 214 #ifdef DIAGNOSTIC 215 if (uio->uio_rw != UIO_READ) 216 panic("fifo_read mode"); 217 #endif 218 if (uio->uio_resid == 0) 219 return (0); 220 if (ap->a_ioflag & IO_NDELAY) 221 rso->so_state |= SS_NBIO; 222 VOP_UNLOCK(ap->a_vp, p); 223 error = soreceive(rso, NULL, uio, NULL, NULL, NULL, 0); 224 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 225 if (ap->a_ioflag & IO_NDELAY) { 226 rso->so_state &= ~SS_NBIO; 227 if (error == EWOULDBLOCK && 228 ap->a_vp->v_fifoinfo->fi_writers == 0) 229 error = 0; 230 } 231 return (error); 232 } 233 234 /* 235 * Vnode op for write 236 */ 237 /* ARGSUSED */ 238 int 239 fifo_write(void *v) 240 { 241 struct vop_write_args *ap = v; 242 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 243 struct proc *p = ap->a_uio->uio_procp; 244 int error; 245 246 #ifdef DIAGNOSTIC 247 if (ap->a_uio->uio_rw != UIO_WRITE) 248 panic("fifo_write mode"); 249 #endif 250 if (ap->a_ioflag & IO_NDELAY) 251 wso->so_state |= SS_NBIO; 252 VOP_UNLOCK(ap->a_vp, p); 253 error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0); 254 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 255 if (ap->a_ioflag & IO_NDELAY) 256 wso->so_state &= ~SS_NBIO; 257 return (error); 258 } 259 260 /* 261 * Device ioctl operation. 262 */ 263 /* ARGSUSED */ 264 int 265 fifo_ioctl(void *v) 266 { 267 struct vop_ioctl_args *ap = v; 268 struct file filetmp; 269 int error; 270 271 if (ap->a_command == FIONBIO) 272 return (0); 273 if (ap->a_fflag & FREAD) { 274 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 275 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 276 if (error) 277 return (error); 278 } 279 if (ap->a_fflag & FWRITE) { 280 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 281 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 282 if (error) 283 return (error); 284 } 285 return (0); 286 } 287 288 /* ARGSUSED */ 289 int 290 fifo_poll(void *v) 291 { 292 struct vop_poll_args *ap = v; 293 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 294 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 295 int events = 0; 296 int revents = 0; 297 298 /* 299 * FIFOs don't support out-of-band or high priority data. 300 */ 301 if (ap->a_fflag & FREAD) 302 events |= ap->a_events & (POLLIN | POLLRDNORM); 303 if (ap->a_fflag & FWRITE) 304 events |= ap->a_events & (POLLOUT | POLLWRNORM); 305 306 if (events & (POLLIN | POLLRDNORM)) { 307 if (soreadable(rso)) 308 revents |= events & (POLLIN | POLLRDNORM); 309 } 310 /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ 311 if ((rso->so_state & SS_ISDISCONNECTED) && !(ap->a_events & POLL_NOHUP)) { 312 revents |= POLLHUP; 313 } else if (events & (POLLOUT | POLLWRNORM)) { 314 if (sowriteable(wso)) 315 revents |= events & (POLLOUT | POLLWRNORM); 316 } 317 if (revents == 0) { 318 /* We want to return POLLHUP even if no valid events set. */ 319 if (events == 0 && !(ap->a_events & POLL_NOHUP)) 320 events = POLLIN; 321 if (events & (POLLIN | POLLRDNORM)) { 322 selrecord(ap->a_p, &rso->so_rcv.sb_sel); 323 rso->so_rcv.sb_flagsintr |= SB_SEL; 324 } 325 if (events & (POLLOUT | POLLWRNORM)) { 326 selrecord(ap->a_p, &wso->so_snd.sb_sel); 327 wso->so_snd.sb_flagsintr |= SB_SEL; 328 } 329 } 330 return (revents); 331 } 332 333 int 334 fifo_inactive(void *v) 335 { 336 struct vop_inactive_args *ap = v; 337 338 VOP_UNLOCK(ap->a_vp, ap->a_p); 339 return (0); 340 } 341 342 343 /* 344 * Device close routine 345 */ 346 /* ARGSUSED */ 347 int 348 fifo_close(void *v) 349 { 350 struct vop_close_args *ap = v; 351 struct vnode *vp = ap->a_vp; 352 struct fifoinfo *fip = vp->v_fifoinfo; 353 int error1 = 0, error2 = 0; 354 355 if (fip == NULL) 356 return (0); 357 358 if (ap->a_fflag & FREAD) { 359 if (--fip->fi_readers == 0) 360 socantsendmore(fip->fi_writesock); 361 } 362 if (ap->a_fflag & FWRITE) { 363 if (--fip->fi_writers == 0) { 364 /* SS_ISDISCONNECTED will result in POLLHUP */ 365 fip->fi_readsock->so_state |= SS_ISDISCONNECTED; 366 socantrcvmore(fip->fi_readsock); 367 } 368 } 369 if (fip->fi_readers == 0 && fip->fi_writers == 0) { 370 error1 = soclose(fip->fi_readsock); 371 error2 = soclose(fip->fi_writesock); 372 free(fip, M_VNODE, sizeof *fip); 373 vp->v_fifoinfo = NULL; 374 } 375 return (error1 ? error1 : error2); 376 } 377 378 int 379 fifo_reclaim(void *v) 380 { 381 struct vop_reclaim_args *ap = v; 382 struct vnode *vp = ap->a_vp; 383 struct fifoinfo *fip = vp->v_fifoinfo; 384 385 if (fip == NULL) 386 return (0); 387 388 soclose(fip->fi_readsock); 389 soclose(fip->fi_writesock); 390 free(fip, M_VNODE, sizeof *fip); 391 vp->v_fifoinfo = NULL; 392 393 return (0); 394 } 395 396 /* 397 * Print out the contents of a fifo vnode. 398 */ 399 int 400 fifo_print(void *v) 401 { 402 struct vop_print_args *ap = v; 403 404 printf("tag VT_NON"); 405 fifo_printinfo(ap->a_vp); 406 printf("\n"); 407 return 0; 408 } 409 410 /* 411 * Print out internal contents of a fifo vnode. 412 */ 413 void 414 fifo_printinfo(struct vnode *vp) 415 { 416 struct fifoinfo *fip = vp->v_fifoinfo; 417 418 printf(", fifo with %ld readers and %ld writers", 419 fip->fi_readers, fip->fi_writers); 420 } 421 422 /* 423 * Return POSIX pathconf information applicable to fifo's. 424 */ 425 int 426 fifo_pathconf(void *v) 427 { 428 struct vop_pathconf_args *ap = v; 429 int error = 0; 430 431 switch (ap->a_name) { 432 case _PC_LINK_MAX: 433 *ap->a_retval = LINK_MAX; 434 break; 435 case _PC_CHOWN_RESTRICTED: 436 *ap->a_retval = 1; 437 break; 438 case _PC_TIMESTAMP_RESOLUTION: 439 *ap->a_retval = 1; 440 break; 441 default: 442 error = EINVAL; 443 break; 444 } 445 446 return (error); 447 } 448 449 /* 450 * Fifo failed operation 451 */ 452 /*ARGSUSED*/ 453 int 454 fifo_ebadf(void *v) 455 { 456 457 return (EBADF); 458 } 459 460 /* 461 * Fifo advisory byte-level locks. 462 */ 463 /* ARGSUSED */ 464 int 465 fifo_advlock(void *v) 466 { 467 return (EOPNOTSUPP); 468 } 469 470 /* 471 * Fifo bad operation 472 */ 473 /*ARGSUSED*/ 474 int 475 fifo_badop(void *v) 476 { 477 478 panic("fifo_badop called"); 479 /* NOTREACHED */ 480 return(0); 481 } 482 483 484 int 485 fifo_kqfilter(void *v) 486 { 487 struct vop_kqfilter_args *ap = v; 488 struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock; 489 struct sockbuf *sb; 490 491 switch (ap->a_kn->kn_filter) { 492 case EVFILT_READ: 493 ap->a_kn->kn_fop = &fiforead_filtops; 494 sb = &so->so_rcv; 495 break; 496 case EVFILT_WRITE: 497 ap->a_kn->kn_fop = &fifowrite_filtops; 498 sb = &so->so_snd; 499 break; 500 default: 501 return (EINVAL); 502 } 503 504 ap->a_kn->kn_hook = so; 505 506 SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext); 507 sb->sb_flags |= SB_KNOTE; 508 509 return (0); 510 } 511 512 void 513 filt_fifordetach(struct knote *kn) 514 { 515 struct socket *so = (struct socket *)kn->kn_hook; 516 517 SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext); 518 if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note)) 519 so->so_rcv.sb_flags &= ~SB_KNOTE; 520 } 521 522 int 523 filt_fiforead(struct knote *kn, long hint) 524 { 525 struct socket *so = (struct socket *)kn->kn_hook; 526 527 kn->kn_data = so->so_rcv.sb_cc; 528 if (so->so_state & SS_CANTRCVMORE) { 529 kn->kn_flags |= EV_EOF; 530 return (1); 531 } 532 kn->kn_flags &= ~EV_EOF; 533 return (kn->kn_data > 0); 534 } 535 536 void 537 filt_fifowdetach(struct knote *kn) 538 { 539 struct socket *so = (struct socket *)kn->kn_hook; 540 541 SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext); 542 if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note)) 543 so->so_snd.sb_flags &= ~SB_KNOTE; 544 } 545 546 int 547 filt_fifowrite(struct knote *kn, long hint) 548 { 549 struct socket *so = (struct socket *)kn->kn_hook; 550 551 kn->kn_data = sbspace(&so->so_snd); 552 if (so->so_state & SS_CANTSENDMORE) { 553 kn->kn_flags |= EV_EOF; 554 return (1); 555 } 556 kn->kn_flags &= ~EV_EOF; 557 return (kn->kn_data >= so->so_snd.sb_lowat); 558 } 559