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