1 /* $NetBSD: kern_descrip.c,v 1.43 1997/04/02 18:22:32 kleink 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(u_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(u_int) from; 147 syscallarg(u_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_fstat(p, v, retval) 399 struct proc *p; 400 void *v; 401 register_t *retval; 402 { 403 register struct sys_fstat_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((caddr_t)&ub, (caddr_t)SCARG(uap, sb), 432 sizeof (ub)); 433 return (error); 434 } 435 436 /* 437 * Return pathconf information about a file descriptor. 438 */ 439 /* ARGSUSED */ 440 int 441 sys_fpathconf(p, v, retval) 442 struct proc *p; 443 void *v; 444 register_t *retval; 445 { 446 register struct sys_fpathconf_args /* { 447 syscallarg(int) fd; 448 syscallarg(int) name; 449 } */ *uap = v; 450 int fd = SCARG(uap, fd); 451 struct filedesc *fdp = p->p_fd; 452 struct file *fp; 453 struct vnode *vp; 454 455 if ((u_int)fd >= fdp->fd_nfiles || 456 (fp = fdp->fd_ofiles[fd]) == NULL) 457 return (EBADF); 458 switch (fp->f_type) { 459 460 case DTYPE_SOCKET: 461 if (SCARG(uap, name) != _PC_PIPE_BUF) 462 return (EINVAL); 463 *retval = PIPE_BUF; 464 return (0); 465 466 case DTYPE_VNODE: 467 vp = (struct vnode *)fp->f_data; 468 return (VOP_PATHCONF(vp, SCARG(uap, name), retval)); 469 470 default: 471 panic("fpathconf"); 472 } 473 /*NOTREACHED*/ 474 } 475 476 /* 477 * Allocate a file descriptor for the process. 478 */ 479 int fdexpand; 480 481 int 482 fdalloc(p, want, result) 483 struct proc *p; 484 int want; 485 int *result; 486 { 487 register struct filedesc *fdp = p->p_fd; 488 register int i; 489 int lim, last, nfiles; 490 struct file **newofile; 491 char *newofileflags; 492 493 /* 494 * Search for a free descriptor starting at the higher 495 * of want or fd_freefile. If that fails, consider 496 * expanding the ofile array. 497 */ 498 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); 499 for (;;) { 500 last = min(fdp->fd_nfiles, lim); 501 if ((i = want) < fdp->fd_freefile) 502 i = fdp->fd_freefile; 503 for (; i < last; i++) { 504 if (fdp->fd_ofiles[i] == NULL) { 505 fd_used(fdp, i); 506 if (want <= fdp->fd_freefile) 507 fdp->fd_freefile = i; 508 *result = i; 509 return (0); 510 } 511 } 512 513 /* 514 * No space in current array. Expand? 515 */ 516 if (fdp->fd_nfiles >= lim) 517 return (EMFILE); 518 if (fdp->fd_nfiles < NDEXTENT) 519 nfiles = NDEXTENT; 520 else 521 nfiles = 2 * fdp->fd_nfiles; 522 MALLOC(newofile, struct file **, nfiles * OFILESIZE, 523 M_FILEDESC, M_WAITOK); 524 newofileflags = (char *) &newofile[nfiles]; 525 /* 526 * Copy the existing ofile and ofileflags arrays 527 * and zero the new portion of each array. 528 */ 529 bcopy(fdp->fd_ofiles, newofile, 530 (i = sizeof(struct file *) * fdp->fd_nfiles)); 531 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i); 532 bcopy(fdp->fd_ofileflags, newofileflags, 533 (i = sizeof(char) * fdp->fd_nfiles)); 534 bzero(newofileflags + i, nfiles * sizeof(char) - i); 535 if (fdp->fd_nfiles > NDFILE) 536 FREE(fdp->fd_ofiles, M_FILEDESC); 537 fdp->fd_ofiles = newofile; 538 fdp->fd_ofileflags = newofileflags; 539 fdp->fd_nfiles = nfiles; 540 fdexpand++; 541 } 542 } 543 544 /* 545 * Check to see whether n user file descriptors 546 * are available to the process p. 547 */ 548 int 549 fdavail(p, n) 550 struct proc *p; 551 register int n; 552 { 553 register struct filedesc *fdp = p->p_fd; 554 register struct file **fpp; 555 register int i, lim; 556 557 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); 558 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0) 559 return (1); 560 fpp = &fdp->fd_ofiles[fdp->fd_freefile]; 561 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++) 562 if (*fpp == NULL && --n <= 0) 563 return (1); 564 return (0); 565 } 566 567 /* 568 * Create a new open file structure and allocate 569 * a file decriptor for the process that refers to it. 570 */ 571 int 572 falloc(p, resultfp, resultfd) 573 register struct proc *p; 574 struct file **resultfp; 575 int *resultfd; 576 { 577 register struct file *fp, *fq; 578 int error, i; 579 580 if ((error = fdalloc(p, 0, &i)) != 0) 581 return (error); 582 if (nfiles >= maxfiles) { 583 tablefull("file"); 584 return (ENFILE); 585 } 586 /* 587 * Allocate a new file descriptor. 588 * If the process has file descriptor zero open, add to the list 589 * of open files at that point, otherwise put it at the front of 590 * the list of open files. 591 */ 592 nfiles++; 593 MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); 594 bzero(fp, sizeof(struct file)); 595 if ((fq = p->p_fd->fd_ofiles[0]) != NULL) { 596 LIST_INSERT_AFTER(fq, fp, f_list); 597 } else { 598 LIST_INSERT_HEAD(&filehead, fp, f_list); 599 } 600 p->p_fd->fd_ofiles[i] = fp; 601 fp->f_count = 1; 602 fp->f_cred = p->p_ucred; 603 crhold(fp->f_cred); 604 if (resultfp) 605 *resultfp = fp; 606 if (resultfd) 607 *resultfd = i; 608 return (0); 609 } 610 611 /* 612 * Free a file descriptor. 613 */ 614 void 615 ffree(fp) 616 register struct file *fp; 617 { 618 LIST_REMOVE(fp, f_list); 619 crfree(fp->f_cred); 620 #ifdef DIAGNOSTIC 621 fp->f_count = 0; 622 #endif 623 nfiles--; 624 FREE(fp, M_FILE); 625 } 626 627 /* 628 * Copy a filedesc structure. 629 */ 630 struct filedesc * 631 fdcopy(p) 632 struct proc *p; 633 { 634 register struct filedesc *newfdp, *fdp = p->p_fd; 635 register struct file **fpp; 636 register int i; 637 638 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0), 639 M_FILEDESC, M_WAITOK); 640 bcopy(fdp, newfdp, sizeof(struct filedesc)); 641 VREF(newfdp->fd_cdir); 642 if (newfdp->fd_rdir) 643 VREF(newfdp->fd_rdir); 644 newfdp->fd_refcnt = 1; 645 646 /* 647 * If the number of open files fits in the internal arrays 648 * of the open file structure, use them, otherwise allocate 649 * additional memory for the number of descriptors currently 650 * in use. 651 */ 652 if (newfdp->fd_lastfile < NDFILE) { 653 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; 654 newfdp->fd_ofileflags = 655 ((struct filedesc0 *) newfdp)->fd_dfileflags; 656 i = NDFILE; 657 } else { 658 /* 659 * Compute the smallest multiple of NDEXTENT needed 660 * for the file descriptors currently in use, 661 * allowing the table to shrink. 662 */ 663 i = newfdp->fd_nfiles; 664 while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2) 665 i /= 2; 666 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE, 667 M_FILEDESC, M_WAITOK); 668 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; 669 } 670 newfdp->fd_nfiles = i; 671 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **)); 672 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char)); 673 fpp = newfdp->fd_ofiles; 674 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp++) 675 if (*fpp != NULL) 676 (*fpp)->f_count++; 677 return (newfdp); 678 } 679 680 /* 681 * Release a filedesc structure. 682 */ 683 void 684 fdfree(p) 685 struct proc *p; 686 { 687 register struct filedesc *fdp = p->p_fd; 688 register struct file **fpp, *fp; 689 register int i; 690 691 if (--fdp->fd_refcnt > 0) 692 return; 693 fpp = fdp->fd_ofiles; 694 for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) { 695 fp = *fpp; 696 if (fp != NULL) { 697 *fpp = NULL; 698 (void) closef(fp, p); 699 } 700 } 701 p->p_fd = NULL; 702 if (fdp->fd_nfiles > NDFILE) 703 FREE(fdp->fd_ofiles, M_FILEDESC); 704 vrele(fdp->fd_cdir); 705 if (fdp->fd_rdir) 706 vrele(fdp->fd_rdir); 707 FREE(fdp, M_FILEDESC); 708 } 709 710 /* 711 * Internal form of close. 712 * Decrement reference count on file structure. 713 * Note: p may be NULL when closing a file 714 * that was being passed in a message. 715 */ 716 int 717 closef(fp, p) 718 register struct file *fp; 719 register struct proc *p; 720 { 721 struct vnode *vp; 722 struct flock lf; 723 int error; 724 725 if (fp == NULL) 726 return (0); 727 /* 728 * POSIX record locking dictates that any close releases ALL 729 * locks owned by this process. This is handled by setting 730 * a flag in the unlock to free ONLY locks obeying POSIX 731 * semantics, and not to free BSD-style file locks. 732 * If the descriptor was in a message, POSIX-style locks 733 * aren't passed with the descriptor. 734 */ 735 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) { 736 lf.l_whence = SEEK_SET; 737 lf.l_start = 0; 738 lf.l_len = 0; 739 lf.l_type = F_UNLCK; 740 vp = (struct vnode *)fp->f_data; 741 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX); 742 } 743 if (--fp->f_count > 0) 744 return (0); 745 if (fp->f_count < 0) 746 panic("closef: count < 0"); 747 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) { 748 lf.l_whence = SEEK_SET; 749 lf.l_start = 0; 750 lf.l_len = 0; 751 lf.l_type = F_UNLCK; 752 vp = (struct vnode *)fp->f_data; 753 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); 754 } 755 if (fp->f_ops) 756 error = (*fp->f_ops->fo_close)(fp, p); 757 else 758 error = 0; 759 ffree(fp); 760 return (error); 761 } 762 763 /* 764 * Apply an advisory lock on a file descriptor. 765 * 766 * Just attempt to get a record lock of the requested type on 767 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 768 */ 769 /* ARGSUSED */ 770 int 771 sys_flock(p, v, retval) 772 struct proc *p; 773 void *v; 774 register_t *retval; 775 { 776 register struct sys_flock_args /* { 777 syscallarg(int) fd; 778 syscallarg(int) how; 779 } */ *uap = v; 780 int fd = SCARG(uap, fd); 781 int how = SCARG(uap, how); 782 register struct filedesc *fdp = p->p_fd; 783 register struct file *fp; 784 struct vnode *vp; 785 struct flock lf; 786 787 if ((u_int)fd >= fdp->fd_nfiles || 788 (fp = fdp->fd_ofiles[fd]) == NULL) 789 return (EBADF); 790 if (fp->f_type != DTYPE_VNODE) 791 return (EOPNOTSUPP); 792 vp = (struct vnode *)fp->f_data; 793 lf.l_whence = SEEK_SET; 794 lf.l_start = 0; 795 lf.l_len = 0; 796 if (how & LOCK_UN) { 797 lf.l_type = F_UNLCK; 798 fp->f_flag &= ~FHASLOCK; 799 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK)); 800 } 801 if (how & LOCK_EX) 802 lf.l_type = F_WRLCK; 803 else if (how & LOCK_SH) 804 lf.l_type = F_RDLCK; 805 else 806 return (EBADF); 807 fp->f_flag |= FHASLOCK; 808 if (how & LOCK_NB) 809 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK)); 810 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); 811 } 812 813 /* 814 * File Descriptor pseudo-device driver (/dev/fd/). 815 * 816 * Opening minor device N dup()s the file (if any) connected to file 817 * descriptor N belonging to the calling process. Note that this driver 818 * consists of only the ``open()'' routine, because all subsequent 819 * references to this file will be direct to the other driver. 820 */ 821 /* ARGSUSED */ 822 int 823 filedescopen(dev, mode, type, p) 824 dev_t dev; 825 int mode, type; 826 struct proc *p; 827 { 828 829 /* 830 * XXX Kludge: set curproc->p_dupfd to contain the value of the 831 * the file descriptor being sought for duplication. The error 832 * return ensures that the vnode for this device will be released 833 * by vn_open. Open will detect this special error and take the 834 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 835 * will simply report the error. 836 */ 837 p->p_dupfd = minor(dev); 838 return (ENODEV); 839 } 840 841 /* 842 * Duplicate the specified descriptor to a free descriptor. 843 */ 844 int 845 dupfdopen(fdp, indx, dfd, mode, error) 846 register struct filedesc *fdp; 847 register int indx, dfd; 848 int mode; 849 int error; 850 { 851 register struct file *wfp; 852 struct file *fp; 853 854 /* 855 * If the to-be-dup'd fd number is greater than the allowed number 856 * of file descriptors, or the fd to be dup'd has already been 857 * closed, reject. Note, check for new == old is necessary as 858 * falloc could allocate an already closed to-be-dup'd descriptor 859 * as the new descriptor. 860 */ 861 fp = fdp->fd_ofiles[indx]; 862 if ((u_int)dfd >= fdp->fd_nfiles || 863 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp) 864 return (EBADF); 865 866 /* 867 * There are two cases of interest here. 868 * 869 * For ENODEV simply dup (dfd) to file descriptor 870 * (indx) and return. 871 * 872 * For ENXIO steal away the file structure from (dfd) and 873 * store it in (indx). (dfd) is effectively closed by 874 * this operation. 875 * 876 * Any other error code is just returned. 877 */ 878 switch (error) { 879 case ENODEV: 880 /* 881 * Check that the mode the file is being opened for is a 882 * subset of the mode of the existing descriptor. 883 */ 884 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 885 return (EACCES); 886 fdp->fd_ofiles[indx] = wfp; 887 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 888 wfp->f_count++; 889 fd_used(fdp, indx); 890 return (0); 891 892 case ENXIO: 893 /* 894 * Steal away the file pointer from dfd, and stuff it into indx. 895 */ 896 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd]; 897 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 898 fdp->fd_ofiles[dfd] = NULL; 899 fdp->fd_ofileflags[dfd] = 0; 900 /* 901 * Complete the clean up of the filedesc structure by 902 * recomputing the various hints. 903 */ 904 fd_used(fdp, indx); 905 fd_unused(fdp, dfd); 906 return (0); 907 908 default: 909 return (error); 910 } 911 /* NOTREACHED */ 912 } 913 914 /* 915 * Close any files on exec? 916 */ 917 void 918 fdcloseexec(p) 919 struct proc *p; 920 { 921 register struct filedesc *fdp = p->p_fd; 922 register int fd; 923 924 for (fd = 0; fd <= fdp->fd_lastfile; fd++) 925 if (fdp->fd_ofileflags[fd] & UF_EXCLOSE) 926 (void) fdrelease(p, fd); 927 } 928