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