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