123367Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423367Smckusick * 544431Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*45914Smckusick * @(#)kern_descrip.c 7.17 (Berkeley) 01/10/91 823367Smckusick */ 97422Sroot 1017089Sbloom #include "param.h" 1117089Sbloom #include "systm.h" 1244404Skarels #include "user.h" 13*45914Smckusick #include "filedesc.h" 1417089Sbloom #include "kernel.h" 1537728Smckusick #include "vnode.h" 1617089Sbloom #include "proc.h" 1717089Sbloom #include "file.h" 1817089Sbloom #include "socket.h" 1917089Sbloom #include "socketvar.h" 2017089Sbloom #include "stat.h" 2117089Sbloom #include "ioctl.h" 22*45914Smckusick #include "malloc.h" 23*45914Smckusick #include "syslog.h" 247497Sroot 257422Sroot /* 267497Sroot * Descriptor management. 277422Sroot */ 28*45914Smckusick int nofile = NOFILE; /* per-process maximum open files */ 297497Sroot 307497Sroot /* 317497Sroot * System calls on descriptors. 327497Sroot */ 3342863Smckusick /* ARGSUSED */ 3442863Smckusick getdtablesize(p, uap, retval) 3542863Smckusick struct proc *p; 3642863Smckusick struct args *uap; 3742863Smckusick int *retval; 387497Sroot { 397497Sroot 40*45914Smckusick *retval = nofile; 4144404Skarels return (0); 427497Sroot } 437497Sroot 4442863Smckusick /* 4542863Smckusick * Duplicate a file descriptor. 4642863Smckusick */ 4742863Smckusick /* ARGSUSED */ 4842863Smckusick dup(p, uap, retval) 4942863Smckusick struct proc *p; 5042863Smckusick struct args { 5142863Smckusick int i; 5242863Smckusick } *uap; 5342863Smckusick int *retval; 547422Sroot { 55*45914Smckusick register struct filedesc *fdp = p->p_fd; 567696Ssam struct file *fp; 5742863Smckusick int fd, error; 587497Sroot 5942863Smckusick /* 6042863Smckusick * XXX Compatibility 6142863Smckusick */ 6244404Skarels if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); } 637497Sroot 64*45914Smckusick if ((unsigned)uap->i >= fdp->fd_maxfiles || 65*45914Smckusick (fp = OFILE(fdp, uap->i)) == NULL) 6644404Skarels return (EBADF); 67*45914Smckusick if (error = ufalloc(fdp, 0, &fd)) 6844404Skarels return (error); 69*45914Smckusick OFILE(fdp, fd) = fp; 70*45914Smckusick OFILEFLAGS(fdp, fd) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE; 7142863Smckusick fp->f_count++; 72*45914Smckusick if (fd > fdp->fd_lastfile) 73*45914Smckusick fdp->fd_lastfile = fd; 7442863Smckusick *retval = fd; 7544404Skarels return (0); 767497Sroot } 777497Sroot 7842863Smckusick /* 7942863Smckusick * Duplicate a file descriptor to a particular value. 8042863Smckusick */ 8142863Smckusick /* ARGSUSED */ 8242863Smckusick dup2(p, uap, retval) 8342863Smckusick struct proc *p; 8442863Smckusick register struct args { 8542863Smckusick int i; 8642863Smckusick int j; 8742863Smckusick } *uap; 8842863Smckusick int *retval; 897497Sroot { 90*45914Smckusick register struct filedesc *fdp = p->p_fd; 917497Sroot register struct file *fp; 92*45914Smckusick int i, error; 937422Sroot 94*45914Smckusick if ((unsigned)uap->i >= fdp->fd_maxfiles || 95*45914Smckusick (fp = OFILE(fdp, uap->i)) == NULL || 96*45914Smckusick (unsigned)uap->j >= nofile) 9744404Skarels return (EBADF); 9842863Smckusick *retval = uap->j; 997497Sroot if (uap->i == uap->j) 10044404Skarels return (0); 101*45914Smckusick if ((unsigned)uap->j >= fdp->fd_maxfiles) { 102*45914Smckusick if (error = ufalloc(fdp, uap->j, &i)) 103*45914Smckusick return (error); 104*45914Smckusick if (uap->j != i) 105*45914Smckusick panic("dup2: ufalloc"); 106*45914Smckusick } else if (OFILE(fdp, uap->j)) { 107*45914Smckusick if (OFILEFLAGS(fdp, uap->j) & UF_MAPPED) 108*45914Smckusick (void) munmapfd(p, uap->j); 109*45914Smckusick error = closef(OFILE(fdp, uap->j)); 1107422Sroot } 111*45914Smckusick OFILE(fdp, uap->j) = fp; 112*45914Smckusick OFILEFLAGS(fdp, uap->j) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE; 11342863Smckusick fp->f_count++; 114*45914Smckusick if (uap->j > fdp->fd_lastfile) 115*45914Smckusick fdp->fd_lastfile = uap->j; 11639354Smckusick /* 11739354Smckusick * dup2() must succeed even though the close had an error. 11839354Smckusick */ 11939354Smckusick error = 0; /* XXX */ 12044404Skarels return (error); 1217696Ssam } 1227696Ssam 12312748Ssam /* 12412748Ssam * The file control system call. 12512748Ssam */ 12642863Smckusick /* ARGSUSED */ 12742863Smckusick fcntl(p, uap, retval) 12842863Smckusick struct proc *p; 12942863Smckusick register struct args { 13012748Ssam int fdes; 13112748Ssam int cmd; 13212748Ssam int arg; 13342863Smckusick } *uap; 13442863Smckusick int *retval; 13542863Smckusick { 136*45914Smckusick register struct filedesc *fdp = p->p_fd; 13742863Smckusick register struct file *fp; 13812748Ssam register char *pop; 13942863Smckusick int i, error; 1407497Sroot 141*45914Smckusick if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 142*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL) 14344404Skarels return (EBADF); 144*45914Smckusick pop = &OFILEFLAGS(fdp, uap->fdes); 14512748Ssam switch(uap->cmd) { 14615076Skarels case F_DUPFD: 147*45914Smckusick if ((unsigned)uap->arg >= nofile) 14844404Skarels return (EINVAL); 149*45914Smckusick if (error = ufalloc(fdp, uap->arg, &i)) 15044404Skarels return (error); 151*45914Smckusick OFILE(fdp, i) = fp; 152*45914Smckusick OFILEFLAGS(fdp, i) = *pop &~ UF_EXCLOSE; 15342863Smckusick fp->f_count++; 154*45914Smckusick if (i > fdp->fd_lastfile) 155*45914Smckusick fdp->fd_lastfile = i; 15642863Smckusick *retval = i; 15744404Skarels return (0); 1587497Sroot 15915076Skarels case F_GETFD: 16042863Smckusick *retval = *pop & 1; 16144404Skarels return (0); 1627422Sroot 16315076Skarels case F_SETFD: 16412748Ssam *pop = (*pop &~ 1) | (uap->arg & 1); 16544404Skarels return (0); 1668145Sroot 16715076Skarels case F_GETFL: 16842863Smckusick *retval = fp->f_flag + FOPEN; 16944404Skarels return (0); 1708145Sroot 17115076Skarels case F_SETFL: 17212748Ssam fp->f_flag &= FCNTLCANT; 17312748Ssam fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 17442863Smckusick if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY)) 17544404Skarels return (error); 17642863Smckusick if (error = fset(fp, FASYNC, fp->f_flag & FASYNC)) 17712748Ssam (void) fset(fp, FNDELAY, 0); 17844404Skarels return (error); 1797422Sroot 18015076Skarels case F_GETOWN: 18144404Skarels return (fgetown(fp, retval)); 1827422Sroot 18315076Skarels case F_SETOWN: 18444404Skarels return (fsetown(fp, uap->arg)); 1858115Sroot 18612748Ssam default: 18744404Skarels return (EINVAL); 1887422Sroot } 18942863Smckusick /* NOTREACHED */ 1907422Sroot } 1917422Sroot 19212748Ssam fset(fp, bit, value) 19312748Ssam struct file *fp; 19412748Ssam int bit, value; 1957422Sroot { 1967422Sroot 19712748Ssam if (value) 19812748Ssam fp->f_flag |= bit; 19912748Ssam else 20012748Ssam fp->f_flag &= ~bit; 20112748Ssam return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 20212748Ssam (caddr_t)&value)); 20312748Ssam } 2047422Sroot 20512748Ssam fgetown(fp, valuep) 20612748Ssam struct file *fp; 20712748Ssam int *valuep; 20812748Ssam { 20912748Ssam int error; 2108115Sroot 21112748Ssam switch (fp->f_type) { 2128115Sroot 21312748Ssam case DTYPE_SOCKET: 21435810Smarc *valuep = ((struct socket *)fp->f_data)->so_pgid; 21512748Ssam return (0); 2167497Sroot 21712748Ssam default: 21812748Ssam error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 21912748Ssam *valuep = -*valuep; 22012748Ssam return (error); 2217422Sroot } 2227422Sroot } 2237422Sroot 22412748Ssam fsetown(fp, value) 22512748Ssam struct file *fp; 22612748Ssam int value; 2277422Sroot { 22837728Smckusick 22912748Ssam if (fp->f_type == DTYPE_SOCKET) { 23035810Smarc ((struct socket *)fp->f_data)->so_pgid = value; 23112748Ssam return (0); 23212748Ssam } 23312748Ssam if (value > 0) { 23412748Ssam struct proc *p = pfind(value); 23512748Ssam if (p == 0) 23628201Skarels return (ESRCH); 23735810Smarc value = p->p_pgrp->pg_id; 23812748Ssam } else 23912748Ssam value = -value; 24012748Ssam return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 2417422Sroot } 2427422Sroot 24312748Ssam fioctl(fp, cmd, value) 24412748Ssam struct file *fp; 24512748Ssam int cmd; 24612748Ssam caddr_t value; 2477422Sroot { 2487422Sroot 24912748Ssam return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 2507422Sroot } 2517422Sroot 25242863Smckusick /* 25342863Smckusick * Close a file descriptor. 25442863Smckusick */ 25542863Smckusick /* ARGSUSED */ 25642863Smckusick close(p, uap, retval) 25742863Smckusick struct proc *p; 25842863Smckusick struct args { 25942863Smckusick int fdes; 26042863Smckusick } *uap; 26142863Smckusick int *retval; 2628029Sroot { 263*45914Smckusick register struct filedesc *fdp = p->p_fd; 26412748Ssam register struct file *fp; 26513044Ssam register u_char *pf; 2668029Sroot 267*45914Smckusick if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 268*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL) 26944404Skarels return (EBADF); 270*45914Smckusick pf = (u_char *)&OFILEFLAGS(fdp, uap->fdes); 27113044Ssam if (*pf & UF_MAPPED) 272*45914Smckusick (void) munmapfd(p, uap->fdes); 273*45914Smckusick OFILE(fdp, uap->fdes) = NULL; 274*45914Smckusick while (fdp->fd_lastfile >= 0 && OFILE(fdp, fdp->fd_lastfile) == NULL) 275*45914Smckusick fdp->fd_lastfile--; 27615550Skarels *pf = 0; 27744404Skarels return (closef(fp)); 2788029Sroot } 2798029Sroot 28042863Smckusick /* 28142863Smckusick * Return status information about a file descriptor. 28242863Smckusick */ 28342863Smckusick /* ARGSUSED */ 28442863Smckusick fstat(p, uap, retval) 28542863Smckusick struct proc *p; 28642863Smckusick register struct args { 28742863Smckusick int fdes; 28842863Smckusick struct stat *sb; 28942863Smckusick } *uap; 29042863Smckusick int *retval; 29113044Ssam { 292*45914Smckusick register struct filedesc *fdp = p->p_fd; 29313044Ssam register struct file *fp; 29413044Ssam struct stat ub; 29542863Smckusick int error; 29613044Ssam 297*45914Smckusick if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 298*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL) 29944404Skarels return (EBADF); 30013044Ssam switch (fp->f_type) { 30113044Ssam 30237728Smckusick case DTYPE_VNODE: 30342863Smckusick error = vn_stat((struct vnode *)fp->f_data, &ub); 30413044Ssam break; 30513044Ssam 30613044Ssam case DTYPE_SOCKET: 30742863Smckusick error = soo_stat((struct socket *)fp->f_data, &ub); 30813044Ssam break; 30913044Ssam 31013044Ssam default: 31113044Ssam panic("fstat"); 31213044Ssam /*NOTREACHED*/ 31313044Ssam } 31442863Smckusick if (error == 0) 31542863Smckusick error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); 31644404Skarels return (error); 31713044Ssam } 31813044Ssam 3197422Sroot /* 3207497Sroot * Allocate a user file descriptor. 3217422Sroot */ 322*45914Smckusick int fdexpand, fdreexpand; 323*45914Smckusick 324*45914Smckusick ufalloc(fdp, want, result) 325*45914Smckusick register struct filedesc *fdp; 32637728Smckusick register int want; 32737728Smckusick int *result; 3287422Sroot { 329*45914Smckusick int last, osize, ofiles, nfiles; 330*45914Smckusick struct file **newofile; 331*45914Smckusick char *newofileflags; 3327497Sroot 333*45914Smckusick for (;;) { 334*45914Smckusick last = (fdp->fd_maxfiles < nofile) ? fdp->fd_maxfiles : nofile; 335*45914Smckusick for (; want < last; want++) { 336*45914Smckusick if (OFILE(fdp, want) == NULL) { 337*45914Smckusick OFILEFLAGS(fdp, want) = 0; 338*45914Smckusick if (want > fdp->fd_lastfile) 339*45914Smckusick fdp->fd_lastfile = want; 340*45914Smckusick *result = want; 341*45914Smckusick return (0); 342*45914Smckusick } 3437497Sroot } 344*45914Smckusick if (fdp->fd_maxfiles >= nofile) 345*45914Smckusick return (EMFILE); 346*45914Smckusick if (fdp->fd_maxfiles == NDFILE) { 347*45914Smckusick fdp->fd_moreofiles = (struct file **) 348*45914Smckusick malloc(NDEXTENT * OFILESIZE, M_FILE, M_WAITOK); 349*45914Smckusick fdp->fd_moreofileflags = 350*45914Smckusick (char *)&fdp->fd_moreofiles[NDEXTENT]; 351*45914Smckusick bzero((char *)fdp->fd_moreofiles, NDEXTENT * OFILESIZE); 352*45914Smckusick fdp->fd_maxfiles = NDFILE + NDEXTENT; 353*45914Smckusick fdexpand++; 354*45914Smckusick continue; 355*45914Smckusick } 356*45914Smckusick ofiles = fdp->fd_maxfiles - NDFILE; 357*45914Smckusick osize = ofiles * OFILESIZE; 358*45914Smckusick nfiles = (2 * osize) / OFILESIZE; 359*45914Smckusick newofile = (struct file **) malloc(2 * osize, M_FILE, M_WAITOK); 360*45914Smckusick newofileflags = (char *)&newofile[nfiles]; 361*45914Smckusick bzero((char *)newofile, 2 * osize); 362*45914Smckusick bcopy((char *)fdp->fd_moreofiles, (char *)newofile, 363*45914Smckusick sizeof(struct file *) * ofiles); 364*45914Smckusick bcopy((char *)fdp->fd_moreofileflags, (char *)newofileflags, 365*45914Smckusick sizeof(char) * ofiles); 366*45914Smckusick free(fdp->fd_moreofiles, M_FILE); 367*45914Smckusick fdp->fd_moreofiles = newofile; 368*45914Smckusick fdp->fd_moreofileflags = newofileflags; 369*45914Smckusick fdp->fd_maxfiles = NDFILE + nfiles; 370*45914Smckusick fdreexpand++; 37139733Smckusick } 3727497Sroot } 3737497Sroot 37442863Smckusick /* 37542863Smckusick * Check to see if any user file descriptors are available. 37642863Smckusick */ 377*45914Smckusick ufavail(fdp) 378*45914Smckusick register struct filedesc *fdp; 37912748Ssam { 380*45914Smckusick register int i, avail; 38112748Ssam 382*45914Smckusick avail = nofile - fdp->fd_maxfiles; 383*45914Smckusick for (i = 0; i < fdp->fd_maxfiles; i++) 384*45914Smckusick if (OFILE(fdp, i) == NULL) 38512748Ssam avail++; 38612748Ssam return (avail); 38712748Ssam } 38812748Ssam 3897497Sroot struct file *lastf; 3907497Sroot /* 3917497Sroot * Allocate a user file descriptor 3927497Sroot * and a file structure. 3937497Sroot * Initialize the descriptor 3947497Sroot * to point at the file structure. 3957497Sroot */ 396*45914Smckusick falloc(p, resultfp, resultfd) 397*45914Smckusick register struct proc *p; 39837728Smckusick struct file **resultfp; 39937728Smckusick int *resultfd; 4007497Sroot { 4017422Sroot register struct file *fp; 40237728Smckusick int error, i; 4037422Sroot 404*45914Smckusick if (error = ufalloc(p->p_fd, 0, &i)) 40537728Smckusick return (error); 4067497Sroot if (lastf == 0) 4077497Sroot lastf = file; 4087497Sroot for (fp = lastf; fp < fileNFILE; fp++) 4097497Sroot if (fp->f_count == 0) 4107497Sroot goto slot; 4117497Sroot for (fp = file; fp < lastf; fp++) 4127497Sroot if (fp->f_count == 0) 4137497Sroot goto slot; 4147497Sroot tablefull("file"); 41537728Smckusick return (ENFILE); 4167497Sroot slot: 417*45914Smckusick OFILE(p->p_fd, i) = fp; 41812748Ssam fp->f_count = 1; 41912748Ssam fp->f_data = 0; 4207497Sroot fp->f_offset = 0; 42137728Smckusick fp->f_cred = u.u_cred; 42237728Smckusick crhold(fp->f_cred); 4237497Sroot lastf = fp + 1; 42437728Smckusick if (resultfp) 42537728Smckusick *resultfp = fp; 42637728Smckusick if (resultfd) 42737728Smckusick *resultfd = i; 42837728Smckusick return (0); 4297497Sroot } 43012748Ssam 4317497Sroot /* 432*45914Smckusick * Duplicate a filedesc structure. 433*45914Smckusick */ 434*45914Smckusick struct filedesc * 435*45914Smckusick fddup(fdp, justref) 436*45914Smckusick register struct filedesc *fdp; 437*45914Smckusick int justref; 438*45914Smckusick { 439*45914Smckusick register struct filedesc *newfdp; 440*45914Smckusick register struct file *fp; 441*45914Smckusick register int i; 442*45914Smckusick int j, last; 443*45914Smckusick 444*45914Smckusick if (justref) { 445*45914Smckusick fdp->fd_refcnt++; 446*45914Smckusick return (fdp); 447*45914Smckusick } 448*45914Smckusick MALLOC(newfdp, struct filedesc *, sizeof(*fdp), M_FILE, M_WAITOK); 449*45914Smckusick bcopy((char *)fdp, (char *)newfdp, sizeof(*fdp)); 450*45914Smckusick VREF(newfdp->fd_cdir); 451*45914Smckusick if (newfdp->fd_rdir) 452*45914Smckusick VREF(newfdp->fd_rdir); 453*45914Smckusick newfdp->fd_refcnt = 1; 454*45914Smckusick newfdp->fd_maxfiles = NDFILE; 455*45914Smckusick if (fdp->fd_lastfile > NDFILE && 456*45914Smckusick ufalloc(newfdp, fdp->fd_lastfile, &j)) { 457*45914Smckusick log(LOG_ERR, "fddup: lost file descriptor(s)"); 458*45914Smckusick last = newfdp->fd_maxfiles; 459*45914Smckusick } else 460*45914Smckusick last = fdp->fd_lastfile; 461*45914Smckusick for (i = 0; i <= last; i++) { 462*45914Smckusick fp = OFILE(fdp, i); 463*45914Smckusick if (fp == NULL) 464*45914Smckusick continue; 465*45914Smckusick fp->f_count++; 466*45914Smckusick OFILE(newfdp, i) = fp; 467*45914Smckusick OFILEFLAGS(newfdp, i) = OFILEFLAGS(fdp, i); 468*45914Smckusick } 469*45914Smckusick return (newfdp); 470*45914Smckusick } 471*45914Smckusick 472*45914Smckusick /* 473*45914Smckusick * Release a filedesc structure. 474*45914Smckusick */ 475*45914Smckusick fdrele(fdp) 476*45914Smckusick register struct filedesc *fdp; 477*45914Smckusick { 478*45914Smckusick struct file *f; 479*45914Smckusick register int i; 480*45914Smckusick 481*45914Smckusick if (fdp->fd_refcnt > 1) { 482*45914Smckusick fdp->fd_refcnt--; 483*45914Smckusick return; 484*45914Smckusick } 485*45914Smckusick for (i = 0; i <= fdp->fd_lastfile; i++) { 486*45914Smckusick if (f = OFILE(fdp, i)) { 487*45914Smckusick OFILE(fdp, i) = NULL; 488*45914Smckusick OFILEFLAGS(fdp, i) = 0; 489*45914Smckusick (void) closef(f); 490*45914Smckusick } 491*45914Smckusick } 492*45914Smckusick if (fdp->fd_maxfiles > NDFILE) 493*45914Smckusick FREE(fdp->fd_moreofiles, M_FILE); 494*45914Smckusick vrele(fdp->fd_cdir); 495*45914Smckusick if (fdp->fd_rdir) 496*45914Smckusick vrele(fdp->fd_rdir); 497*45914Smckusick FREE(fdp, M_FILE); 498*45914Smckusick } 499*45914Smckusick 500*45914Smckusick /* 5017497Sroot * Internal form of close. 50212748Ssam * Decrement reference count on file structure. 5037497Sroot */ 50413044Ssam closef(fp) 5057497Sroot register struct file *fp; 5067497Sroot { 50739354Smckusick int error; 5087497Sroot 5097422Sroot if (fp == NULL) 51039354Smckusick return (0); 5117497Sroot if (fp->f_count > 1) { 5127497Sroot fp->f_count--; 51339354Smckusick return (0); 5147422Sroot } 51537728Smckusick if (fp->f_count < 1) 51637728Smckusick panic("closef: count < 1"); 51739354Smckusick error = (*fp->f_ops->fo_close)(fp); 51837728Smckusick crfree(fp->f_cred); 5197497Sroot fp->f_count = 0; 52039354Smckusick return (error); 5217422Sroot } 52213044Ssam 52313044Ssam /* 52413044Ssam * Apply an advisory lock on a file descriptor. 52513044Ssam */ 52642863Smckusick /* ARGSUSED */ 52742863Smckusick flock(p, uap, retval) 52842863Smckusick struct proc *p; 52942863Smckusick register struct args { 53037728Smckusick int fdes; 53113044Ssam int how; 53242863Smckusick } *uap; 53342863Smckusick int *retval; 53442863Smckusick { 535*45914Smckusick register struct filedesc *fdp = p->p_fd; 53613044Ssam register struct file *fp; 53713044Ssam 538*45914Smckusick if ((unsigned)uap->fdes >= fdp->fd_maxfiles || 539*45914Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL) 54044404Skarels return (EBADF); 54142863Smckusick if (fp->f_type != DTYPE_VNODE) 54244404Skarels return (EOPNOTSUPP); 54313101Ssam if (uap->how & LOCK_UN) { 54437728Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 54544404Skarels return (0); 54613044Ssam } 54717434Skarels if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 54844404Skarels return (0); /* error? */ 54917998Skarels if (uap->how & LOCK_EX) 55017998Skarels uap->how &= ~LOCK_SH; 55113101Ssam /* avoid work... */ 55217998Skarels if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 55317998Skarels (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 55444404Skarels return (0); 55544404Skarels return (vn_lock(fp, uap->how)); 55613044Ssam } 55737586Smarc 55837586Smarc /* 55937586Smarc * File Descriptor pseudo-device driver (/dev/fd/). 56037586Smarc * 56137586Smarc * Opening minor device N dup()s the file (if any) connected to file 56237586Smarc * descriptor N belonging to the calling process. Note that this driver 56337586Smarc * consists of only the ``open()'' routine, because all subsequent 56437586Smarc * references to this file will be direct to the other driver. 56537586Smarc */ 56637728Smckusick /* ARGSUSED */ 56737728Smckusick fdopen(dev, mode, type) 56837586Smarc dev_t dev; 56937728Smckusick int mode, type; 57037586Smarc { 57143406Smckusick struct proc *p = u.u_procp; /* XXX */ 57237586Smarc 57337586Smarc /* 57443449Smckusick * XXX Kludge: set p->p_dupfd to contain the value of the 57543406Smckusick * the file descriptor being sought for duplication. The error 57643406Smckusick * return ensures that the vnode for this device will be released 57743406Smckusick * by vn_open. Open will detect this special error and take the 57843406Smckusick * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 57943406Smckusick * will simply report the error. 58037586Smarc */ 58143449Smckusick p->p_dupfd = minor(dev); 58243406Smckusick return (ENODEV); 58343406Smckusick } 58440873Sbostic 58543406Smckusick /* 58643406Smckusick * Duplicate the specified descriptor to a free descriptor. 58743406Smckusick */ 588*45914Smckusick dupfdopen(fdp, indx, dfd, mode) 589*45914Smckusick register struct filedesc *fdp; 59043406Smckusick register int indx, dfd; 59143406Smckusick int mode; 59243406Smckusick { 59343406Smckusick register struct file *wfp; 59443406Smckusick struct file *fp; 59543406Smckusick 59637586Smarc /* 59743406Smckusick * If the to-be-dup'd fd number is greater than the allowed number 59843406Smckusick * of file descriptors, or the fd to be dup'd has already been 59943406Smckusick * closed, reject. Note, check for new == old is necessary as 60043406Smckusick * falloc could allocate an already closed to-be-dup'd descriptor 60143406Smckusick * as the new descriptor. 60237586Smarc */ 603*45914Smckusick fp = OFILE(fdp, indx); 604*45914Smckusick if ((u_int)dfd >= fdp->fd_maxfiles || (wfp = OFILE(fdp, dfd)) == NULL || 60540873Sbostic fp == wfp) 60637586Smarc return (EBADF); 60740873Sbostic 60837586Smarc /* 60940873Sbostic * Check that the mode the file is being opened for is a subset 61040873Sbostic * of the mode of the existing descriptor. 61137586Smarc */ 61243406Smckusick if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 61337586Smarc return (EACCES); 614*45914Smckusick OFILE(fdp, indx) = wfp; 615*45914Smckusick OFILEFLAGS(fdp, indx) = OFILEFLAGS(fdp, dfd); 61642863Smckusick wfp->f_count++; 617*45914Smckusick if (indx > fdp->fd_lastfile) 618*45914Smckusick fdp->fd_lastfile = indx; 61943406Smckusick return (0); 62037586Smarc } 621*45914Smckusick 622*45914Smckusick #if defined(vax) || defined(tahoe) 623*45914Smckusick /* 624*45914Smckusick * Brain dead routines to compensate for limitations in PCC 625*45914Smckusick */ 626*45914Smckusick struct file ** 627*45914Smckusick ofilefunc(fdp, indx) 628*45914Smckusick struct filedesc *fdp; 629*45914Smckusick int indx; 630*45914Smckusick { 631*45914Smckusick 632*45914Smckusick if (indx < NDFILE) 633*45914Smckusick return (&fdp->fd_ofile[indx]); 634*45914Smckusick return (&fdp->fd_moreofiles[indx - NDFILE]); 635*45914Smckusick } 636*45914Smckusick 637*45914Smckusick char * 638*45914Smckusick ofileflagsfunc(fdp, indx) 639*45914Smckusick struct filedesc *fdp; 640*45914Smckusick int indx; 641*45914Smckusick { 642*45914Smckusick 643*45914Smckusick if (indx < NDFILE) 644*45914Smckusick return (&fdp->fd_ofileflags[indx]); 645*45914Smckusick return (&fdp->fd_moreofileflags[indx - NDFILE]); 646*45914Smckusick } 647*45914Smckusick #endif 648