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