1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_descrip.c 7.20 (Berkeley) 02/28/91 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "user.h" 13 #include "filedesc.h" 14 #include "kernel.h" 15 #include "vnode.h" 16 #include "proc.h" 17 #include "file.h" 18 #include "socket.h" 19 #include "socketvar.h" 20 #include "stat.h" 21 #include "ioctl.h" 22 #include "fcntl.h" 23 #include "malloc.h" 24 #include "syslog.h" 25 26 /* 27 * Descriptor management. 28 */ 29 int nofile = NOFILE; /* per-process maximum open files */ 30 31 /* 32 * System calls on descriptors. 33 */ 34 /* ARGSUSED */ 35 getdtablesize(p, uap, retval) 36 struct proc *p; 37 struct args *uap; 38 int *retval; 39 { 40 41 *retval = nofile; 42 return (0); 43 } 44 45 /* 46 * Duplicate a file descriptor. 47 */ 48 /* ARGSUSED */ 49 dup(p, uap, retval) 50 struct proc *p; 51 struct args { 52 int i; 53 } *uap; 54 int *retval; 55 { 56 register struct filedesc *fdp = p->p_fd; 57 struct file *fp; 58 int fd, error; 59 60 /* 61 * XXX Compatibility 62 */ 63 if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); } 64 65 if ((unsigned)uap->i >= fdp->fd_maxfiles || 66 (fp = OFILE(fdp, uap->i)) == NULL) 67 return (EBADF); 68 if (error = ufalloc(fdp, 0, &fd)) 69 return (error); 70 OFILE(fdp, fd) = fp; 71 OFILEFLAGS(fdp, fd) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE; 72 fp->f_count++; 73 if (fd > fdp->fd_lastfile) 74 fdp->fd_lastfile = fd; 75 *retval = fd; 76 return (0); 77 } 78 79 /* 80 * Duplicate a file descriptor to a particular value. 81 */ 82 /* ARGSUSED */ 83 dup2(p, uap, retval) 84 struct proc *p; 85 register struct args { 86 int i; 87 int j; 88 } *uap; 89 int *retval; 90 { 91 register struct filedesc *fdp = p->p_fd; 92 register struct file *fp; 93 int i, error; 94 95 if ((unsigned)uap->i >= fdp->fd_maxfiles || 96 (fp = OFILE(fdp, uap->i)) == NULL || 97 (unsigned)uap->j >= nofile) 98 return (EBADF); 99 *retval = uap->j; 100 if (uap->i == uap->j) 101 return (0); 102 if ((unsigned)uap->j >= fdp->fd_maxfiles) { 103 if (error = ufalloc(fdp, uap->j, &i)) 104 return (error); 105 if (uap->j != i) 106 panic("dup2: ufalloc"); 107 } else if (OFILE(fdp, uap->j)) { 108 if (OFILEFLAGS(fdp, uap->j) & UF_MAPPED) 109 (void) munmapfd(p, uap->j); 110 error = closef(OFILE(fdp, uap->j)); 111 } 112 OFILE(fdp, uap->j) = fp; 113 OFILEFLAGS(fdp, uap->j) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE; 114 fp->f_count++; 115 if (uap->j > fdp->fd_lastfile) 116 fdp->fd_lastfile = uap->j; 117 /* 118 * dup2() must succeed even though the close had an error. 119 */ 120 error = 0; /* XXX */ 121 return (error); 122 } 123 124 /* 125 * The file control system call. 126 */ 127 /* ARGSUSED */ 128 fcntl(p, uap, retval) 129 struct proc *p; 130 register struct args { 131 int fdes; 132 int cmd; 133 int arg; 134 } *uap; 135 int *retval; 136 { 137 register struct filedesc *fdp = p->p_fd; 138 register struct file *fp; 139 register char *pop; 140 struct vnode *vp; 141 int i, error, flags = F_POSIX; 142 struct flock fl; 143 144 if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 145 (fp = OFILE(fdp, uap->fdes)) == NULL) 146 return (EBADF); 147 pop = &OFILEFLAGS(fdp, uap->fdes); 148 switch(uap->cmd) { 149 case F_DUPFD: 150 if ((unsigned)uap->arg >= nofile) 151 return (EINVAL); 152 if (error = ufalloc(fdp, uap->arg, &i)) 153 return (error); 154 OFILE(fdp, i) = fp; 155 OFILEFLAGS(fdp, i) = *pop &~ UF_EXCLOSE; 156 fp->f_count++; 157 if (i > fdp->fd_lastfile) 158 fdp->fd_lastfile = i; 159 *retval = i; 160 return (0); 161 162 case F_GETFD: 163 *retval = *pop & 1; 164 return (0); 165 166 case F_SETFD: 167 *pop = (*pop &~ 1) | (uap->arg & 1); 168 return (0); 169 170 case F_GETFL: 171 *retval = OFLAGS(fp->f_flag); 172 return (0); 173 174 case F_SETFL: 175 fp->f_flag &= ~FCNTLFLAGS; 176 fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS; 177 if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY)) 178 return (error); 179 if (error = fset(fp, FASYNC, fp->f_flag & FASYNC)) 180 (void) fset(fp, FNDELAY, 0); 181 return (error); 182 183 case F_GETOWN: 184 return (fgetown(fp, retval)); 185 186 case F_SETOWN: 187 return (fsetown(fp, uap->arg)); 188 189 case F_SETLKW: 190 flags |= F_WAIT; 191 /* Fall into F_SETLK */ 192 193 case F_SETLK: 194 if (fp->f_type != DTYPE_VNODE) 195 return (EBADF); 196 vp = (struct vnode *)fp->f_data; 197 /* Copy in the lock structure */ 198 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); 199 if (error) 200 return (error); 201 if (fl.l_whence == SEEK_CUR) 202 fl.l_start += fp->f_offset; 203 switch (fl.l_type) { 204 205 case F_RDLCK: 206 if ((fp->f_flag & FREAD) == 0) 207 return (EBADF); 208 return (VOP_ADVLOCK(vp, p, F_SETLK, &fl, flags)); 209 210 case F_WRLCK: 211 if ((fp->f_flag & FWRITE) == 0) 212 return (EBADF); 213 return (VOP_ADVLOCK(vp, p, F_SETLK, &fl, flags)); 214 215 case F_UNLCK: 216 return (VOP_ADVLOCK(vp, p, F_UNLCK, &fl, F_POSIX)); 217 218 default: 219 return (EINVAL); 220 } 221 222 case F_GETLK: 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 if (error = VOP_ADVLOCK(vp, p, F_GETLK, &fl, F_POSIX)) 233 return (error); 234 return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl))); 235 236 default: 237 return (EINVAL); 238 } 239 /* NOTREACHED */ 240 } 241 242 fset(fp, bit, value) 243 struct file *fp; 244 int bit, value; 245 { 246 247 if (value) 248 fp->f_flag |= bit; 249 else 250 fp->f_flag &= ~bit; 251 return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 252 (caddr_t)&value)); 253 } 254 255 fgetown(fp, valuep) 256 struct file *fp; 257 int *valuep; 258 { 259 int error; 260 261 switch (fp->f_type) { 262 263 case DTYPE_SOCKET: 264 *valuep = ((struct socket *)fp->f_data)->so_pgid; 265 return (0); 266 267 default: 268 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 269 *valuep = -*valuep; 270 return (error); 271 } 272 } 273 274 fsetown(fp, value) 275 struct file *fp; 276 int value; 277 { 278 279 if (fp->f_type == DTYPE_SOCKET) { 280 ((struct socket *)fp->f_data)->so_pgid = value; 281 return (0); 282 } 283 if (value > 0) { 284 struct proc *p = pfind(value); 285 if (p == 0) 286 return (ESRCH); 287 value = p->p_pgrp->pg_id; 288 } else 289 value = -value; 290 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 291 } 292 293 fioctl(fp, cmd, value) 294 struct file *fp; 295 int cmd; 296 caddr_t value; 297 { 298 299 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 300 } 301 302 /* 303 * Close a file descriptor. 304 */ 305 /* ARGSUSED */ 306 close(p, uap, retval) 307 struct proc *p; 308 struct args { 309 int fdes; 310 } *uap; 311 int *retval; 312 { 313 register struct filedesc *fdp = p->p_fd; 314 register struct file *fp; 315 register u_char *pf; 316 317 if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 318 (fp = OFILE(fdp, uap->fdes)) == NULL) 319 return (EBADF); 320 pf = (u_char *)&OFILEFLAGS(fdp, uap->fdes); 321 if (*pf & UF_MAPPED) 322 (void) munmapfd(p, uap->fdes); 323 OFILE(fdp, uap->fdes) = NULL; 324 while (fdp->fd_lastfile >= 0 && OFILE(fdp, fdp->fd_lastfile) == NULL) 325 fdp->fd_lastfile--; 326 *pf = 0; 327 return (closef(fp)); 328 } 329 330 /* 331 * Return status information about a file descriptor. 332 */ 333 /* ARGSUSED */ 334 fstat(p, uap, retval) 335 struct proc *p; 336 register struct args { 337 int fdes; 338 struct stat *sb; 339 } *uap; 340 int *retval; 341 { 342 register struct filedesc *fdp = p->p_fd; 343 register struct file *fp; 344 struct stat ub; 345 int error; 346 347 if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 348 (fp = OFILE(fdp, uap->fdes)) == NULL) 349 return (EBADF); 350 switch (fp->f_type) { 351 352 case DTYPE_VNODE: 353 error = vn_stat((struct vnode *)fp->f_data, &ub); 354 break; 355 356 case DTYPE_SOCKET: 357 error = soo_stat((struct socket *)fp->f_data, &ub); 358 break; 359 360 default: 361 panic("fstat"); 362 /*NOTREACHED*/ 363 } 364 if (error == 0) 365 error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); 366 return (error); 367 } 368 369 /* 370 * Allocate a user file descriptor. 371 */ 372 int fdexpand, fdreexpand; 373 374 ufalloc(fdp, want, result) 375 register struct filedesc *fdp; 376 register int want; 377 int *result; 378 { 379 int last, osize, ofiles, nfiles; 380 struct file **newofile; 381 char *newofileflags; 382 383 for (;;) { 384 last = (fdp->fd_maxfiles < nofile) ? fdp->fd_maxfiles : nofile; 385 for (; want < last; want++) { 386 if (OFILE(fdp, want) == NULL) { 387 OFILEFLAGS(fdp, want) = 0; 388 if (want > fdp->fd_lastfile) 389 fdp->fd_lastfile = want; 390 *result = want; 391 return (0); 392 } 393 } 394 if (fdp->fd_maxfiles >= nofile) 395 return (EMFILE); 396 if (fdp->fd_maxfiles == NDFILE) { 397 fdp->fd_moreofiles = (struct file **) 398 malloc(NDEXTENT * OFILESIZE, M_FILE, M_WAITOK); 399 fdp->fd_moreofileflags = 400 (char *)&fdp->fd_moreofiles[NDEXTENT]; 401 bzero((char *)fdp->fd_moreofiles, NDEXTENT * OFILESIZE); 402 fdp->fd_maxfiles = NDFILE + NDEXTENT; 403 fdexpand++; 404 continue; 405 } 406 ofiles = fdp->fd_maxfiles - NDFILE; 407 osize = ofiles * OFILESIZE; 408 nfiles = (2 * osize) / OFILESIZE; 409 newofile = (struct file **) malloc(2 * osize, M_FILE, M_WAITOK); 410 newofileflags = (char *)&newofile[nfiles]; 411 bzero((char *)newofile, 2 * osize); 412 bcopy((char *)fdp->fd_moreofiles, (char *)newofile, 413 sizeof(struct file *) * ofiles); 414 bcopy((char *)fdp->fd_moreofileflags, (char *)newofileflags, 415 sizeof(char) * ofiles); 416 free(fdp->fd_moreofiles, M_FILE); 417 fdp->fd_moreofiles = newofile; 418 fdp->fd_moreofileflags = newofileflags; 419 fdp->fd_maxfiles = NDFILE + nfiles; 420 fdreexpand++; 421 } 422 } 423 424 /* 425 * Check to see if any user file descriptors are available. 426 */ 427 ufavail(fdp) 428 register struct filedesc *fdp; 429 { 430 register int i, avail; 431 432 avail = nofile - fdp->fd_maxfiles; 433 for (i = 0; i < fdp->fd_maxfiles; i++) 434 if (OFILE(fdp, i) == NULL) 435 avail++; 436 return (avail); 437 } 438 439 struct file *lastf; 440 /* 441 * Allocate a user file descriptor 442 * and a file structure. 443 * Initialize the descriptor 444 * to point at the file structure. 445 */ 446 falloc(p, resultfp, resultfd) 447 register struct proc *p; 448 struct file **resultfp; 449 int *resultfd; 450 { 451 register struct file *fp; 452 int error, i; 453 454 if (error = ufalloc(p->p_fd, 0, &i)) 455 return (error); 456 if (lastf == 0) 457 lastf = file; 458 for (fp = lastf; fp < fileNFILE; fp++) 459 if (fp->f_count == 0) 460 goto slot; 461 for (fp = file; fp < lastf; fp++) 462 if (fp->f_count == 0) 463 goto slot; 464 tablefull("file"); 465 return (ENFILE); 466 slot: 467 OFILE(p->p_fd, i) = fp; 468 fp->f_count = 1; 469 fp->f_data = 0; 470 fp->f_offset = 0; 471 fp->f_cred = u.u_cred; 472 crhold(fp->f_cred); 473 lastf = fp + 1; 474 if (resultfp) 475 *resultfp = fp; 476 if (resultfd) 477 *resultfd = i; 478 return (0); 479 } 480 481 /* 482 * Duplicate a filedesc structure. 483 */ 484 struct filedesc * 485 fddup(fdp, justref) 486 register struct filedesc *fdp; 487 int justref; 488 { 489 register struct filedesc *newfdp; 490 register struct file *fp; 491 register int i; 492 int j, last; 493 494 if (justref) { 495 fdp->fd_refcnt++; 496 return (fdp); 497 } 498 MALLOC(newfdp, struct filedesc *, sizeof(*fdp), M_FILE, M_WAITOK); 499 bcopy((char *)fdp, (char *)newfdp, sizeof(*fdp)); 500 VREF(newfdp->fd_cdir); 501 if (newfdp->fd_rdir) 502 VREF(newfdp->fd_rdir); 503 newfdp->fd_refcnt = 1; 504 newfdp->fd_maxfiles = NDFILE; 505 if (fdp->fd_lastfile > NDFILE && 506 ufalloc(newfdp, fdp->fd_lastfile, &j)) { 507 log(LOG_ERR, "fddup: lost file descriptor(s)"); 508 last = newfdp->fd_maxfiles; 509 } else 510 last = fdp->fd_lastfile; 511 for (i = 0; i <= last; i++) { 512 fp = OFILE(fdp, i); 513 if (fp == NULL) 514 continue; 515 fp->f_count++; 516 OFILE(newfdp, i) = fp; 517 OFILEFLAGS(newfdp, i) = OFILEFLAGS(fdp, i); 518 } 519 return (newfdp); 520 } 521 522 /* 523 * Release a filedesc structure. 524 */ 525 fdrele(fdp) 526 register struct filedesc *fdp; 527 { 528 struct file *f; 529 register int i; 530 531 if (fdp->fd_refcnt > 1) { 532 fdp->fd_refcnt--; 533 return; 534 } 535 for (i = 0; i <= fdp->fd_lastfile; i++) { 536 if (f = OFILE(fdp, i)) { 537 OFILE(fdp, i) = NULL; 538 OFILEFLAGS(fdp, i) = 0; 539 (void) closef(f); 540 } 541 } 542 if (fdp->fd_maxfiles > NDFILE) 543 FREE(fdp->fd_moreofiles, M_FILE); 544 vrele(fdp->fd_cdir); 545 if (fdp->fd_rdir) 546 vrele(fdp->fd_rdir); 547 FREE(fdp, M_FILE); 548 } 549 550 /* 551 * Internal form of close. 552 * Decrement reference count on file structure. 553 */ 554 closef(fp) 555 register struct file *fp; 556 { 557 struct proc *p = u.u_procp; /* XXX */ 558 struct vnode *vp; 559 struct flock lf; 560 int error; 561 562 if (fp == NULL) 563 return (0); 564 /* 565 * POSIX record locking dictates that any close releases ALL 566 * locks owned by this process. This is handled by setting 567 * a flag in the unlock to free ONLY locks obeying POSIX 568 * semantics, and not to free BSD-style file locks. 569 */ 570 if (fp->f_type == DTYPE_VNODE) { 571 lf.l_whence = SEEK_SET; 572 lf.l_start = 0; 573 lf.l_len = 0; 574 lf.l_type = F_UNLCK; 575 vp = (struct vnode *)fp->f_data; 576 (void) VOP_ADVLOCK(vp, p, F_UNLCK, &lf, F_POSIX); 577 } 578 if (fp->f_count > 1) { 579 fp->f_count--; 580 return (0); 581 } 582 if (fp->f_count < 1) 583 panic("closef: count < 1"); 584 if (fp->f_type == DTYPE_VNODE) 585 (void) VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK); 586 error = (*fp->f_ops->fo_close)(fp); 587 crfree(fp->f_cred); 588 fp->f_count = 0; 589 return (error); 590 } 591 592 /* 593 * Apply an advisory lock on a file descriptor. 594 * 595 * Just attempt to get a record lock of the requested type on 596 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 597 */ 598 599 /* ARGSUSED */ 600 flock(p, uap, retval) 601 struct proc *p; 602 register struct args { 603 int fdes; 604 int how; 605 } *uap; 606 int *retval; 607 { 608 register struct filedesc *fdp = p->p_fd; 609 register struct file *fp; 610 struct vnode *vp; 611 struct flock lf; 612 int error; 613 614 if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 615 (fp = OFILE(fdp, uap->fdes)) == NULL) 616 return (EBADF); 617 if (fp->f_type != DTYPE_VNODE) 618 return (EOPNOTSUPP); 619 vp = (struct vnode *)fp->f_data; 620 lf.l_whence = SEEK_SET; 621 lf.l_start = 0; 622 lf.l_len = 0; 623 if (uap->how & LOCK_UN) { 624 lf.l_type = F_UNLCK; 625 return (VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK)); 626 } 627 if (uap->how & LOCK_EX) 628 lf.l_type = F_WRLCK; 629 else if (uap->how & LOCK_SH) 630 lf.l_type = F_RDLCK; 631 else 632 return (EBADF); 633 if (uap->how & LOCK_NB) 634 return (VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK)); 635 return (VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); 636 } 637 638 /* 639 * File Descriptor pseudo-device driver (/dev/fd/). 640 * 641 * Opening minor device N dup()s the file (if any) connected to file 642 * descriptor N belonging to the calling process. Note that this driver 643 * consists of only the ``open()'' routine, because all subsequent 644 * references to this file will be direct to the other driver. 645 */ 646 /* ARGSUSED */ 647 fdopen(dev, mode, type) 648 dev_t dev; 649 int mode, type; 650 { 651 struct proc *p = u.u_procp; /* XXX */ 652 653 /* 654 * XXX Kludge: set p->p_dupfd to contain the value of the 655 * the file descriptor being sought for duplication. The error 656 * return ensures that the vnode for this device will be released 657 * by vn_open. Open will detect this special error and take the 658 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 659 * will simply report the error. 660 */ 661 p->p_dupfd = minor(dev); 662 return (ENODEV); 663 } 664 665 /* 666 * Duplicate the specified descriptor to a free descriptor. 667 */ 668 dupfdopen(fdp, indx, dfd, mode) 669 register struct filedesc *fdp; 670 register int indx, dfd; 671 int mode; 672 { 673 register struct file *wfp; 674 struct file *fp; 675 676 /* 677 * If the to-be-dup'd fd number is greater than the allowed number 678 * of file descriptors, or the fd to be dup'd has already been 679 * closed, reject. Note, check for new == old is necessary as 680 * falloc could allocate an already closed to-be-dup'd descriptor 681 * as the new descriptor. 682 */ 683 fp = OFILE(fdp, indx); 684 if ((u_int)dfd >= fdp->fd_maxfiles || (wfp = OFILE(fdp, dfd)) == NULL || 685 fp == wfp) 686 return (EBADF); 687 688 /* 689 * Check that the mode the file is being opened for is a subset 690 * of the mode of the existing descriptor. 691 */ 692 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 693 return (EACCES); 694 OFILE(fdp, indx) = wfp; 695 OFILEFLAGS(fdp, indx) = OFILEFLAGS(fdp, dfd); 696 wfp->f_count++; 697 if (indx > fdp->fd_lastfile) 698 fdp->fd_lastfile = indx; 699 return (0); 700 } 701 702 #if defined(vax) || defined(tahoe) 703 /* 704 * Brain dead routines to compensate for limitations in PCC 705 */ 706 struct file ** 707 ofilefunc(fdp, indx) 708 struct filedesc *fdp; 709 int indx; 710 { 711 712 if (indx < NDFILE) 713 return (&fdp->fd_ofile[indx]); 714 return (&fdp->fd_moreofiles[indx - NDFILE]); 715 } 716 717 char * 718 ofileflagsfunc(fdp, indx) 719 struct filedesc *fdp; 720 int indx; 721 { 722 723 if (indx < NDFILE) 724 return (&fdp->fd_ofileflags[indx]); 725 return (&fdp->fd_moreofileflags[indx - NDFILE]); 726 } 727 #endif 728