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.5 (Berkeley) 01/21/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 file *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, **fpp; 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 if (fq = p->p_fd->fd_ofiles[0]) 566 fpp = &fq->f_filef; 567 else 568 fpp = &filehead; 569 p->p_fd->fd_ofiles[i] = fp; 570 if (fq = *fpp) 571 fq->f_fileb = &fp->f_filef; 572 fp->f_filef = fq; 573 fp->f_fileb = fpp; 574 *fpp = fp; 575 fp->f_count = 1; 576 fp->f_msgcount = 0; 577 fp->f_offset = 0; 578 fp->f_cred = p->p_ucred; 579 crhold(fp->f_cred); 580 if (resultfp) 581 *resultfp = fp; 582 if (resultfd) 583 *resultfd = i; 584 return (0); 585 } 586 587 /* 588 * Free a file descriptor. 589 */ 590 ffree(fp) 591 register struct file *fp; 592 { 593 register struct file *fq; 594 595 if (fq = fp->f_filef) 596 fq->f_fileb = fp->f_fileb; 597 *fp->f_fileb = fq; 598 crfree(fp->f_cred); 599 #ifdef DIAGNOSTIC 600 fp->f_filef = NULL; 601 fp->f_fileb = NULL; 602 fp->f_count = 0; 603 #endif 604 nfiles--; 605 FREE(fp, M_FILE); 606 } 607 608 /* 609 * Copy a filedesc structure. 610 */ 611 struct filedesc * 612 fdcopy(p) 613 struct proc *p; 614 { 615 register struct filedesc *newfdp, *fdp = p->p_fd; 616 register struct file **fpp; 617 register int i; 618 619 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0), 620 M_FILEDESC, M_WAITOK); 621 bcopy(fdp, newfdp, sizeof(struct filedesc)); 622 VREF(newfdp->fd_cdir); 623 if (newfdp->fd_rdir) 624 VREF(newfdp->fd_rdir); 625 newfdp->fd_refcnt = 1; 626 627 /* 628 * If the number of open files fits in the internal arrays 629 * of the open file structure, use them, otherwise allocate 630 * additional memory for the number of descriptors currently 631 * in use. 632 */ 633 if (newfdp->fd_lastfile < NDFILE) { 634 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; 635 newfdp->fd_ofileflags = 636 ((struct filedesc0 *) newfdp)->fd_dfileflags; 637 i = NDFILE; 638 } else { 639 /* 640 * Compute the smallest multiple of NDEXTENT needed 641 * for the file descriptors currently in use, 642 * allowing the table to shrink. 643 */ 644 i = newfdp->fd_nfiles; 645 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2) 646 i /= 2; 647 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE, 648 M_FILEDESC, M_WAITOK); 649 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; 650 } 651 newfdp->fd_nfiles = i; 652 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **)); 653 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char)); 654 fpp = newfdp->fd_ofiles; 655 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++) 656 if (*fpp != NULL) 657 (*fpp)->f_count++; 658 return (newfdp); 659 } 660 661 /* 662 * Release a filedesc structure. 663 */ 664 void 665 fdfree(p) 666 struct proc *p; 667 { 668 register struct filedesc *fdp = p->p_fd; 669 struct file **fpp; 670 register int i; 671 672 if (--fdp->fd_refcnt > 0) 673 return; 674 fpp = fdp->fd_ofiles; 675 for (i = fdp->fd_lastfile; i-- >= 0; fpp++) 676 if (*fpp) 677 (void) closef(*fpp, p); 678 if (fdp->fd_nfiles > NDFILE) 679 FREE(fdp->fd_ofiles, M_FILEDESC); 680 vrele(fdp->fd_cdir); 681 if (fdp->fd_rdir) 682 vrele(fdp->fd_rdir); 683 FREE(fdp, M_FILEDESC); 684 } 685 686 /* 687 * Internal form of close. 688 * Decrement reference count on file structure. 689 * Note: p may be NULL when closing a file 690 * that was being passed in a message. 691 */ 692 closef(fp, p) 693 register struct file *fp; 694 register struct proc *p; 695 { 696 struct vnode *vp; 697 struct flock lf; 698 int error; 699 700 if (fp == NULL) 701 return (0); 702 /* 703 * POSIX record locking dictates that any close releases ALL 704 * locks owned by this process. This is handled by setting 705 * a flag in the unlock to free ONLY locks obeying POSIX 706 * semantics, and not to free BSD-style file locks. 707 * If the descriptor was in a message, POSIX-style locks 708 * aren't passed with the descriptor. 709 */ 710 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) { 711 lf.l_whence = SEEK_SET; 712 lf.l_start = 0; 713 lf.l_len = 0; 714 lf.l_type = F_UNLCK; 715 vp = (struct vnode *)fp->f_data; 716 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX); 717 } 718 if (--fp->f_count > 0) 719 return (0); 720 if (fp->f_count < 0) 721 panic("closef: count < 0"); 722 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) { 723 lf.l_whence = SEEK_SET; 724 lf.l_start = 0; 725 lf.l_len = 0; 726 lf.l_type = F_UNLCK; 727 vp = (struct vnode *)fp->f_data; 728 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); 729 } 730 error = (*fp->f_ops->fo_close)(fp, p); 731 ffree(fp); 732 return (error); 733 } 734 735 /* 736 * Apply an advisory lock on a file descriptor. 737 * 738 * Just attempt to get a record lock of the requested type on 739 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 740 */ 741 struct flock_args { 742 int fd; 743 int how; 744 }; 745 /* ARGSUSED */ 746 flock(p, uap, retval) 747 struct proc *p; 748 register struct flock_args *uap; 749 int *retval; 750 { 751 register struct filedesc *fdp = p->p_fd; 752 register struct file *fp; 753 struct vnode *vp; 754 struct flock lf; 755 756 if ((unsigned)uap->fd >= fdp->fd_nfiles || 757 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 758 return (EBADF); 759 if (fp->f_type != DTYPE_VNODE) 760 return (EOPNOTSUPP); 761 vp = (struct vnode *)fp->f_data; 762 lf.l_whence = SEEK_SET; 763 lf.l_start = 0; 764 lf.l_len = 0; 765 if (uap->how & LOCK_UN) { 766 lf.l_type = F_UNLCK; 767 fp->f_flag &= ~FHASLOCK; 768 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK)); 769 } 770 if (uap->how & LOCK_EX) 771 lf.l_type = F_WRLCK; 772 else if (uap->how & LOCK_SH) 773 lf.l_type = F_RDLCK; 774 else 775 return (EBADF); 776 fp->f_flag |= FHASLOCK; 777 if (uap->how & LOCK_NB) 778 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK)); 779 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); 780 } 781 782 /* 783 * File Descriptor pseudo-device driver (/dev/fd/). 784 * 785 * Opening minor device N dup()s the file (if any) connected to file 786 * descriptor N belonging to the calling process. Note that this driver 787 * consists of only the ``open()'' routine, because all subsequent 788 * references to this file will be direct to the other driver. 789 */ 790 /* ARGSUSED */ 791 fdopen(dev, mode, type, p) 792 dev_t dev; 793 int mode, type; 794 struct proc *p; 795 { 796 797 /* 798 * XXX Kludge: set curproc->p_dupfd to contain the value of the 799 * the file descriptor being sought for duplication. The error 800 * return ensures that the vnode for this device will be released 801 * by vn_open. Open will detect this special error and take the 802 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 803 * will simply report the error. 804 */ 805 p->p_dupfd = minor(dev); 806 return (ENODEV); 807 } 808 809 /* 810 * Duplicate the specified descriptor to a free descriptor. 811 */ 812 dupfdopen(fdp, indx, dfd, mode, error) 813 register struct filedesc *fdp; 814 register int indx, dfd; 815 int mode; 816 int error; 817 { 818 register struct file *wfp; 819 struct file *fp; 820 821 /* 822 * If the to-be-dup'd fd number is greater than the allowed number 823 * of file descriptors, or the fd to be dup'd has already been 824 * closed, reject. Note, check for new == old is necessary as 825 * falloc could allocate an already closed to-be-dup'd descriptor 826 * as the new descriptor. 827 */ 828 fp = fdp->fd_ofiles[indx]; 829 if ((u_int)dfd >= fdp->fd_nfiles || 830 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp) 831 return (EBADF); 832 833 /* 834 * There are two cases of interest here. 835 * 836 * For ENODEV simply dup (dfd) to file descriptor 837 * (indx) and return. 838 * 839 * For ENXIO steal away the file structure from (dfd) and 840 * store it in (indx). (dfd) is effectively closed by 841 * this operation. 842 * 843 * Any other error code is just returned. 844 */ 845 switch (error) { 846 case ENODEV: 847 /* 848 * Check that the mode the file is being opened for is a 849 * subset of the mode of the existing descriptor. 850 */ 851 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 852 return (EACCES); 853 fdp->fd_ofiles[indx] = wfp; 854 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 855 wfp->f_count++; 856 if (indx > fdp->fd_lastfile) 857 fdp->fd_lastfile = indx; 858 return (0); 859 860 case ENXIO: 861 /* 862 * Steal away the file pointer from dfd, and stuff it into indx. 863 */ 864 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd]; 865 fdp->fd_ofiles[dfd] = NULL; 866 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 867 fdp->fd_ofileflags[dfd] = 0; 868 /* 869 * Complete the clean up of the filedesc structure by 870 * recomputing the various hints. 871 */ 872 if (indx > fdp->fd_lastfile) 873 fdp->fd_lastfile = indx; 874 else 875 while (fdp->fd_lastfile > 0 && 876 fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 877 fdp->fd_lastfile--; 878 if (dfd < fdp->fd_freefile) 879 fdp->fd_freefile = dfd; 880 return (0); 881 882 default: 883 return (error); 884 } 885 /* NOTREACHED */ 886 } 887