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