1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 3 * 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 * $Id: descrip.c,v 1.1 94/10/20 00:02:49 bill Exp $ 34 * 35 * File instance and file descriptor management and system calls. 36 */ 37 38 #include "sys/param.h" 39 #include "sys/stat.h" 40 #include "sys/ioctl.h" 41 #include "sys/fcntl.h" 42 #include "sys/syslog.h" 43 #include "sys/errno.h" 44 #include "filedesc.h" 45 #include "kernel.h" /* time */ 46 #include "malloc.h" 47 #include "modconfig.h" 48 #include "proc.h" 49 #include "socketvar.h" 50 #include "resourcevar.h" 51 #include "uio.h" 52 #ifdef KTRACE 53 #include "sys/ktrace.h" 54 #endif 55 56 57 #include "vnode.h" 58 59 #include "prototypes.h" 60 61 /* 62 * Descriptor management. 63 */ 64 struct file *filehead; /* head of list of open files */ 65 int nfiles; /* actual number of open files */ 66 static int fdopen(dev_t dev, int mode, int type, struct proc *p); 67 /*int fdalloc(struct proc *p, int want, int *result);*/ 68 static int selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval); 69 70 71 72 73 74 /* 75 * Descriptor system calls, both BSD and POSIX. 76 */ 77 78 /* BSD file descriptor "table" size (number of descriptors */ 79 int 80 getdtablesize(p, uap, retval) 81 struct proc *p; 82 void *uap; 83 int *retval; 84 { 85 86 *retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur; 87 return (0); 88 } 89 90 91 92 /* POSIX Duplicate a file descriptor. */ 93 int 94 dup(p, uap, retval) 95 struct proc *p; 96 struct args { 97 int i; 98 } *uap; 99 int *retval; 100 { 101 register struct filedesc *fdp = p->p_fd; 102 struct file *fp; 103 int fd, error; 104 105 if ((unsigned)uap->i >= fdp->fd_nfiles || 106 (fp = fdp->fd_ofiles[uap->i]) == NULL) 107 return (EBADF); 108 109 if (error = fdalloc(p, 0, &fd)) 110 return (error); 111 112 fdp->fd_ofiles[fd] = fp; 113 fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 114 fp->f_count++; 115 if (fd > fdp->fd_lastfile) 116 fdp->fd_lastfile = fd; 117 *retval = fd; 118 return (0); 119 } 120 121 122 123 124 /* POSIX Duplicate a file descriptor to a particular value. */ 125 int 126 dup2(p, uap, retval) 127 struct proc *p; 128 struct args { 129 u_int from; 130 u_int to; 131 } *uap; 132 int *retval; 133 { 134 register struct filedesc *fdp = p->p_fd; 135 register struct file *fp; 136 register u_int old = uap->from, new = uap->to; 137 int i, error; 138 139 if (old >= fdp->fd_nfiles || 140 (fp = fdp->fd_ofiles[old]) == NULL || 141 new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur) 142 return (EBADF); 143 144 *retval = new; 145 if (old == new) 146 return (0); 147 148 if (new >= fdp->fd_nfiles) { 149 if (error = fdalloc(p, new, &i)) 150 return (error); 151 #ifdef DIAGNOSTIC 152 if (new != i) 153 panic("dup2: fdalloc"); 154 #endif 155 } else if (fdp->fd_ofiles[new]) { 156 if (fdp->fd_ofileflags[new] & UF_MAPPED) 157 (void) munmapfd(p, new); 158 /* dup2() must succeed even if the close has an error.*/ 159 (void) closef(fdp->fd_ofiles[new], p); 160 } 161 162 fdp->fd_ofiles[new] = fp; 163 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE; 164 fp->f_count++; 165 if (new > fdp->fd_lastfile) 166 fdp->fd_lastfile = new; 167 return (0); 168 } 169 170 171 172 173 /* POSIX file control system call. */ 174 int 175 fcntl(p, uap, retval) 176 struct proc *p; 177 struct args { 178 int fd; 179 int cmd; 180 int arg; 181 } *uap; 182 int *retval; 183 { 184 struct filedesc *fdp = p->p_fd; 185 struct file *fp; 186 char *pop; 187 struct vnode *vp; 188 int i, tmp, error, flg = F_POSIX; 189 struct flock fl; 190 191 if ((unsigned)uap->fd >= fdp->fd_nfiles || 192 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 193 return (EBADF); 194 195 pop = &fdp->fd_ofileflags[uap->fd]; 196 switch(uap->cmd) { 197 case F_DUPFD: 198 if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur) 199 return (EINVAL); 200 if (error = fdalloc(p, uap->arg, &i)) 201 return (error); 202 fdp->fd_ofiles[i] = fp; 203 fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE; 204 fp->f_count++; 205 if (i > fdp->fd_lastfile) 206 fdp->fd_lastfile = i; 207 *retval = i; 208 return (0); 209 210 case F_GETFD: 211 *retval = *pop & UF_EXCLOSE; 212 return (0); 213 214 case F_SETFD: 215 *pop = (*pop &~ UF_EXCLOSE) | (uap->arg & 1); 216 return (0); 217 218 case F_GETFL: 219 *retval = OFLAGS(fp->f_flag); 220 return (0); 221 222 case F_SETFL: 223 fp->f_flag &= ~FCNTLFLAGS; 224 fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS; 225 tmp = fp->f_flag & FNONBLOCK; 226 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 227 if (error) 228 return (error); 229 tmp = fp->f_flag & FASYNC; 230 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 231 if (!error) 232 return (0); 233 fp->f_flag &= ~FNONBLOCK; 234 tmp = 0; 235 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 236 return (error); 237 238 case F_GETOWN: 239 if (fp->f_type == DTYPE_SOCKET) { 240 *retval = ((struct socket *)fp->f_data)->so_pgid; 241 return (0); 242 } 243 error = (*fp->f_ops->fo_ioctl) 244 (fp, (int)TIOCGPGRP, (caddr_t)retval, p); 245 *retval = -*retval; 246 return (error); 247 248 case F_SETOWN: 249 if (fp->f_type == DTYPE_SOCKET) { 250 ((struct socket *)fp->f_data)->so_pgid = uap->arg; 251 return (0); 252 } 253 if (uap->arg <= 0) { 254 uap->arg = -uap->arg; 255 } else { 256 struct proc *p1 = pfind(uap->arg); 257 if (p1 == 0) 258 return (ESRCH); 259 uap->arg = p1->p_pgrp->pg_id; 260 } 261 return ((*fp->f_ops->fo_ioctl) 262 (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p)); 263 264 case F_SETLKW: 265 flg |= F_WAIT; 266 /* Fall into F_SETLK */ 267 268 case F_SETLK: 269 if (fp->f_type != DTYPE_VNODE) 270 return (EBADF); 271 vp = (struct vnode *)fp->f_data; 272 273 /* fetch the lock structure */ 274 error = copyin(p, (caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); 275 if (error) 276 return (error); 277 278 if (fl.l_whence == SEEK_CUR) 279 fl.l_start += fp->f_offset; 280 281 switch (fl.l_type) { 282 283 case F_RDLCK: 284 if ((fp->f_flag & FREAD) == 0) 285 return (EBADF); 286 p->p_flag |= SADVLCK; 287 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); 288 289 case F_WRLCK: 290 if ((fp->f_flag & FWRITE) == 0) 291 return (EBADF); 292 p->p_flag |= SADVLCK; 293 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); 294 295 case F_UNLCK: 296 return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl, 297 F_POSIX)); 298 299 default: 300 return (EINVAL); 301 } 302 303 case F_GETLK: 304 if (fp->f_type != DTYPE_VNODE) 305 return (EBADF); 306 vp = (struct vnode *)fp->f_data; 307 308 /* fetch the lock structure */ 309 error = copyin(p, (caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); 310 if (error) 311 return (error); 312 if (fl.l_whence == SEEK_CUR) 313 fl.l_start += fp->f_offset; 314 if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX)) 315 return (error); 316 return (copyout(p, (caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl))); 317 318 default: 319 return (EINVAL); 320 } 321 /* NOTREACHED */ 322 } 323 324 325 326 327 /* POSIX close a file descriptor. */ 328 int 329 close(p, uap, retval) 330 struct proc *p; 331 struct args { 332 int fd; 333 } *uap; 334 int *retval; 335 { 336 struct filedesc *fdp = p->p_fd; 337 struct file *fp; 338 int fd = uap->fd; 339 u_char *pf; 340 341 if ((unsigned)fd >= fdp->fd_nfiles || 342 (fp = fdp->fd_ofiles[fd]) == NULL) 343 return (EBADF); 344 345 pf = (u_char *)&fdp->fd_ofileflags[fd]; 346 if (*pf & UF_MAPPED) 347 (void) munmapfd(p, fd); 348 349 fdp->fd_ofiles[fd] = NULL; 350 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 351 fdp->fd_lastfile--; 352 if (fd < fdp->fd_freefile) 353 fdp->fd_freefile = fd; 354 *pf = 0; 355 return (closef(fp, p)); 356 } 357 358 359 360 /* POSIX: Return status information about a file descriptor. */ 361 int 362 fstat(p, uap, retval) 363 struct proc *p; 364 struct args { 365 int fd; 366 struct stat *sb; 367 } *uap; 368 int *retval; 369 { 370 struct filedesc *fdp = p->p_fd; 371 struct file *fp; 372 struct stat ub; 373 int error; 374 375 if ((unsigned)uap->fd >= fdp->fd_nfiles || 376 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 377 return (EBADF); 378 379 switch (fp->f_type) { 380 381 case DTYPE_VNODE: 382 error = vn_stat((struct vnode *)fp->f_data, &ub, p); 383 break; 384 385 case DTYPE_SOCKET: 386 error = soo_stat((struct socket *)fp->f_data, &ub); 387 break; 388 389 default: 390 panic("fstat"); 391 /*NOTREACHED*/ 392 } 393 394 if (error == 0) 395 error = copyout(p, (caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); 396 return (error); 397 } 398 399 400 401 /* POSIX Read function system call handler. */ 402 int 403 read(p, uap, retval) 404 struct proc *p; 405 register struct args { 406 int fdes; 407 char *cbuf; 408 unsigned count; 409 } *uap; 410 int *retval; 411 { 412 register struct file *fp; 413 register struct filedesc *fdp = p->p_fd; 414 struct uio auio; 415 struct iovec aiov; 416 long cnt, error = 0; 417 #ifdef KTRACE 418 struct iovec ktriov; 419 #endif 420 421 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 422 (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 423 (fp->f_flag & FREAD) == 0) 424 return (EBADF); 425 426 aiov.iov_base = (caddr_t)uap->cbuf; 427 aiov.iov_len = uap->count; 428 auio.uio_iov = &aiov; 429 auio.uio_iovcnt = 1; 430 auio.uio_resid = uap->count; 431 auio.uio_rw = UIO_READ; 432 auio.uio_segflg = UIO_USERSPACE; 433 auio.uio_procp = p; 434 435 #ifdef KTRACE 436 /* 437 * if tracing, save a copy of iovec 438 */ 439 if (KTRPOINT(p, KTR_GENIO)) 440 ktriov = aiov; 441 #endif 442 443 cnt = uap->count; 444 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 445 if (auio.uio_resid != cnt && (error == ERESTART || 446 error == EINTR || error == EWOULDBLOCK)) 447 error = 0; 448 cnt -= auio.uio_resid; 449 450 #ifdef KTRACE 451 if (KTRPOINT(p, KTR_GENIO) && error == 0) 452 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error); 453 #endif 454 455 *retval = cnt; 456 return (error); 457 } 458 459 460 461 /* BSD scatter readv() system call handler. */ 462 int 463 readv(p, uap, retval) 464 struct proc *p; 465 register struct args { 466 int fdes; 467 struct iovec *iovp; 468 unsigned iovcnt; 469 } *uap; 470 int *retval; 471 { 472 struct file *fp; 473 struct filedesc *fdp = p->p_fd; 474 struct uio auio; 475 struct iovec *iov; 476 struct iovec *saveiov; 477 struct iovec aiov[UIO_SMALLIOV]; 478 long i, cnt, error = 0; 479 unsigned iovlen; 480 #ifdef KTRACE 481 struct iovec *ktriov = NULL; 482 #endif 483 484 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 485 (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 486 (fp->f_flag & FREAD) == 0) 487 return (EBADF); 488 489 /* note: can't use iovlen until iovcnt is validated */ 490 iovlen = uap->iovcnt * sizeof (struct iovec); 491 492 if (uap->iovcnt > UIO_SMALLIOV) { 493 if (uap->iovcnt > UIO_MAXIOV) 494 return (EINVAL); 495 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 496 saveiov = iov; 497 } else 498 iov = aiov; 499 500 auio.uio_iov = iov; 501 auio.uio_iovcnt = uap->iovcnt; 502 auio.uio_rw = UIO_READ; 503 auio.uio_segflg = UIO_USERSPACE; 504 auio.uio_procp = p; 505 506 if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 507 goto done; 508 509 auio.uio_resid = 0; 510 for (i = 0; i < uap->iovcnt; i++) { 511 if (iov->iov_len < 0) { 512 error = EINVAL; 513 goto done; 514 } 515 auio.uio_resid += iov->iov_len; 516 if (auio.uio_resid < 0) { 517 error = EINVAL; 518 goto done; 519 } 520 iov++; 521 } 522 523 #ifdef KTRACE 524 /* 525 * if tracing, save a copy of iovec 526 */ 527 if (KTRPOINT(p, KTR_GENIO)) { 528 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 529 (void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); 530 } 531 #endif 532 533 cnt = auio.uio_resid; 534 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 535 if (auio.uio_resid != cnt && (error == ERESTART || 536 error == EINTR || error == EWOULDBLOCK)) 537 error = 0; 538 cnt -= auio.uio_resid; 539 540 #ifdef KTRACE 541 if (ktriov != NULL) { 542 if (error == 0) 543 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 544 cnt, error); 545 FREE(ktriov, M_TEMP); 546 } 547 #endif 548 549 *retval = cnt; 550 done: 551 if (uap->iovcnt > UIO_SMALLIOV) 552 FREE(saveiov, M_IOV); 553 554 return (error); 555 } 556 557 558 559 /* POSIX write() function system call handler */ 560 int 561 write(p, uap, retval) 562 struct proc *p; 563 struct args { 564 int fdes; 565 char *cbuf; 566 unsigned count; 567 } *uap; 568 int *retval; 569 { 570 register struct file *fp; 571 register struct filedesc *fdp = p->p_fd; 572 struct uio auio; 573 struct iovec aiov; 574 long cnt, error = 0; 575 #ifdef KTRACE 576 struct iovec ktriov; 577 #endif 578 579 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 580 (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 581 (fp->f_flag & FWRITE) == 0) 582 return (EBADF); 583 584 aiov.iov_base = (caddr_t)uap->cbuf; 585 aiov.iov_len = uap->count; 586 auio.uio_iov = &aiov; 587 auio.uio_iovcnt = 1; 588 auio.uio_resid = uap->count; 589 auio.uio_rw = UIO_WRITE; 590 auio.uio_segflg = UIO_USERSPACE; 591 auio.uio_procp = p; 592 593 #ifdef KTRACE 594 /* 595 * if tracing, save a copy of iovec 596 */ 597 if (KTRPOINT(p, KTR_GENIO)) 598 ktriov = aiov; 599 #endif 600 601 cnt = uap->count; 602 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 603 if (auio.uio_resid != cnt && (error == ERESTART || 604 error == EINTR || error == EWOULDBLOCK)) 605 error = 0; 606 if (error == EPIPE) 607 psignal(p, SIGPIPE); 608 } 609 cnt -= auio.uio_resid; 610 611 #ifdef KTRACE 612 if (KTRPOINT(p, KTR_GENIO) && error == 0) 613 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 614 &ktriov, cnt, error); 615 #endif 616 617 *retval = cnt; 618 return (error); 619 } 620 621 622 623 /* BSD gather write writev() function system call handler */ 624 int 625 writev(p, uap, retval) 626 struct proc *p; 627 register struct args { 628 int fdes; 629 struct iovec *iovp; 630 unsigned iovcnt; 631 } *uap; 632 int *retval; 633 { 634 register struct file *fp; 635 register struct filedesc *fdp = p->p_fd; 636 struct uio auio; 637 register struct iovec *iov; 638 struct iovec *saveiov; 639 struct iovec aiov[UIO_SMALLIOV]; 640 long i, cnt, error = 0; 641 unsigned iovlen; 642 #ifdef KTRACE 643 struct iovec *ktriov = NULL; 644 #endif 645 646 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 647 (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 648 (fp->f_flag & FWRITE) == 0) 649 return (EBADF); 650 651 /* note: can't use iovlen until iovcnt is validated */ 652 iovlen = uap->iovcnt * sizeof (struct iovec); 653 if (uap->iovcnt > UIO_SMALLIOV) { 654 if (uap->iovcnt > UIO_MAXIOV) 655 return (EINVAL); 656 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 657 saveiov = iov; 658 } else 659 iov = aiov; 660 661 auio.uio_iov = iov; 662 auio.uio_iovcnt = uap->iovcnt; 663 auio.uio_rw = UIO_WRITE; 664 auio.uio_segflg = UIO_USERSPACE; 665 auio.uio_procp = p; 666 667 if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 668 goto done; 669 670 auio.uio_resid = 0; 671 for (i = 0; i < uap->iovcnt; i++) { 672 if (iov->iov_len < 0) { 673 error = EINVAL; 674 goto done; 675 } 676 auio.uio_resid += iov->iov_len; 677 if (auio.uio_resid < 0) { 678 error = EINVAL; 679 goto done; 680 } 681 iov++; 682 } 683 684 #ifdef KTRACE 685 /* 686 * if tracing, save a copy of iovec 687 */ 688 if (KTRPOINT(p, KTR_GENIO)) { 689 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 690 (void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); 691 } 692 #endif 693 694 cnt = auio.uio_resid; 695 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 696 if (auio.uio_resid != cnt && (error == ERESTART || 697 error == EINTR || error == EWOULDBLOCK)) 698 error = 0; 699 if (error == EPIPE) 700 psignal(p, SIGPIPE); 701 } 702 cnt -= auio.uio_resid; 703 704 #ifdef KTRACE 705 if (ktriov != NULL) { 706 if (error == 0) 707 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 708 ktriov, cnt, error); 709 FREE(ktriov, M_TEMP); 710 } 711 #endif 712 713 *retval = cnt; 714 done: 715 if (uap->iovcnt > UIO_SMALLIOV) 716 FREE(saveiov, M_IOV); 717 718 return (error); 719 } 720 721 722 723 724 /* POSIX ioctl() function system call handler */ 725 int 726 ioctl(p, uap, retval) 727 struct proc *p; 728 register struct args { 729 int fdes; 730 int cmd; 731 caddr_t cmarg; 732 } *uap; 733 int *retval; 734 { 735 struct file *fp; 736 struct filedesc *fdp = p->p_fd; 737 int com, error; 738 u_int size; 739 caddr_t memp = 0; 740 #define STK_PARAMS 128 741 char stkbuf[STK_PARAMS]; 742 caddr_t data = stkbuf; 743 int tmp; 744 745 if ((unsigned)uap->fdes >= fdp->fd_nfiles || 746 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 747 return (EBADF); 748 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 749 return (EBADF); 750 751 com = uap->cmd; 752 if (com == FIOCLEX) { 753 fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE; 754 return (0); 755 } 756 if (com == FIONCLEX) { 757 fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE; 758 return (0); 759 } 760 761 /* 762 * Interpret high order word to find 763 * amount of data to be copied to/from the 764 * user's address space. 765 */ 766 size = IOCPARM_LEN(com); 767 if (size > IOCPARM_MAX) 768 return (ENOTTY); 769 if (size > sizeof (stkbuf)) { 770 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 771 data = memp; 772 } 773 if (com&IOC_IN) { 774 if (size) { 775 error = copyin(p, uap->cmarg, data, (u_int)size); 776 if (error) { 777 if (memp) 778 free(memp, M_IOCTLOPS); 779 return (error); 780 } 781 } else 782 *(caddr_t *)data = uap->cmarg; 783 } else if ((com&IOC_OUT) && size) 784 /* 785 * Zero the buffer so the user always 786 * gets back something deterministic. 787 */ 788 (void) memset(data, 0, size); 789 else if (com&IOC_VOID) 790 *(caddr_t *)data = uap->cmarg; 791 792 switch (com) { 793 794 case FIONBIO: 795 if (tmp = *(int *)data) 796 fp->f_flag |= FNONBLOCK; 797 else 798 fp->f_flag &= ~FNONBLOCK; 799 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 800 break; 801 802 case FIOASYNC: 803 if (tmp = *(int *)data) 804 fp->f_flag |= FASYNC; 805 else 806 fp->f_flag &= ~FASYNC; 807 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 808 break; 809 810 case FIOSETOWN: 811 tmp = *(int *)data; 812 if (fp->f_type == DTYPE_SOCKET) { 813 ((struct socket *)fp->f_data)->so_pgid = tmp; 814 error = 0; 815 break; 816 } 817 if (tmp <= 0) { 818 tmp = -tmp; 819 } else { 820 struct proc *p1 = pfind(tmp); 821 if (p1 == 0) { 822 error = ESRCH; 823 break; 824 } 825 tmp = p1->p_pgrp->pg_id; 826 } 827 error = (*fp->f_ops->fo_ioctl) 828 (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 829 break; 830 831 case FIOGETOWN: 832 if (fp->f_type == DTYPE_SOCKET) { 833 error = 0; 834 *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 835 break; 836 } 837 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 838 *(int *)data = -*(int *)data; 839 break; 840 841 default: 842 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 843 if (error == 0 && (com&IOC_OUT) && size) 844 error = copyout(p, data, uap->cmarg, (u_int)size); 845 break; 846 } 847 848 if (memp) 849 free(memp, M_IOCTLOPS); 850 return (error); 851 } 852 853 int selwait, nselcoll; 854 855 856 857 /* BSD select() function system call handler. */ 858 int 859 select(p, uap, retval) 860 register struct proc *p; 861 register struct args { 862 int nd; 863 fd_set *in, *ou, *ex; 864 struct timeval *tv; 865 } *uap; 866 int *retval; 867 { 868 fd_set ibits[3], obits[3]; 869 struct timeval atv; 870 int ncoll, ni, error = 0, timo; 871 872 (void) memset((caddr_t)ibits, 0, sizeof(ibits)); 873 (void) memset((caddr_t)obits, 0, sizeof(obits)); 874 if (uap->nd > p->p_fd->fd_nfiles) 875 uap->nd = p->p_fd->fd_nfiles; 876 ni = howmany(uap->nd, NFDBITS); 877 878 #define getbits(name, x) \ 879 if (uap->name) { \ 880 error = copyin(p, (caddr_t)uap->name, (caddr_t)&ibits[x], \ 881 (unsigned)(ni * sizeof(fd_mask))); \ 882 if (error) \ 883 goto done; \ 884 } 885 getbits(in, 0); 886 getbits(ou, 1); 887 getbits(ex, 2); 888 #undef getbits 889 890 if (uap->tv) { 891 error = copyin(p, (caddr_t)uap->tv, (caddr_t)&atv, 892 sizeof (atv)); 893 if (error) 894 goto done; 895 if (itimerfix(&atv)) { 896 error = EINVAL; 897 goto done; 898 } 899 splclock(); timevaladd(&atv, &time); splnone(); 900 timo = hzto(&atv); 901 } else 902 timo = 0; 903 904 retry: 905 ncoll = nselcoll; 906 p->p_flag |= SSEL; 907 error = selscan(p, ibits, obits, uap->nd, retval); 908 if (error || *retval) 909 goto done; 910 911 splhigh(); 912 /* this should be timercmp(&time, &atv, >=) */ 913 if (uap->tv && (time.tv_sec > atv.tv_sec || 914 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 915 p->p_flag &= ~SSEL; 916 /* error = EWOULDBLOCK; */ 917 splnone(); 918 goto done; 919 } 920 if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 921 splnone(); 922 goto retry; 923 } 924 p->p_flag &= ~SSEL; 925 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 926 splnone(); 927 928 if (error == 0) 929 goto retry; 930 done: 931 932 /* select is not restarted after signals... */ 933 if (error == ERESTART) 934 error = EINTR; 935 if (error == EWOULDBLOCK) 936 error = 0; 937 938 #define putbits(name, x) \ 939 if (uap->name) { \ 940 int error2 = copyout(p, (caddr_t)&obits[x], (caddr_t)uap->name, \ 941 (unsigned)(ni * sizeof(fd_mask))); \ 942 if (error2) \ 943 error = error2; \ 944 } 945 if (error == 0) { 946 putbits(in, 0); 947 putbits(ou, 1); 948 putbits(ex, 2); 949 } 950 #undef putbits 951 952 return (error); 953 } 954 955 static int 956 selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval) 957 { 958 struct filedesc *fdp = p->p_fd; 959 int which, i, j; 960 fd_mask bits; 961 int flag; 962 struct file *fp; 963 int error = 0, n = 0; 964 965 for (which = 0; which < 3; which++) { 966 switch (which) { 967 968 case 0: 969 flag = FREAD; break; 970 971 case 1: 972 flag = FWRITE; break; 973 974 case 2: 975 flag = 0; break; 976 } 977 for (i = 0; i < nfd; i += NFDBITS) { 978 bits = ibits[which].fds_bits[i/NFDBITS]; 979 while ((j = ffs(bits)) && i + --j < nfd) { 980 bits &= ~(1 << j); 981 fp = fdp->fd_ofiles[i + j]; 982 if (fp == NULL) { 983 error = EBADF; 984 break; 985 } 986 if ((*fp->f_ops->fo_select)(fp, flag, p)) { 987 FD_SET(i + j, &obits[which]); 988 n++; 989 } 990 } 991 } 992 } 993 *retval = n; 994 return (error); 995 } 996 997 /*ARGSUSED*/ 998 int 999 seltrue(dev_t dev, int which, struct proc *p) 1000 { 1001 1002 return (1); 1003 } 1004 1005 1006 void 1007 selwakeup(pid_t pid, int coll) 1008 { 1009 register struct proc *p; 1010 1011 if (coll) { 1012 nselcoll++; 1013 wakeup((caddr_t)&selwait); 1014 } 1015 1016 if (pid && (p = pfind(pid))) { 1017 int s = splhigh(); 1018 1019 if (p->p_wchan == (caddr_t)&selwait) { 1020 if (p->p_stat == SSLEEP) 1021 setrun(p); 1022 else 1023 unsleep(p); 1024 } else if (p->p_flag & SSEL) 1025 p->p_flag &= ~SSEL; 1026 splx(s); 1027 } 1028 } 1029 1030 /* 1031 * Allocate a file descriptor for the process. 1032 */ 1033 int 1034 fdalloc(struct proc *p, int want, int *result) 1035 { 1036 register struct filedesc *fdp = p->p_fd; 1037 int i; 1038 int lim, last, nfiles; 1039 struct file **newofile; 1040 char *newofileflags; 1041 1042 /* 1043 * Search for a free descriptor starting at the higher 1044 * of want or fd_freefile. If that fails, consider 1045 * expanding the ofile array. 1046 */ 1047 lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur; 1048 for (;;) { 1049 last = min(fdp->fd_nfiles, lim); 1050 if ((i = want) < fdp->fd_freefile) 1051 i = fdp->fd_freefile; 1052 for (; i < last; i++) { 1053 if (fdp->fd_ofiles[i] == NULL) { 1054 fdp->fd_ofileflags[i] = 0; 1055 if (i > fdp->fd_lastfile) 1056 fdp->fd_lastfile = i; 1057 if (want <= fdp->fd_freefile) 1058 fdp->fd_freefile = i; 1059 *result = i; 1060 return (0); 1061 } 1062 } 1063 1064 /* no space in current array. expand it? */ 1065 if (fdp->fd_nfiles >= lim) 1066 return (EMFILE); 1067 if (fdp->fd_nfiles < NDEXTENT) 1068 nfiles = NDEXTENT; 1069 else 1070 nfiles = (2 * fdp->fd_nfiles) % lim; 1071 1072 MALLOC(newofile, struct file **, nfiles * OFILESIZE, 1073 M_FILEDESC, M_WAITOK); 1074 newofileflags = (char *) &newofile[nfiles]; 1075 1076 /* 1077 * Copy the existing ofile and ofileflags arrays 1078 * and zero the new portion of each array. 1079 */ 1080 (void) memcpy(newofile, fdp->fd_ofiles, 1081 (i = sizeof(struct file *) * fdp->fd_nfiles)); 1082 (void) memset((char *)newofile + i, 0, 1083 nfiles * sizeof(struct file *) - i); 1084 (void) memcpy(newofileflags, fdp->fd_ofileflags, 1085 (i = sizeof(char) * fdp->fd_nfiles)); 1086 (void) memset(newofileflags + i, 0, nfiles * sizeof(char) - i); 1087 1088 if (fdp->fd_nfiles > NDFILE) 1089 FREE(fdp->fd_ofiles, M_FILEDESC); 1090 1091 fdp->fd_ofiles = newofile; 1092 fdp->fd_ofileflags = newofileflags; 1093 fdp->fd_nfiles = nfiles; 1094 } 1095 } 1096 1097 /* 1098 * Check to see whether n user file descriptors 1099 * are available to the process p. 1100 */ 1101 int 1102 fdavail(struct proc *p, int n) 1103 { 1104 struct filedesc *fdp = p->p_fd; 1105 struct file **fpp; 1106 int i; 1107 1108 if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 && 1109 (n -= i) <= 0) 1110 return (1); 1111 1112 fpp = &fdp->fd_ofiles[fdp->fd_freefile]; 1113 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++) 1114 if (*fpp == NULL && --n <= 0) 1115 return (1); 1116 return (0); 1117 } 1118 1119 /* 1120 * Create a new open file structure and allocate 1121 * a file descriptor for the process that refers to it. 1122 */ 1123 int 1124 falloc(struct proc *p, struct file **resultfp, int *resultfd) 1125 { 1126 struct file *fp, *fq, **fpp; 1127 int error, i; 1128 1129 if (error = fdalloc(p, 0, &i)) 1130 return (error); 1131 if (nfiles >= maxfiles) { 1132 tablefull("file"); 1133 return (ENFILE); 1134 } 1135 1136 /* 1137 * Allocate a new file descriptor. 1138 * If the process has file descriptor zero open, add to the list 1139 * of open files at that point, otherwise put it at the front of 1140 * the list of open files. 1141 */ 1142 nfiles++; 1143 MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); 1144 if (fq = p->p_fd->fd_ofiles[0]) 1145 fpp = &fq->f_filef; 1146 else 1147 fpp = &filehead; 1148 p->p_fd->fd_ofiles[i] = fp; 1149 if (fq = *fpp) 1150 fq->f_fileb = &fp->f_filef; 1151 fp->f_filef = fq; 1152 fp->f_fileb = fpp; 1153 *fpp = fp; 1154 1155 fp->f_count = 1; 1156 fp->f_msgcount = 0; 1157 fp->f_offset = 0; 1158 fp->f_cred = p->p_ucred; 1159 crhold(fp->f_cred); 1160 1161 if (resultfp) 1162 *resultfp = fp; 1163 if (resultfd) 1164 *resultfd = i; 1165 return (0); 1166 } 1167 1168 /* 1169 * Free a file instance, recovering resources. 1170 */ 1171 void 1172 ffree(struct file *fp) 1173 { 1174 struct file *fq; 1175 1176 /* remove from global file list */ 1177 if (fq = fp->f_filef) 1178 fq->f_fileb = fp->f_fileb; 1179 *fp->f_fileb = fq; 1180 1181 #ifdef DIAGNOSTIC 1182 fp->f_filef = NULL; 1183 fp->f_fileb = NULL; 1184 fp->f_count = 0; 1185 #endif 1186 1187 crfree(fp->f_cred); 1188 nfiles--; 1189 FREE(fp, M_FILE); 1190 } 1191 1192 /* 1193 * Copy a filedesc structure. 1194 */ 1195 struct filedesc * 1196 fdcopy(struct proc *p) 1197 { 1198 struct filedesc *newfdp, *fdp = p->p_fd; 1199 struct file **fpp; 1200 int i; 1201 1202 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0), 1203 M_FILEDESC, M_WAITOK); 1204 (void) memcpy(newfdp, fdp, sizeof(struct filedesc)); 1205 newfdp->fd_refcnt = 1; 1206 1207 VREF(newfdp->fd_cdir); 1208 if (newfdp->fd_rdir) 1209 VREF(newfdp->fd_rdir); 1210 1211 /* 1212 * If the number of open files fits in the internal arrays 1213 * of the open file structure, use them, otherwise allocate 1214 * additional memory for the number of descriptors currently 1215 * in use. 1216 */ 1217 if (newfdp->fd_lastfile < NDFILE) { 1218 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; 1219 newfdp->fd_ofileflags = 1220 ((struct filedesc0 *) newfdp)->fd_dfileflags; 1221 i = NDFILE; 1222 } else { 1223 /* 1224 * Compute the smallest multiple of NDEXTENT needed 1225 * for the file descriptors currently in use, 1226 * allowing the table to shrink. 1227 */ 1228 i = newfdp->fd_nfiles; 1229 while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2) 1230 i /= 2; 1231 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE, 1232 M_FILEDESC, M_WAITOK); 1233 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; 1234 } 1235 1236 newfdp->fd_nfiles = i; 1237 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file **)); 1238 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char)); 1239 fpp = newfdp->fd_ofiles; 1240 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++) 1241 if (*fpp != NULL) 1242 (*fpp)->f_count++; 1243 1244 return (newfdp); 1245 } 1246 1247 /* 1248 * Release a filedesc structure. 1249 */ 1250 void 1251 fdfree(struct proc *p) 1252 { 1253 register struct filedesc *fdp = p->p_fd; 1254 struct file **fpp; 1255 char *fdfp; 1256 register int i; 1257 1258 if (--fdp->fd_refcnt > 0) 1259 return; 1260 1261 fpp = fdp->fd_ofiles; 1262 fdfp = fdp->fd_ofileflags; 1263 for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++) 1264 if (*fpp != NULL) { 1265 if (*fdfp & UF_MAPPED) 1266 (void) munmapfd(p, i); 1267 (void) closef(*fpp, p); 1268 } 1269 1270 if (fdp->fd_nfiles > NDFILE) 1271 FREE(fdp->fd_ofiles, M_FILEDESC); 1272 1273 vrele(fdp->fd_cdir); 1274 if (fdp->fd_rdir) 1275 vrele(fdp->fd_rdir); 1276 1277 FREE(fdp, M_FILEDESC); 1278 } 1279 1280 /* Close any files on execve()? */ 1281 void 1282 fdcloseexec(struct proc *p) 1283 { 1284 struct filedesc *fdp = p->p_fd; 1285 struct file **fpp; 1286 char *fdfp; 1287 register int i; 1288 1289 fpp = fdp->fd_ofiles; 1290 fdfp = fdp->fd_ofileflags; 1291 for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++) 1292 if (*fpp != NULL && (*fdfp & UF_EXCLOSE)) { 1293 if (*fdfp & UF_MAPPED) 1294 (void) munmapfd(p, i); 1295 (void) closef(*fpp, p); 1296 *fpp = NULL; 1297 *fdfp = 0; 1298 if (i < fdp->fd_freefile) 1299 fdp->fd_freefile = i; 1300 } 1301 1302 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 1303 fdp->fd_lastfile--; 1304 } 1305 1306 /* 1307 * Private file close function. 1308 * Decrement reference count on file structure. 1309 */ 1310 int 1311 closef(struct file *fp, struct proc *p) 1312 { 1313 struct vnode *vp; 1314 struct flock lf; 1315 int error; 1316 1317 if (fp == NULL) 1318 return (0); 1319 /* 1320 * POSIX record locking dictates that any close releases ALL 1321 * locks owned by this process. This is handled by setting 1322 * a flag in the unlock to free ONLY locks obeying POSIX 1323 * semantics, and not to free BSD-style file locks. 1324 */ 1325 if ((p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) { 1326 lf.l_whence = SEEK_SET; 1327 lf.l_start = 0; 1328 lf.l_len = 0; 1329 lf.l_type = F_UNLCK; 1330 vp = (struct vnode *)fp->f_data; 1331 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX); 1332 } 1333 if (--fp->f_count > 0) 1334 return (0); 1335 1336 #ifdef DIAGNOSTIC 1337 if (fp->f_count < 0) 1338 panic("closef: count < 0"); 1339 #endif 1340 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) { 1341 lf.l_whence = SEEK_SET; 1342 lf.l_start = 0; 1343 lf.l_len = 0; 1344 lf.l_type = F_UNLCK; 1345 vp = (struct vnode *)fp->f_data; 1346 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); 1347 } 1348 1349 error = (*fp->f_ops->fo_close)(fp, p); 1350 ffree(fp); 1351 return (error); 1352 } 1353 1354 /* 1355 * Apply an advisory lock on a file descriptor. 1356 * 1357 * Just attempt to get a record lock of the requested type on 1358 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 1359 */ 1360 1361 /* ARGSUSED */ 1362 int 1363 flock(p, uap, retval) 1364 struct proc *p; 1365 struct args { 1366 int fd; 1367 int how; 1368 } *uap; 1369 int *retval; 1370 { 1371 register struct filedesc *fdp = p->p_fd; 1372 register struct file *fp; 1373 struct vnode *vp; 1374 struct flock lf; 1375 int error; 1376 1377 if ((unsigned)uap->fd >= fdp->fd_nfiles || 1378 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 1379 return (EBADF); 1380 if (fp->f_type != DTYPE_VNODE) 1381 return (EOPNOTSUPP); 1382 1383 vp = (struct vnode *)fp->f_data; 1384 lf.l_whence = SEEK_SET; 1385 lf.l_start = 0; 1386 lf.l_len = 0; 1387 1388 if (uap->how & LOCK_UN) { 1389 lf.l_type = F_UNLCK; 1390 fp->f_flag &= ~FHASLOCK; 1391 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK)); 1392 } 1393 1394 if (uap->how & LOCK_EX) 1395 lf.l_type = F_WRLCK; 1396 else if (uap->how & LOCK_SH) 1397 lf.l_type = F_RDLCK; 1398 else 1399 return (EBADF); 1400 1401 fp->f_flag |= FHASLOCK; 1402 if (uap->how & LOCK_NB) 1403 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK)); 1404 1405 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); 1406 } 1407 1408 /* 1409 * File Descriptor pseudo-device driver (/dev/fd/). 1410 * 1411 * Opening minor device N dup()s the file (if any) connected to file 1412 * descriptor N belonging to the calling process. Note that this driver 1413 * consists of only the ``open()'' routine, because all subsequent 1414 * references to this file will be directed to the other file. 1415 */ 1416 /* ARGSUSED */ 1417 static int 1418 fdopen(dev_t dev, int mode, int type, struct proc *p) 1419 { 1420 1421 /* 1422 * XXX Kludge: set curproc->p_dupfd to contain the value of the 1423 * the file descriptor being sought for duplication. The error 1424 * return ensures that the vnode for this device will be released 1425 * by vn_open. Open will detect this special error and take the 1426 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 1427 * will simply report the error. 1428 */ 1429 p->p_dupfd = minor(dev); /* XXX */ 1430 return (ENODEV); 1431 } 1432 1433 static struct devif fd_devif = 1434 { 1435 {0}, -1, -2, 0, 0, 0, 0, 0, 0, 1436 fdopen, 0, 0, 0, 0, 0, 0, 1437 0, 0, 0, 0, 1438 0, 0, 1439 }; 1440 1441 DRIVER_MODCONFIG() { 1442 char *cfg_string = "fdesc 53."; 1443 1444 if (devif_config(&cfg_string, &fd_devif) == 0) 1445 return; 1446 } 1447 1448 /* 1449 * Duplicate the specified descriptor to a free descriptor. 1450 */ 1451 int 1452 dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode) 1453 { 1454 register struct file *wfp; 1455 struct file *fp; 1456 1457 /* 1458 * If the to-be-dup'd fd number is greater than the allowed number 1459 * of file descriptors, or the fd to be dup'd has already been 1460 * closed, reject. Note, check for new == old is necessary as 1461 * falloc could allocate an already closed to-be-dup'd descriptor 1462 * as the new descriptor. 1463 */ 1464 fp = fdp->fd_ofiles[indx]; 1465 if ((u_int)dfd >= fdp->fd_nfiles || 1466 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp) 1467 return (EBADF); 1468 1469 /* 1470 * Check that the mode the file is being opened for is a subset 1471 * of the mode of the existing descriptor. 1472 */ 1473 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 1474 return (EACCES); 1475 fdp->fd_ofiles[indx] = wfp; 1476 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 1477 wfp->f_count++; 1478 if (indx > fdp->fd_lastfile) 1479 fdp->fd_lastfile = indx; 1480 return (0); 1481 } 1482