1 /* $NetBSD: kern_descrip.c,v 1.48 1998/01/05 04:51:16 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/filedesc.h> 46 #include <sys/kernel.h> 47 #include <sys/vnode.h> 48 #include <sys/proc.h> 49 #include <sys/file.h> 50 #include <sys/socket.h> 51 #include <sys/socketvar.h> 52 #include <sys/stat.h> 53 #include <sys/ioctl.h> 54 #include <sys/fcntl.h> 55 #include <sys/malloc.h> 56 #include <sys/syslog.h> 57 #include <sys/unistd.h> 58 #include <sys/resourcevar.h> 59 #include <sys/conf.h> 60 61 #include <sys/mount.h> 62 #include <sys/syscallargs.h> 63 64 #include <vm/vm.h> 65 66 /* 67 * Descriptor management. 68 */ 69 struct filelist filehead; /* head of list of open files */ 70 int nfiles; /* actual number of open files */ 71 72 static __inline void fd_used __P((struct filedesc *, int)); 73 static __inline void fd_unused __P((struct filedesc *, int)); 74 int finishdup __P((struct filedesc *, int, int, register_t *)); 75 76 static __inline void 77 fd_used(fdp, fd) 78 register struct filedesc *fdp; 79 register int fd; 80 { 81 82 if (fd > fdp->fd_lastfile) 83 fdp->fd_lastfile = fd; 84 } 85 86 static __inline void 87 fd_unused(fdp, fd) 88 register struct filedesc *fdp; 89 register int fd; 90 { 91 92 if (fd < fdp->fd_freefile) 93 fdp->fd_freefile = fd; 94 #ifdef DIAGNOSTIC 95 if (fd > fdp->fd_lastfile) 96 panic("fd_unused: fd_lastfile inconsistent"); 97 #endif 98 if (fd == fdp->fd_lastfile) { 99 do { 100 fd--; 101 } while (fd >= 0 && fdp->fd_ofiles[fd] == NULL); 102 fdp->fd_lastfile = fd; 103 } 104 } 105 106 /* 107 * System calls on descriptors. 108 */ 109 110 /* 111 * Duplicate a file descriptor. 112 */ 113 /* ARGSUSED */ 114 int 115 sys_dup(p, v, retval) 116 struct proc *p; 117 void *v; 118 register_t *retval; 119 { 120 struct sys_dup_args /* { 121 syscallarg(int) fd; 122 } */ *uap = v; 123 register struct filedesc *fdp = p->p_fd; 124 register int old = SCARG(uap, fd); 125 int new; 126 int error; 127 128 if ((u_int)old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL) 129 return (EBADF); 130 if ((error = fdalloc(p, 0, &new)) != 0) 131 return (error); 132 return (finishdup(fdp, old, new, retval)); 133 } 134 135 /* 136 * Duplicate a file descriptor to a particular value. 137 */ 138 /* ARGSUSED */ 139 int 140 sys_dup2(p, v, retval) 141 struct proc *p; 142 void *v; 143 register_t *retval; 144 { 145 struct sys_dup2_args /* { 146 syscallarg(int) from; 147 syscallarg(int) to; 148 } */ *uap = v; 149 register struct filedesc *fdp = p->p_fd; 150 register int old = SCARG(uap, from), new = SCARG(uap, to); 151 int i, error; 152 153 if ((u_int)old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL || 154 (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || 155 (u_int)new >= maxfiles) 156 return (EBADF); 157 if (old == new) { 158 *retval = new; 159 return (0); 160 } 161 if (new >= fdp->fd_nfiles) { 162 if ((error = fdalloc(p, new, &i)) != 0) 163 return (error); 164 if (new != i) 165 panic("dup2: fdalloc"); 166 } else { 167 (void) fdrelease(p, new); 168 } 169 return (finishdup(fdp, old, new, retval)); 170 } 171 172 /* 173 * The file control system call. 174 */ 175 /* ARGSUSED */ 176 int 177 sys_fcntl(p, v, retval) 178 struct proc *p; 179 void *v; 180 register_t *retval; 181 { 182 register struct sys_fcntl_args /* { 183 syscallarg(int) fd; 184 syscallarg(int) cmd; 185 syscallarg(void *) arg; 186 } */ *uap = v; 187 int fd = SCARG(uap, fd); 188 register struct filedesc *fdp = p->p_fd; 189 register struct file *fp; 190 struct vnode *vp; 191 int i, tmp, error, flg = F_POSIX; 192 struct flock fl; 193 int newmin; 194 195 if ((u_int)fd >= fdp->fd_nfiles || 196 (fp = fdp->fd_ofiles[fd]) == NULL) 197 return (EBADF); 198 switch (SCARG(uap, cmd)) { 199 200 case F_DUPFD: 201 newmin = (long)SCARG(uap, arg); 202 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || 203 (u_int)newmin >= maxfiles) 204 return (EINVAL); 205 if ((error = fdalloc(p, newmin, &i)) != 0) 206 return (error); 207 return (finishdup(fdp, fd, i, retval)); 208 209 case F_GETFD: 210 *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0; 211 return (0); 212 213 case F_SETFD: 214 if ((long)SCARG(uap, arg) & 1) 215 fdp->fd_ofileflags[fd] |= UF_EXCLOSE; 216 else 217 fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE; 218 return (0); 219 220 case F_GETFL: 221 *retval = OFLAGS(fp->f_flag); 222 return (0); 223 224 case F_SETFL: 225 fp->f_flag &= ~FCNTLFLAGS; 226 fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS; 227 tmp = fp->f_flag & FNONBLOCK; 228 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 229 if (error) 230 return (error); 231 tmp = fp->f_flag & FASYNC; 232 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 233 if (!error) 234 return (0); 235 fp->f_flag &= ~FNONBLOCK; 236 tmp = 0; 237 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 238 return (error); 239 240 case F_GETOWN: 241 if (fp->f_type == DTYPE_SOCKET) { 242 *retval = ((struct socket *)fp->f_data)->so_pgid; 243 return (0); 244 } 245 error = (*fp->f_ops->fo_ioctl) 246 (fp, TIOCGPGRP, (caddr_t)retval, p); 247 *retval = -*retval; 248 return (error); 249 250 case F_SETOWN: 251 if (fp->f_type == DTYPE_SOCKET) { 252 ((struct socket *)fp->f_data)->so_pgid = 253 (long)SCARG(uap, arg); 254 return (0); 255 } 256 if ((long)SCARG(uap, arg) <= 0) { 257 SCARG(uap, arg) = (void *)(-(long)SCARG(uap, arg)); 258 } else { 259 struct proc *p1 = pfind((long)SCARG(uap, arg)); 260 if (p1 == 0) 261 return (ESRCH); 262 SCARG(uap, arg) = (void *)(long)p1->p_pgrp->pg_id; 263 } 264 return ((*fp->f_ops->fo_ioctl) 265 (fp, TIOCSPGRP, (caddr_t)&SCARG(uap, arg), p)); 266 267 case F_SETLKW: 268 flg |= F_WAIT; 269 /* Fall into F_SETLK */ 270 271 case F_SETLK: 272 if (fp->f_type != DTYPE_VNODE) 273 return (EBADF); 274 vp = (struct vnode *)fp->f_data; 275 /* Copy in the lock structure */ 276 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, 277 sizeof (fl)); 278 if (error) 279 return (error); 280 if (fl.l_whence == SEEK_CUR) 281 fl.l_start += fp->f_offset; 282 switch (fl.l_type) { 283 case F_RDLCK: 284 if ((fp->f_flag & FREAD) == 0) 285 return (EBADF); 286 p->p_flag |= P_ADVLOCK; 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 |= P_ADVLOCK; 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 /* Copy in the lock structure */ 308 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, 309 sizeof (fl)); 310 if (error) 311 return (error); 312 if (fl.l_whence == SEEK_CUR) 313 fl.l_start += fp->f_offset; 314 if (fl.l_type != F_RDLCK && 315 fl.l_type != F_WRLCK && 316 fl.l_type != F_UNLCK) 317 return (EINVAL); 318 error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX); 319 if (error) 320 return (error); 321 return (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg), 322 sizeof (fl))); 323 324 default: 325 return (EINVAL); 326 } 327 /* NOTREACHED */ 328 } 329 330 /* 331 * Common code for dup, dup2, and fcntl(F_DUPFD). 332 */ 333 int 334 finishdup(fdp, old, new, retval) 335 register struct filedesc *fdp; 336 register int old, new; 337 register_t *retval; 338 { 339 register struct file *fp; 340 341 fp = fdp->fd_ofiles[old]; 342 fdp->fd_ofiles[new] = fp; 343 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE; 344 fp->f_count++; 345 fd_used(fdp, new); 346 *retval = new; 347 return (0); 348 } 349 350 int 351 fdrelease(p, fd) 352 struct proc *p; 353 int fd; 354 { 355 register struct filedesc *fdp = p->p_fd; 356 register struct file **fpp, *fp; 357 register char *pf; 358 359 fpp = &fdp->fd_ofiles[fd]; 360 fp = *fpp; 361 if (fp == NULL) 362 return (EBADF); 363 pf = &fdp->fd_ofileflags[fd]; 364 if (*pf & UF_MAPPED) 365 (void) munmapfd(p, fd); 366 *fpp = NULL; 367 *pf = 0; 368 fd_unused(fdp, fd); 369 return (closef(fp, p)); 370 } 371 372 /* 373 * Close a file descriptor. 374 */ 375 /* ARGSUSED */ 376 int 377 sys_close(p, v, retval) 378 struct proc *p; 379 void *v; 380 register_t *retval; 381 { 382 struct sys_close_args /* { 383 syscallarg(int) fd; 384 } */ *uap = v; 385 int fd = SCARG(uap, fd); 386 register struct filedesc *fdp = p->p_fd; 387 388 if ((u_int)fd >= fdp->fd_nfiles) 389 return (EBADF); 390 return (fdrelease(p, fd)); 391 } 392 393 /* 394 * Return status information about a file descriptor. 395 */ 396 /* ARGSUSED */ 397 int 398 sys___fstat13(p, v, retval) 399 struct proc *p; 400 void *v; 401 register_t *retval; 402 { 403 register struct sys___fstat13_args /* { 404 syscallarg(int) fd; 405 syscallarg(struct stat *) sb; 406 } */ *uap = v; 407 int fd = SCARG(uap, fd); 408 register struct filedesc *fdp = p->p_fd; 409 register struct file *fp; 410 struct stat ub; 411 int error; 412 413 if ((u_int)fd >= fdp->fd_nfiles || 414 (fp = fdp->fd_ofiles[fd]) == NULL) 415 return (EBADF); 416 switch (fp->f_type) { 417 418 case DTYPE_VNODE: 419 error = vn_stat((struct vnode *)fp->f_data, &ub, p); 420 break; 421 422 case DTYPE_SOCKET: 423 error = soo_stat((struct socket *)fp->f_data, &ub); 424 break; 425 426 default: 427 panic("fstat"); 428 /*NOTREACHED*/ 429 } 430 if (error == 0) 431 error = copyout(&ub, SCARG(uap, sb), sizeof (ub)); 432 return (error); 433 } 434 435 /* 436 * Return pathconf information about a file descriptor. 437 */ 438 /* ARGSUSED */ 439 int 440 sys_fpathconf(p, v, retval) 441 struct proc *p; 442 void *v; 443 register_t *retval; 444 { 445 register struct sys_fpathconf_args /* { 446 syscallarg(int) fd; 447 syscallarg(int) name; 448 } */ *uap = v; 449 int fd = SCARG(uap, fd); 450 struct filedesc *fdp = p->p_fd; 451 struct file *fp; 452 struct vnode *vp; 453 454 if ((u_int)fd >= fdp->fd_nfiles || 455 (fp = fdp->fd_ofiles[fd]) == NULL) 456 return (EBADF); 457 switch (fp->f_type) { 458 459 case DTYPE_SOCKET: 460 if (SCARG(uap, name) != _PC_PIPE_BUF) 461 return (EINVAL); 462 *retval = PIPE_BUF; 463 return (0); 464 465 case DTYPE_VNODE: 466 vp = (struct vnode *)fp->f_data; 467 return (VOP_PATHCONF(vp, SCARG(uap, name), retval)); 468 469 default: 470 panic("fpathconf"); 471 } 472 /*NOTREACHED*/ 473 } 474 475 /* 476 * Allocate a file descriptor for the process. 477 */ 478 int fdexpand; 479 480 int 481 fdalloc(p, want, result) 482 struct proc *p; 483 int want; 484 int *result; 485 { 486 register struct filedesc *fdp = p->p_fd; 487 register int i; 488 int lim, last, nfiles; 489 struct file **newofile; 490 char *newofileflags; 491 492 /* 493 * Search for a free descriptor starting at the higher 494 * of want or fd_freefile. If that fails, consider 495 * expanding the ofile array. 496 */ 497 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); 498 for (;;) { 499 last = min(fdp->fd_nfiles, lim); 500 if ((i = want) < fdp->fd_freefile) 501 i = fdp->fd_freefile; 502 for (; i < last; i++) { 503 if (fdp->fd_ofiles[i] == NULL) { 504 fd_used(fdp, i); 505 if (want <= fdp->fd_freefile) 506 fdp->fd_freefile = i; 507 *result = i; 508 return (0); 509 } 510 } 511 512 /* 513 * No space in current array. Expand? 514 */ 515 if (fdp->fd_nfiles >= lim) 516 return (EMFILE); 517 if (fdp->fd_nfiles < NDEXTENT) 518 nfiles = NDEXTENT; 519 else 520 nfiles = 2 * fdp->fd_nfiles; 521 MALLOC(newofile, struct file **, nfiles * OFILESIZE, 522 M_FILEDESC, M_WAITOK); 523 newofileflags = (char *) &newofile[nfiles]; 524 /* 525 * Copy the existing ofile and ofileflags arrays 526 * and zero the new portion of each array. 527 */ 528 bcopy(fdp->fd_ofiles, newofile, 529 (i = sizeof(struct file *) * fdp->fd_nfiles)); 530 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i); 531 bcopy(fdp->fd_ofileflags, newofileflags, 532 (i = sizeof(char) * fdp->fd_nfiles)); 533 bzero(newofileflags + i, nfiles * sizeof(char) - i); 534 if (fdp->fd_nfiles > NDFILE) 535 FREE(fdp->fd_ofiles, M_FILEDESC); 536 fdp->fd_ofiles = newofile; 537 fdp->fd_ofileflags = newofileflags; 538 fdp->fd_nfiles = nfiles; 539 fdexpand++; 540 } 541 } 542 543 /* 544 * Check to see whether n user file descriptors 545 * are available to the process p. 546 */ 547 int 548 fdavail(p, n) 549 struct proc *p; 550 register int n; 551 { 552 register struct filedesc *fdp = p->p_fd; 553 register struct file **fpp; 554 register int i, lim; 555 556 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); 557 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0) 558 return (1); 559 fpp = &fdp->fd_ofiles[fdp->fd_freefile]; 560 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++) 561 if (*fpp == NULL && --n <= 0) 562 return (1); 563 return (0); 564 } 565 566 /* 567 * Create a new open file structure and allocate 568 * a file decriptor for the process that refers to it. 569 */ 570 int 571 falloc(p, resultfp, resultfd) 572 register struct proc *p; 573 struct file **resultfp; 574 int *resultfd; 575 { 576 register struct file *fp, *fq; 577 int error, i; 578 579 if ((error = fdalloc(p, 0, &i)) != 0) 580 return (error); 581 if (nfiles >= maxfiles) { 582 tablefull("file"); 583 return (ENFILE); 584 } 585 /* 586 * Allocate a new file descriptor. 587 * If the process has file descriptor zero open, add to the list 588 * of open files at that point, otherwise put it at the front of 589 * the list of open files. 590 */ 591 nfiles++; 592 MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); 593 bzero(fp, sizeof(struct file)); 594 if ((fq = p->p_fd->fd_ofiles[0]) != NULL) { 595 LIST_INSERT_AFTER(fq, fp, f_list); 596 } else { 597 LIST_INSERT_HEAD(&filehead, fp, f_list); 598 } 599 p->p_fd->fd_ofiles[i] = fp; 600 fp->f_count = 1; 601 fp->f_cred = p->p_ucred; 602 crhold(fp->f_cred); 603 if (resultfp) 604 *resultfp = fp; 605 if (resultfd) 606 *resultfd = i; 607 return (0); 608 } 609 610 /* 611 * Free a file descriptor. 612 */ 613 void 614 ffree(fp) 615 register struct file *fp; 616 { 617 LIST_REMOVE(fp, f_list); 618 crfree(fp->f_cred); 619 #ifdef DIAGNOSTIC 620 fp->f_count = 0; 621 #endif 622 nfiles--; 623 FREE(fp, M_FILE); 624 } 625 626 /* 627 * Create an initial filedesc structure, using the same current and root 628 * directories as p. 629 */ 630 struct filedesc * 631 fdinit(p) 632 struct proc *p; 633 { 634 struct filedesc0 *newfdp; 635 struct filedesc *fdp = p->p_fd; 636 637 MALLOC(newfdp, struct filedesc0 *, sizeof(struct filedesc0), 638 M_FILEDESC, M_WAITOK); 639 bzero(newfdp, sizeof(struct filedesc0)); 640 newfdp->fd_fd.fd_cdir = fdp->fd_cdir; 641 VREF(newfdp->fd_fd.fd_cdir); 642 newfdp->fd_fd.fd_rdir = fdp->fd_rdir; 643 if (newfdp->fd_fd.fd_rdir) 644 VREF(newfdp->fd_fd.fd_rdir); 645 646 fdinit1(newfdp); 647 648 return (&newfdp->fd_fd); 649 } 650 651 /* 652 * Initialize a file descriptor table. 653 */ 654 void 655 fdinit1(newfdp) 656 struct filedesc0 *newfdp; 657 { 658 extern int cmask; /* init_main.c */ 659 660 newfdp->fd_fd.fd_refcnt = 1; 661 newfdp->fd_fd.fd_cmask = cmask; 662 newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles; 663 newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags; 664 newfdp->fd_fd.fd_nfiles = NDFILE; 665 } 666 667 /* 668 * Make p2 share p1's filedesc structure. 669 */ 670 void 671 fdshare(p1, p2) 672 struct proc *p1, *p2; 673 { 674 675 p2->p_fd = p1->p_fd; 676 p1->p_fd->fd_refcnt++; 677 } 678 679 /* 680 * Make this process not share its filedesc structure, maintaining 681 * all file descriptor state. 682 */ 683 void 684 fdunshare(p) 685 struct proc *p; 686 { 687 struct filedesc *newfd; 688 689 if (p->p_fd->fd_refcnt == 1) 690 return; 691 692 newfd = fdcopy(p); 693 fdfree(p); 694 p->p_fd = newfd; 695 } 696 697 /* 698 * Clear a process's fd table. 699 */ 700 void 701 fdclear(p) 702 struct proc *p; 703 { 704 struct filedesc *newfd; 705 706 newfd = fdinit(p); 707 fdfree(p); 708 p->p_fd = newfd; 709 } 710 711 /* 712 * Copy a filedesc structure. 713 */ 714 struct filedesc * 715 fdcopy(p) 716 struct proc *p; 717 { 718 register struct filedesc *newfdp, *fdp = p->p_fd; 719 register struct file **fpp; 720 register int i; 721 722 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0), 723 M_FILEDESC, M_WAITOK); 724 bcopy(fdp, newfdp, sizeof(struct filedesc)); 725 VREF(newfdp->fd_cdir); 726 if (newfdp->fd_rdir) 727 VREF(newfdp->fd_rdir); 728 newfdp->fd_refcnt = 1; 729 730 /* 731 * If the number of open files fits in the internal arrays 732 * of the open file structure, use them, otherwise allocate 733 * additional memory for the number of descriptors currently 734 * in use. 735 */ 736 if (newfdp->fd_lastfile < NDFILE) { 737 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; 738 newfdp->fd_ofileflags = 739 ((struct filedesc0 *) newfdp)->fd_dfileflags; 740 i = NDFILE; 741 } else { 742 /* 743 * Compute the smallest multiple of NDEXTENT needed 744 * for the file descriptors currently in use, 745 * allowing the table to shrink. 746 */ 747 i = newfdp->fd_nfiles; 748 while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2) 749 i /= 2; 750 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE, 751 M_FILEDESC, M_WAITOK); 752 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; 753 } 754 newfdp->fd_nfiles = i; 755 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **)); 756 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char)); 757 fpp = newfdp->fd_ofiles; 758 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp++) 759 if (*fpp != NULL) 760 (*fpp)->f_count++; 761 return (newfdp); 762 } 763 764 /* 765 * Release a filedesc structure. 766 */ 767 void 768 fdfree(p) 769 struct proc *p; 770 { 771 register struct filedesc *fdp = p->p_fd; 772 register struct file **fpp, *fp; 773 register int i; 774 775 if (--fdp->fd_refcnt > 0) 776 return; 777 fpp = fdp->fd_ofiles; 778 for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) { 779 fp = *fpp; 780 if (fp != NULL) { 781 *fpp = NULL; 782 (void) closef(fp, p); 783 } 784 } 785 p->p_fd = NULL; 786 if (fdp->fd_nfiles > NDFILE) 787 FREE(fdp->fd_ofiles, M_FILEDESC); 788 vrele(fdp->fd_cdir); 789 if (fdp->fd_rdir) 790 vrele(fdp->fd_rdir); 791 FREE(fdp, M_FILEDESC); 792 } 793 794 /* 795 * Internal form of close. 796 * Decrement reference count on file structure. 797 * Note: p may be NULL when closing a file 798 * that was being passed in a message. 799 */ 800 int 801 closef(fp, p) 802 register struct file *fp; 803 register struct proc *p; 804 { 805 struct vnode *vp; 806 struct flock lf; 807 int error; 808 809 if (fp == NULL) 810 return (0); 811 /* 812 * POSIX record locking dictates that any close releases ALL 813 * locks owned by this process. This is handled by setting 814 * a flag in the unlock to free ONLY locks obeying POSIX 815 * semantics, and not to free BSD-style file locks. 816 * If the descriptor was in a message, POSIX-style locks 817 * aren't passed with the descriptor. 818 */ 819 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) { 820 lf.l_whence = SEEK_SET; 821 lf.l_start = 0; 822 lf.l_len = 0; 823 lf.l_type = F_UNLCK; 824 vp = (struct vnode *)fp->f_data; 825 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX); 826 } 827 if (--fp->f_count > 0) 828 return (0); 829 if (fp->f_count < 0) 830 panic("closef: count < 0"); 831 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) { 832 lf.l_whence = SEEK_SET; 833 lf.l_start = 0; 834 lf.l_len = 0; 835 lf.l_type = F_UNLCK; 836 vp = (struct vnode *)fp->f_data; 837 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); 838 } 839 if (fp->f_ops) 840 error = (*fp->f_ops->fo_close)(fp, p); 841 else 842 error = 0; 843 ffree(fp); 844 return (error); 845 } 846 847 /* 848 * Apply an advisory lock on a file descriptor. 849 * 850 * Just attempt to get a record lock of the requested type on 851 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 852 */ 853 /* ARGSUSED */ 854 int 855 sys_flock(p, v, retval) 856 struct proc *p; 857 void *v; 858 register_t *retval; 859 { 860 register struct sys_flock_args /* { 861 syscallarg(int) fd; 862 syscallarg(int) how; 863 } */ *uap = v; 864 int fd = SCARG(uap, fd); 865 int how = SCARG(uap, how); 866 register struct filedesc *fdp = p->p_fd; 867 register struct file *fp; 868 struct vnode *vp; 869 struct flock lf; 870 871 if ((u_int)fd >= fdp->fd_nfiles || 872 (fp = fdp->fd_ofiles[fd]) == NULL) 873 return (EBADF); 874 if (fp->f_type != DTYPE_VNODE) 875 return (EOPNOTSUPP); 876 vp = (struct vnode *)fp->f_data; 877 lf.l_whence = SEEK_SET; 878 lf.l_start = 0; 879 lf.l_len = 0; 880 if (how & LOCK_UN) { 881 lf.l_type = F_UNLCK; 882 fp->f_flag &= ~FHASLOCK; 883 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK)); 884 } 885 if (how & LOCK_EX) 886 lf.l_type = F_WRLCK; 887 else if (how & LOCK_SH) 888 lf.l_type = F_RDLCK; 889 else 890 return (EINVAL); 891 fp->f_flag |= FHASLOCK; 892 if (how & LOCK_NB) 893 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK)); 894 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); 895 } 896 897 /* 898 * File Descriptor pseudo-device driver (/dev/fd/). 899 * 900 * Opening minor device N dup()s the file (if any) connected to file 901 * descriptor N belonging to the calling process. Note that this driver 902 * consists of only the ``open()'' routine, because all subsequent 903 * references to this file will be direct to the other driver. 904 */ 905 /* ARGSUSED */ 906 int 907 filedescopen(dev, mode, type, p) 908 dev_t dev; 909 int mode, type; 910 struct proc *p; 911 { 912 913 /* 914 * XXX Kludge: set curproc->p_dupfd to contain the value of the 915 * the file descriptor being sought for duplication. The error 916 * return ensures that the vnode for this device will be released 917 * by vn_open. Open will detect this special error and take the 918 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 919 * will simply report the error. 920 */ 921 p->p_dupfd = minor(dev); 922 return (ENODEV); 923 } 924 925 /* 926 * Duplicate the specified descriptor to a free descriptor. 927 */ 928 int 929 dupfdopen(fdp, indx, dfd, mode, error) 930 register struct filedesc *fdp; 931 register int indx, dfd; 932 int mode; 933 int error; 934 { 935 register struct file *wfp; 936 struct file *fp; 937 938 /* 939 * If the to-be-dup'd fd number is greater than the allowed number 940 * of file descriptors, or the fd to be dup'd has already been 941 * closed, reject. Note, check for new == old is necessary as 942 * falloc could allocate an already closed to-be-dup'd descriptor 943 * as the new descriptor. 944 */ 945 fp = fdp->fd_ofiles[indx]; 946 if ((u_int)dfd >= fdp->fd_nfiles || 947 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp) 948 return (EBADF); 949 950 /* 951 * There are two cases of interest here. 952 * 953 * For ENODEV simply dup (dfd) to file descriptor 954 * (indx) and return. 955 * 956 * For ENXIO steal away the file structure from (dfd) and 957 * store it in (indx). (dfd) is effectively closed by 958 * this operation. 959 * 960 * Any other error code is just returned. 961 */ 962 switch (error) { 963 case ENODEV: 964 /* 965 * Check that the mode the file is being opened for is a 966 * subset of the mode of the existing descriptor. 967 */ 968 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 969 return (EACCES); 970 fdp->fd_ofiles[indx] = wfp; 971 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 972 wfp->f_count++; 973 fd_used(fdp, indx); 974 return (0); 975 976 case ENXIO: 977 /* 978 * Steal away the file pointer from dfd, and stuff it into indx. 979 */ 980 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd]; 981 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 982 fdp->fd_ofiles[dfd] = NULL; 983 fdp->fd_ofileflags[dfd] = 0; 984 /* 985 * Complete the clean up of the filedesc structure by 986 * recomputing the various hints. 987 */ 988 fd_used(fdp, indx); 989 fd_unused(fdp, dfd); 990 return (0); 991 992 default: 993 return (error); 994 } 995 /* NOTREACHED */ 996 } 997 998 /* 999 * Close any files on exec? 1000 */ 1001 void 1002 fdcloseexec(p) 1003 struct proc *p; 1004 { 1005 register struct filedesc *fdp = p->p_fd; 1006 register int fd; 1007 1008 for (fd = 0; fd <= fdp->fd_lastfile; fd++) 1009 if (fdp->fd_ofileflags[fd] & UF_EXCLOSE) 1010 (void) fdrelease(p, fd); 1011 } 1012