kern_descrip.c revision 12221
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.12 1995/10/21 08:38:09 davidg Exp $ 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/sysproto.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/unistd.h> 57#include <sys/resourcevar.h> 58 59int finishdup(struct filedesc *fdp, int old, int new, int *retval); 60/* 61 * Descriptor management. 62 */ 63struct file *filehead; /* head of list of open files */ 64int nfiles; /* actual number of open files */ 65 66/* 67 * System calls on descriptors. 68 */ 69#ifndef _SYS_SYSPROTO_H_ 70struct getdtablesize_args { 71 int dummy; 72}; 73#endif 74/* ARGSUSED */ 75int 76getdtablesize(p, uap, retval) 77 struct proc *p; 78 struct getdtablesize_args *uap; 79 int *retval; 80{ 81 82 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc); 83 return (0); 84} 85 86/* 87 * Duplicate a file descriptor to a particular value. 88 */ 89#ifndef _SYS_SYSPROTO_H_ 90struct dup2_args { 91 u_int from; 92 u_int to; 93}; 94#endif 95/* ARGSUSED */ 96int 97dup2(p, uap, retval) 98 struct proc *p; 99 struct dup2_args *uap; 100 int *retval; 101{ 102 register struct filedesc *fdp = p->p_fd; 103 register u_int old = uap->from, new = uap->to; 104 int i, error; 105 106 if (old >= fdp->fd_nfiles || 107 fdp->fd_ofiles[old] == NULL || 108 new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || 109 new >= maxfilesperproc) 110 return (EBADF); 111 if (old == new) { 112 *retval = new; 113 return (0); 114 } 115 if (new >= fdp->fd_nfiles) { 116 if ((error = fdalloc(p, new, &i))) 117 return (error); 118 if (new != i) 119 panic("dup2: fdalloc"); 120 } else if (fdp->fd_ofiles[new]) { 121 if (fdp->fd_ofileflags[new] & UF_MAPPED) 122 (void) munmapfd(p, new); 123 /* 124 * dup2() must succeed even if the close has an error. 125 */ 126 (void) closef(fdp->fd_ofiles[new], p); 127 } 128 return (finishdup(fdp, (int)old, (int)new, retval)); 129} 130 131/* 132 * Duplicate a file descriptor. 133 */ 134#ifndef _SYS_SYSPROTO_H_ 135struct dup_args { 136 u_int fd; 137}; 138#endif 139/* ARGSUSED */ 140int 141dup(p, uap, retval) 142 struct proc *p; 143 struct dup_args *uap; 144 int *retval; 145{ 146 register struct filedesc *fdp; 147 u_int old; 148 int new, error; 149 150 old = uap->fd; 151 152#if 0 153 /* 154 * XXX Compatibility 155 */ 156 if (old &~ 077) { uap->fd &= 077; return (dup2(p, uap, retval)); } 157#endif 158 159 fdp = p->p_fd; 160 if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL) 161 return (EBADF); 162 if ((error = fdalloc(p, 0, &new))) 163 return (error); 164 return (finishdup(fdp, (int)old, new, retval)); 165} 166 167/* 168 * The file control system call. 169 */ 170#ifndef _SYS_SYSPROTO_H_ 171struct fcntl_args { 172 int fd; 173 int cmd; 174 int arg; 175}; 176#endif 177/* ARGSUSED */ 178int 179fcntl(p, uap, retval) 180 struct proc *p; 181 register struct fcntl_args *uap; 182 int *retval; 183{ 184 register struct filedesc *fdp = p->p_fd; 185 register struct file *fp; 186 register char *pop; 187 struct vnode *vp; 188 int i, tmp, error, flg = F_POSIX; 189 struct flock fl; 190 u_int newmin; 191 192 if ((unsigned)uap->fd >= fdp->fd_nfiles || 193 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 194 return (EBADF); 195 pop = &fdp->fd_ofileflags[uap->fd]; 196 switch (uap->cmd) { 197 198 case F_DUPFD: 199 newmin = uap->arg; 200 if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || 201 newmin >= maxfilesperproc) 202 return (EINVAL); 203 if ((error = fdalloc(p, newmin, &i))) 204 return (error); 205 return (finishdup(fdp, uap->fd, i, retval)); 206 207 case F_GETFD: 208 *retval = *pop & 1; 209 return (0); 210 211 case F_SETFD: 212 *pop = (*pop &~ 1) | (uap->arg & 1); 213 return (0); 214 215 case F_GETFL: 216 *retval = OFLAGS(fp->f_flag); 217 return (0); 218 219 case F_SETFL: 220 fp->f_flag &= ~FCNTLFLAGS; 221 fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS; 222 tmp = fp->f_flag & FNONBLOCK; 223 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 224 if (error) 225 return (error); 226 tmp = fp->f_flag & FASYNC; 227 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 228 if (!error) 229 return (0); 230 fp->f_flag &= ~FNONBLOCK; 231 tmp = 0; 232 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 233 return (error); 234 235 case F_GETOWN: 236 if (fp->f_type == DTYPE_SOCKET) { 237 *retval = ((struct socket *)fp->f_data)->so_pgid; 238 return (0); 239 } 240 error = (*fp->f_ops->fo_ioctl) 241 (fp, (int)TIOCGPGRP, (caddr_t)retval, p); 242 *retval = -*retval; 243 return (error); 244 245 case F_SETOWN: 246 if (fp->f_type == DTYPE_SOCKET) { 247 ((struct socket *)fp->f_data)->so_pgid = uap->arg; 248 return (0); 249 } 250 if (uap->arg <= 0) { 251 uap->arg = -uap->arg; 252 } else { 253 struct proc *p1 = pfind(uap->arg); 254 if (p1 == 0) 255 return (ESRCH); 256 uap->arg = p1->p_pgrp->pg_id; 257 } 258 return ((*fp->f_ops->fo_ioctl) 259 (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p)); 260 261 case F_SETLKW: 262 flg |= F_WAIT; 263 /* Fall into F_SETLK */ 264 265 case F_SETLK: 266 if (fp->f_type != DTYPE_VNODE) 267 return (EBADF); 268 vp = (struct vnode *)fp->f_data; 269 /* Copy in the lock structure */ 270 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); 271 if (error) 272 return (error); 273 if (fl.l_whence == SEEK_CUR) 274 fl.l_start += fp->f_offset; 275 switch (fl.l_type) { 276 277 case F_RDLCK: 278 if ((fp->f_flag & FREAD) == 0) 279 return (EBADF); 280 p->p_flag |= P_ADVLOCK; 281 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); 282 283 case F_WRLCK: 284 if ((fp->f_flag & FWRITE) == 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_UNLCK: 290 return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl, 291 F_POSIX)); 292 293 default: 294 return (EINVAL); 295 } 296 297 case F_GETLK: 298 if (fp->f_type != DTYPE_VNODE) 299 return (EBADF); 300 vp = (struct vnode *)fp->f_data; 301 /* Copy in the lock structure */ 302 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); 303 if (error) 304 return (error); 305 if (fl.l_whence == SEEK_CUR) 306 fl.l_start += fp->f_offset; 307 if ((error = VOP_ADVLOCK(vp,(caddr_t)p,F_GETLK,&fl,F_POSIX))) 308 return (error); 309 return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl))); 310 311 default: 312 return (EINVAL); 313 } 314 /* NOTREACHED */ 315} 316 317/* 318 * Common code for dup, dup2, and fcntl(F_DUPFD). 319 */ 320int 321finishdup(fdp, old, new, retval) 322 register struct filedesc *fdp; 323 register int old, new, *retval; 324{ 325 register struct file *fp; 326 327 fp = fdp->fd_ofiles[old]; 328 fdp->fd_ofiles[new] = fp; 329 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE; 330 fp->f_count++; 331 if (new > fdp->fd_lastfile) 332 fdp->fd_lastfile = new; 333 *retval = new; 334 return (0); 335} 336 337/* 338 * Close a file descriptor. 339 */ 340#ifndef _SYS_SYSPROTO_H_ 341struct close_args { 342 int fd; 343}; 344#endif 345/* ARGSUSED */ 346int 347close(p, uap, retval) 348 struct proc *p; 349 struct close_args *uap; 350 int *retval; 351{ 352 register struct filedesc *fdp = p->p_fd; 353 register struct file *fp; 354 register int fd = uap->fd; 355 register u_char *pf; 356 357 if ((unsigned)fd >= fdp->fd_nfiles || 358 (fp = fdp->fd_ofiles[fd]) == NULL) 359 return (EBADF); 360 pf = (u_char *)&fdp->fd_ofileflags[fd]; 361 if (*pf & UF_MAPPED) 362 (void) munmapfd(p, fd); 363 fdp->fd_ofiles[fd] = NULL; 364 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 365 fdp->fd_lastfile--; 366 if (fd < fdp->fd_freefile) 367 fdp->fd_freefile = fd; 368 *pf = 0; 369 return (closef(fp, p)); 370} 371 372#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 373/* 374 * Return status information about a file descriptor. 375 */ 376#ifndef _SYS_SYSPROTO_H_ 377struct ofstat_args { 378 int fd; 379 struct ostat *sb; 380}; 381#endif 382/* ARGSUSED */ 383int 384ofstat(p, uap, retval) 385 struct proc *p; 386 register struct ofstat_args *uap; 387 int *retval; 388{ 389 register struct filedesc *fdp = p->p_fd; 390 register struct file *fp; 391 struct stat ub; 392 struct ostat oub; 393 int error; 394 395 if ((unsigned)uap->fd >= fdp->fd_nfiles || 396 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 397 return (EBADF); 398 switch (fp->f_type) { 399 400 case DTYPE_VNODE: 401 error = vn_stat((struct vnode *)fp->f_data, &ub, p); 402 break; 403 404 case DTYPE_SOCKET: 405 error = soo_stat((struct socket *)fp->f_data, &ub); 406 break; 407 408 default: 409 panic("ofstat"); 410 /*NOTREACHED*/ 411 } 412 cvtstat(&ub, &oub); 413 if (error == 0) 414 error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub)); 415 return (error); 416} 417#endif /* COMPAT_43 || COMPAT_SUNOS */ 418 419/* 420 * Return status information about a file descriptor. 421 */ 422#ifndef _SYS_SYSPROTO_H_ 423struct fstat_args { 424 int fd; 425 struct stat *sb; 426}; 427#endif 428/* ARGSUSED */ 429int 430fstat(p, uap, retval) 431 struct proc *p; 432 register struct fstat_args *uap; 433 int *retval; 434{ 435 register struct filedesc *fdp = p->p_fd; 436 register struct file *fp; 437 struct stat ub; 438 int error; 439 440 if ((unsigned)uap->fd >= fdp->fd_nfiles || 441 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 442 return (EBADF); 443 switch (fp->f_type) { 444 445 case DTYPE_VNODE: 446 error = vn_stat((struct vnode *)fp->f_data, &ub, p); 447 break; 448 449 case DTYPE_SOCKET: 450 error = soo_stat((struct socket *)fp->f_data, &ub); 451 break; 452 453 default: 454 panic("fstat"); 455 /*NOTREACHED*/ 456 } 457 if (error == 0) 458 error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); 459 return (error); 460} 461 462/* 463 * Return pathconf information about a file descriptor. 464 */ 465#ifndef _SYS_SYSPROTO_H_ 466struct fpathconf_args { 467 int fd; 468 int name; 469}; 470#endif 471/* ARGSUSED */ 472int 473fpathconf(p, uap, retval) 474 struct proc *p; 475 register struct fpathconf_args *uap; 476 int *retval; 477{ 478 struct filedesc *fdp = p->p_fd; 479 struct file *fp; 480 struct vnode *vp; 481 482 if ((unsigned)uap->fd >= fdp->fd_nfiles || 483 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 484 return (EBADF); 485 switch (fp->f_type) { 486 487 case DTYPE_SOCKET: 488 if (uap->name != _PC_PIPE_BUF) 489 return (EINVAL); 490 *retval = PIPE_BUF; 491 return (0); 492 493 case DTYPE_VNODE: 494 vp = (struct vnode *)fp->f_data; 495 return (VOP_PATHCONF(vp, uap->name, retval)); 496 497 default: 498 panic("fpathconf"); 499 } 500 /*NOTREACHED*/ 501} 502 503/* 504 * Allocate a file descriptor for the process. 505 */ 506int fdexpand; 507 508int 509fdalloc(p, want, result) 510 struct proc *p; 511 int want; 512 int *result; 513{ 514 register struct filedesc *fdp = p->p_fd; 515 register int i; 516 int lim, last, nfiles; 517 struct file **newofile; 518 char *newofileflags; 519 520 /* 521 * Search for a free descriptor starting at the higher 522 * of want or fd_freefile. If that fails, consider 523 * expanding the ofile array. 524 */ 525 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc); 526 for (;;) { 527 last = min(fdp->fd_nfiles, lim); 528 if ((i = want) < fdp->fd_freefile) 529 i = fdp->fd_freefile; 530 for (; i < last; i++) { 531 if (fdp->fd_ofiles[i] == NULL) { 532 fdp->fd_ofileflags[i] = 0; 533 if (i > fdp->fd_lastfile) 534 fdp->fd_lastfile = i; 535 if (want <= fdp->fd_freefile) 536 fdp->fd_freefile = i; 537 *result = i; 538 return (0); 539 } 540 } 541 542 /* 543 * No space in current array. Expand? 544 */ 545 if (fdp->fd_nfiles >= lim) 546 return (EMFILE); 547 if (fdp->fd_nfiles < NDEXTENT) 548 nfiles = NDEXTENT; 549 else 550 nfiles = 2 * fdp->fd_nfiles; 551 MALLOC(newofile, struct file **, nfiles * OFILESIZE, 552 M_FILEDESC, M_WAITOK); 553 newofileflags = (char *) &newofile[nfiles]; 554 /* 555 * Copy the existing ofile and ofileflags arrays 556 * and zero the new portion of each array. 557 */ 558 bcopy(fdp->fd_ofiles, newofile, 559 (i = sizeof(struct file *) * fdp->fd_nfiles)); 560 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i); 561 bcopy(fdp->fd_ofileflags, newofileflags, 562 (i = sizeof(char) * fdp->fd_nfiles)); 563 bzero(newofileflags + i, nfiles * sizeof(char) - i); 564 if (fdp->fd_nfiles > NDFILE) 565 FREE(fdp->fd_ofiles, M_FILEDESC); 566 fdp->fd_ofiles = newofile; 567 fdp->fd_ofileflags = newofileflags; 568 fdp->fd_nfiles = nfiles; 569 fdexpand++; 570 } 571 return (0); 572} 573 574/* 575 * Check to see whether n user file descriptors 576 * are available to the process p. 577 */ 578int 579fdavail(p, n) 580 struct proc *p; 581 register int n; 582{ 583 register struct filedesc *fdp = p->p_fd; 584 register struct file **fpp; 585 register int i, lim; 586 587 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc); 588 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0) 589 return (1); 590 fpp = &fdp->fd_ofiles[fdp->fd_freefile]; 591 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++) 592 if (*fpp == NULL && --n <= 0) 593 return (1); 594 return (0); 595} 596 597/* 598 * Create a new open file structure and allocate 599 * a file decriptor for the process that refers to it. 600 */ 601int 602falloc(p, resultfp, resultfd) 603 register struct proc *p; 604 struct file **resultfp; 605 int *resultfd; 606{ 607 register struct file *fp, *fq, **fpp; 608 int error, i; 609 610 if ((error = fdalloc(p, 0, &i))) 611 return (error); 612 if (nfiles >= maxfiles) { 613 tablefull("file"); 614 return (ENFILE); 615 } 616 /* 617 * Allocate a new file descriptor. 618 * If the process has file descriptor zero open, add to the list 619 * of open files at that point, otherwise put it at the front of 620 * the list of open files. 621 */ 622 nfiles++; 623 MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); 624 bzero(fp, sizeof(struct file)); 625 if ((fq = p->p_fd->fd_ofiles[0])) 626 fpp = &fq->f_filef; 627 else 628 fpp = &filehead; 629 p->p_fd->fd_ofiles[i] = fp; 630 if ((fq = *fpp)) 631 fq->f_fileb = &fp->f_filef; 632 fp->f_filef = fq; 633 fp->f_fileb = fpp; 634 *fpp = fp; 635 fp->f_count = 1; 636 fp->f_cred = p->p_ucred; 637 crhold(fp->f_cred); 638 if (resultfp) 639 *resultfp = fp; 640 if (resultfd) 641 *resultfd = i; 642 return (0); 643} 644 645/* 646 * Free a file descriptor. 647 */ 648void 649ffree(fp) 650 register struct file *fp; 651{ 652 register struct file *fq; 653 654 if ((fq = fp->f_filef)) 655 fq->f_fileb = fp->f_fileb; 656 *fp->f_fileb = fq; 657 crfree(fp->f_cred); 658#ifdef DIAGNOSTIC 659 fp->f_filef = NULL; 660 fp->f_fileb = NULL; 661 fp->f_count = 0; 662#endif 663 nfiles--; 664 FREE(fp, M_FILE); 665} 666 667/* 668 * Copy a filedesc structure. 669 */ 670struct filedesc * 671fdcopy(p) 672 struct proc *p; 673{ 674 register struct filedesc *newfdp, *fdp = p->p_fd; 675 register struct file **fpp; 676 register int i; 677 678 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0), 679 M_FILEDESC, M_WAITOK); 680 bcopy(fdp, newfdp, sizeof(struct filedesc)); 681 VREF(newfdp->fd_cdir); 682 if (newfdp->fd_rdir) 683 VREF(newfdp->fd_rdir); 684 newfdp->fd_refcnt = 1; 685 686 /* 687 * If the number of open files fits in the internal arrays 688 * of the open file structure, use them, otherwise allocate 689 * additional memory for the number of descriptors currently 690 * in use. 691 */ 692 if (newfdp->fd_lastfile < NDFILE) { 693 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; 694 newfdp->fd_ofileflags = 695 ((struct filedesc0 *) newfdp)->fd_dfileflags; 696 i = NDFILE; 697 } else { 698 /* 699 * Compute the smallest multiple of NDEXTENT needed 700 * for the file descriptors currently in use, 701 * allowing the table to shrink. 702 */ 703 i = newfdp->fd_nfiles; 704 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2) 705 i /= 2; 706 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE, 707 M_FILEDESC, M_WAITOK); 708 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; 709 } 710 newfdp->fd_nfiles = i; 711 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **)); 712 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char)); 713 fpp = newfdp->fd_ofiles; 714 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++) 715 if (*fpp != NULL) 716 (*fpp)->f_count++; 717 return (newfdp); 718} 719 720/* 721 * Release a filedesc structure. 722 */ 723void 724fdfree(p) 725 struct proc *p; 726{ 727 register struct filedesc *fdp = p->p_fd; 728 struct file **fpp; 729 register int i; 730 731 if (--fdp->fd_refcnt > 0) 732 return; 733 fpp = fdp->fd_ofiles; 734 for (i = fdp->fd_lastfile; i-- >= 0; fpp++) 735 if (*fpp) 736 (void) closef(*fpp, p); 737 if (fdp->fd_nfiles > NDFILE) 738 FREE(fdp->fd_ofiles, M_FILEDESC); 739 vrele(fdp->fd_cdir); 740 if (fdp->fd_rdir) 741 vrele(fdp->fd_rdir); 742 FREE(fdp, M_FILEDESC); 743} 744 745/* 746 * Close any files on exec? 747 */ 748void 749fdcloseexec(p) 750 struct proc *p; 751{ 752 struct filedesc *fdp = p->p_fd; 753 struct file **fpp; 754 char *fdfp; 755 register int i; 756 757 fpp = fdp->fd_ofiles; 758 fdfp = fdp->fd_ofileflags; 759 for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++) 760 if (*fpp != NULL && (*fdfp & UF_EXCLOSE)) { 761 if (*fdfp & UF_MAPPED) 762 (void) munmapfd(p, i); 763 (void) closef(*fpp, p); 764 *fpp = NULL; 765 *fdfp = 0; 766 if (i < fdp->fd_freefile) 767 fdp->fd_freefile = i; 768 } 769 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 770 fdp->fd_lastfile--; 771} 772 773/* 774 * Internal form of close. 775 * Decrement reference count on file structure. 776 * Note: p may be NULL when closing a file 777 * that was being passed in a message. 778 */ 779int 780closef(fp, p) 781 register struct file *fp; 782 register struct proc *p; 783{ 784 struct vnode *vp; 785 struct flock lf; 786 int error; 787 788 if (fp == NULL) 789 return (0); 790 /* 791 * POSIX record locking dictates that any close releases ALL 792 * locks owned by this process. This is handled by setting 793 * a flag in the unlock to free ONLY locks obeying POSIX 794 * semantics, and not to free BSD-style file locks. 795 * If the descriptor was in a message, POSIX-style locks 796 * aren't passed with the descriptor. 797 */ 798 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) { 799 lf.l_whence = SEEK_SET; 800 lf.l_start = 0; 801 lf.l_len = 0; 802 lf.l_type = F_UNLCK; 803 vp = (struct vnode *)fp->f_data; 804 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX); 805 } 806 if (--fp->f_count > 0) 807 return (0); 808 if (fp->f_count < 0) 809 panic("closef: count < 0"); 810 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) { 811 lf.l_whence = SEEK_SET; 812 lf.l_start = 0; 813 lf.l_len = 0; 814 lf.l_type = F_UNLCK; 815 vp = (struct vnode *)fp->f_data; 816 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); 817 } 818 if (fp->f_ops) 819 error = (*fp->f_ops->fo_close)(fp, p); 820 else 821 error = 0; 822 ffree(fp); 823 return (error); 824} 825 826/* 827 * Apply an advisory lock on a file descriptor. 828 * 829 * Just attempt to get a record lock of the requested type on 830 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 831 */ 832#ifndef _SYS_SYSPROTO_H_ 833struct flock_args { 834 int fd; 835 int how; 836}; 837#endif 838/* ARGSUSED */ 839int 840flock(p, uap, retval) 841 struct proc *p; 842 register struct flock_args *uap; 843 int *retval; 844{ 845 register struct filedesc *fdp = p->p_fd; 846 register struct file *fp; 847 struct vnode *vp; 848 struct flock lf; 849 850 if ((unsigned)uap->fd >= fdp->fd_nfiles || 851 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 852 return (EBADF); 853 if (fp->f_type != DTYPE_VNODE) 854 return (EOPNOTSUPP); 855 vp = (struct vnode *)fp->f_data; 856 lf.l_whence = SEEK_SET; 857 lf.l_start = 0; 858 lf.l_len = 0; 859 if (uap->how & LOCK_UN) { 860 lf.l_type = F_UNLCK; 861 fp->f_flag &= ~FHASLOCK; 862 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK)); 863 } 864 if (uap->how & LOCK_EX) 865 lf.l_type = F_WRLCK; 866 else if (uap->how & LOCK_SH) 867 lf.l_type = F_RDLCK; 868 else 869 return (EBADF); 870 fp->f_flag |= FHASLOCK; 871 if (uap->how & LOCK_NB) 872 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK)); 873 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); 874} 875 876/* 877 * File Descriptor pseudo-device driver (/dev/fd/). 878 * 879 * Opening minor device N dup()s the file (if any) connected to file 880 * descriptor N belonging to the calling process. Note that this driver 881 * consists of only the ``open()'' routine, because all subsequent 882 * references to this file will be direct to the other driver. 883 */ 884/* ARGSUSED */ 885int 886fdopen(dev, mode, type, p) 887 dev_t dev; 888 int mode, type; 889 struct proc *p; 890{ 891 892 /* 893 * XXX Kludge: set curproc->p_dupfd to contain the value of the 894 * the file descriptor being sought for duplication. The error 895 * return ensures that the vnode for this device will be released 896 * by vn_open. Open will detect this special error and take the 897 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 898 * will simply report the error. 899 */ 900 p->p_dupfd = minor(dev); 901 return (ENODEV); 902} 903 904/* 905 * Duplicate the specified descriptor to a free descriptor. 906 */ 907int 908dupfdopen(fdp, indx, dfd, mode, error) 909 register struct filedesc *fdp; 910 register int indx, dfd; 911 int mode; 912 int error; 913{ 914 register struct file *wfp; 915 struct file *fp; 916 917 /* 918 * If the to-be-dup'd fd number is greater than the allowed number 919 * of file descriptors, or the fd to be dup'd has already been 920 * closed, reject. Note, check for new == old is necessary as 921 * falloc could allocate an already closed to-be-dup'd descriptor 922 * as the new descriptor. 923 */ 924 fp = fdp->fd_ofiles[indx]; 925 if ((u_int)dfd >= fdp->fd_nfiles || 926 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp) 927 return (EBADF); 928 929 /* 930 * There are two cases of interest here. 931 * 932 * For ENODEV simply dup (dfd) to file descriptor 933 * (indx) and return. 934 * 935 * For ENXIO steal away the file structure from (dfd) and 936 * store it in (indx). (dfd) is effectively closed by 937 * this operation. 938 * 939 * Any other error code is just returned. 940 */ 941 switch (error) { 942 case ENODEV: 943 /* 944 * Check that the mode the file is being opened for is a 945 * subset of the mode of the existing descriptor. 946 */ 947 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 948 return (EACCES); 949 fdp->fd_ofiles[indx] = wfp; 950 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 951 wfp->f_count++; 952 if (indx > fdp->fd_lastfile) 953 fdp->fd_lastfile = indx; 954 return (0); 955 956 case ENXIO: 957 /* 958 * Steal away the file pointer from dfd, and stuff it into indx. 959 */ 960 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd]; 961 fdp->fd_ofiles[dfd] = NULL; 962 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 963 fdp->fd_ofileflags[dfd] = 0; 964 /* 965 * Complete the clean up of the filedesc structure by 966 * recomputing the various hints. 967 */ 968 if (indx > fdp->fd_lastfile) 969 fdp->fd_lastfile = indx; 970 else 971 while (fdp->fd_lastfile > 0 && 972 fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 973 fdp->fd_lastfile--; 974 if (dfd < fdp->fd_freefile) 975 fdp->fd_freefile = dfd; 976 return (0); 977 978 default: 979 return (error); 980 } 981 /* NOTREACHED */ 982} 983