123367Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423367Smckusick * 537728Smckusick * Redistribution and use in source and binary forms are permitted 637728Smckusick * provided that the above copyright notice and this paragraph are 737728Smckusick * duplicated in all such forms and that any documentation, 837728Smckusick * advertising materials, and other materials related to such 937728Smckusick * distribution and use acknowledge that the software was developed 1037728Smckusick * by the University of California, Berkeley. The name of the 1137728Smckusick * University may not be used to endorse or promote products derived 1237728Smckusick * from this software without specific prior written permission. 1337728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637728Smckusick * 17*43406Smckusick * @(#)kern_descrip.c 7.13 (Berkeley) 06/21/90 1823367Smckusick */ 197422Sroot 2017089Sbloom #include "param.h" 2117089Sbloom #include "systm.h" 2237728Smckusick #include "syscontext.h" 2317089Sbloom #include "kernel.h" 2437728Smckusick #include "vnode.h" 2517089Sbloom #include "proc.h" 2617089Sbloom #include "file.h" 2717089Sbloom #include "socket.h" 2817089Sbloom #include "socketvar.h" 2917089Sbloom #include "stat.h" 3017089Sbloom #include "ioctl.h" 317497Sroot 32*43406Smckusick #define p_devtmp p_logname[11] 33*43406Smckusick 347422Sroot /* 357497Sroot * Descriptor management. 367422Sroot */ 377497Sroot 387497Sroot /* 397497Sroot * System calls on descriptors. 407497Sroot */ 4142863Smckusick /* ARGSUSED */ 4242863Smckusick getdtablesize(p, uap, retval) 4342863Smckusick struct proc *p; 4442863Smckusick struct args *uap; 4542863Smckusick int *retval; 467497Sroot { 477497Sroot 4842863Smckusick *retval = NOFILE; 4942863Smckusick RETURN (0); 507497Sroot } 517497Sroot 5242863Smckusick /* 5342863Smckusick * Duplicate a file descriptor. 5442863Smckusick */ 5542863Smckusick /* ARGSUSED */ 5642863Smckusick dup(p, uap, retval) 5742863Smckusick struct proc *p; 5842863Smckusick struct args { 5942863Smckusick int i; 6042863Smckusick } *uap; 6142863Smckusick int *retval; 627422Sroot { 637696Ssam struct file *fp; 6442863Smckusick int fd, error; 657497Sroot 6642863Smckusick /* 6742863Smckusick * XXX Compatibility 6842863Smckusick */ 6942863Smckusick if (uap->i &~ 077) { uap->i &= 077; RETURN (dup2(p, uap, retval)); } 707497Sroot 7137728Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 7237728Smckusick RETURN (EBADF); 7342863Smckusick if (error = ufalloc(0, &fd)) 7442863Smckusick RETURN (error); 7542863Smckusick u.u_ofile[fd] = fp; 7642863Smckusick u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 7742863Smckusick fp->f_count++; 7842863Smckusick if (fd > u.u_lastfile) 7942863Smckusick u.u_lastfile = fd; 8042863Smckusick *retval = fd; 8142863Smckusick RETURN (0); 827497Sroot } 837497Sroot 8442863Smckusick /* 8542863Smckusick * Duplicate a file descriptor to a particular value. 8642863Smckusick */ 8742863Smckusick /* ARGSUSED */ 8842863Smckusick dup2(p, uap, retval) 8942863Smckusick struct proc *p; 9042863Smckusick register struct args { 9142863Smckusick int i; 9242863Smckusick int j; 9342863Smckusick } *uap; 9442863Smckusick int *retval; 957497Sroot { 967497Sroot register struct file *fp; 9739354Smckusick int error; 987422Sroot 9937728Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 10037728Smckusick RETURN (EBADF); 10139354Smckusick if (uap->j < 0 || uap->j >= NOFILE) 10239354Smckusick RETURN (EBADF); 10342863Smckusick *retval = uap->j; 1047497Sroot if (uap->i == uap->j) 10539354Smckusick RETURN (0); 1067497Sroot if (u.u_ofile[uap->j]) { 1078945Sroot if (u.u_pofile[uap->j] & UF_MAPPED) 1088945Sroot munmapfd(uap->j); 10939354Smckusick error = closef(u.u_ofile[uap->j]); 1107422Sroot } 11142863Smckusick u.u_ofile[uap->j] = fp; 11242863Smckusick u.u_pofile[uap->j] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 11342863Smckusick fp->f_count++; 11442863Smckusick if (uap->j > u.u_lastfile) 11542863Smckusick u.u_lastfile = uap->j; 11639354Smckusick /* 11739354Smckusick * dup2() must succeed even though the close had an error. 11839354Smckusick */ 11939354Smckusick error = 0; /* XXX */ 12039354Smckusick 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 { 13642863Smckusick register struct file *fp; 13712748Ssam register char *pop; 13842863Smckusick int i, error; 1397497Sroot 14037728Smckusick if ((unsigned)uap->fdes >= NOFILE || 14137728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 14237728Smckusick RETURN (EBADF); 14312748Ssam pop = &u.u_pofile[uap->fdes]; 14412748Ssam switch(uap->cmd) { 14515076Skarels case F_DUPFD: 14642863Smckusick if (uap->arg < 0 || uap->arg >= NOFILE) 14742863Smckusick RETURN (EINVAL); 14842863Smckusick if (error = ufalloc(uap->arg, &i)) 14942863Smckusick RETURN (error); 15042863Smckusick u.u_ofile[i] = fp; 15142863Smckusick u.u_pofile[i] = *pop &~ UF_EXCLOSE; 15242863Smckusick fp->f_count++; 15342863Smckusick if (i > u.u_lastfile) 15442863Smckusick u.u_lastfile = i; 15542863Smckusick *retval = i; 15642863Smckusick RETURN (0); 1577497Sroot 15815076Skarels case F_GETFD: 15942863Smckusick *retval = *pop & 1; 16042863Smckusick RETURN (0); 1617422Sroot 16215076Skarels case F_SETFD: 16312748Ssam *pop = (*pop &~ 1) | (uap->arg & 1); 16442863Smckusick RETURN (0); 1658145Sroot 16615076Skarels case F_GETFL: 16742863Smckusick *retval = fp->f_flag + FOPEN; 16842863Smckusick RETURN (0); 1698145Sroot 17015076Skarels case F_SETFL: 17112748Ssam fp->f_flag &= FCNTLCANT; 17212748Ssam fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 17342863Smckusick if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY)) 17442863Smckusick RETURN (error); 17542863Smckusick if (error = fset(fp, FASYNC, fp->f_flag & FASYNC)) 17612748Ssam (void) fset(fp, FNDELAY, 0); 17742863Smckusick RETURN (error); 1787422Sroot 17915076Skarels case F_GETOWN: 18042863Smckusick RETURN (fgetown(fp, retval)); 1817422Sroot 18215076Skarels case F_SETOWN: 18342863Smckusick RETURN (fsetown(fp, uap->arg)); 1848115Sroot 18512748Ssam default: 18642863Smckusick RETURN (EINVAL); 1877422Sroot } 18842863Smckusick /* NOTREACHED */ 1897422Sroot } 1907422Sroot 19112748Ssam fset(fp, bit, value) 19212748Ssam struct file *fp; 19312748Ssam int bit, value; 1947422Sroot { 1957422Sroot 19612748Ssam if (value) 19712748Ssam fp->f_flag |= bit; 19812748Ssam else 19912748Ssam fp->f_flag &= ~bit; 20012748Ssam return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 20112748Ssam (caddr_t)&value)); 20212748Ssam } 2037422Sroot 20412748Ssam fgetown(fp, valuep) 20512748Ssam struct file *fp; 20612748Ssam int *valuep; 20712748Ssam { 20812748Ssam int error; 2098115Sroot 21012748Ssam switch (fp->f_type) { 2118115Sroot 21212748Ssam case DTYPE_SOCKET: 21335810Smarc *valuep = ((struct socket *)fp->f_data)->so_pgid; 21412748Ssam return (0); 2157497Sroot 21612748Ssam default: 21712748Ssam error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 21812748Ssam *valuep = -*valuep; 21912748Ssam return (error); 2207422Sroot } 2217422Sroot } 2227422Sroot 22312748Ssam fsetown(fp, value) 22412748Ssam struct file *fp; 22512748Ssam int value; 2267422Sroot { 22737728Smckusick 22812748Ssam if (fp->f_type == DTYPE_SOCKET) { 22935810Smarc ((struct socket *)fp->f_data)->so_pgid = value; 23012748Ssam return (0); 23112748Ssam } 23212748Ssam if (value > 0) { 23312748Ssam struct proc *p = pfind(value); 23412748Ssam if (p == 0) 23528201Skarels return (ESRCH); 23635810Smarc value = p->p_pgrp->pg_id; 23712748Ssam } else 23812748Ssam value = -value; 23912748Ssam return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 2407422Sroot } 2417422Sroot 24212748Ssam fioctl(fp, cmd, value) 24312748Ssam struct file *fp; 24412748Ssam int cmd; 24512748Ssam caddr_t value; 2467422Sroot { 2477422Sroot 24812748Ssam return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 2497422Sroot } 2507422Sroot 25142863Smckusick /* 25242863Smckusick * Close a file descriptor. 25342863Smckusick */ 25442863Smckusick /* ARGSUSED */ 25542863Smckusick close(p, uap, retval) 25642863Smckusick struct proc *p; 25742863Smckusick struct args { 25842863Smckusick int fdes; 25942863Smckusick } *uap; 26042863Smckusick int *retval; 2618029Sroot { 26212748Ssam register struct file *fp; 26313044Ssam register u_char *pf; 2648029Sroot 26537728Smckusick if ((unsigned)uap->fdes >= NOFILE || 26637728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 26737728Smckusick RETURN (EBADF); 26837728Smckusick pf = (u_char *)&u.u_pofile[uap->fdes]; 26913044Ssam if (*pf & UF_MAPPED) 27037728Smckusick munmapfd(uap->fdes); 27137728Smckusick u.u_ofile[uap->fdes] = NULL; 27221101Skarels while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 27321101Skarels u.u_lastfile--; 27415550Skarels *pf = 0; 27539354Smckusick RETURN (closef(fp)); 2768029Sroot } 2778029Sroot 27842863Smckusick /* 27942863Smckusick * Return status information about a file descriptor. 28042863Smckusick */ 28142863Smckusick /* ARGSUSED */ 28242863Smckusick fstat(p, uap, retval) 28342863Smckusick struct proc *p; 28442863Smckusick register struct args { 28542863Smckusick int fdes; 28642863Smckusick struct stat *sb; 28742863Smckusick } *uap; 28842863Smckusick int *retval; 28913044Ssam { 29013044Ssam register struct file *fp; 29113044Ssam struct stat ub; 29242863Smckusick int error; 29313044Ssam 29437728Smckusick if ((unsigned)uap->fdes >= NOFILE || 29537728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 29637728Smckusick RETURN (EBADF); 29713044Ssam switch (fp->f_type) { 29813044Ssam 29937728Smckusick case DTYPE_VNODE: 30042863Smckusick error = vn_stat((struct vnode *)fp->f_data, &ub); 30113044Ssam break; 30213044Ssam 30313044Ssam case DTYPE_SOCKET: 30442863Smckusick error = soo_stat((struct socket *)fp->f_data, &ub); 30513044Ssam break; 30613044Ssam 30713044Ssam default: 30813044Ssam panic("fstat"); 30913044Ssam /*NOTREACHED*/ 31013044Ssam } 31142863Smckusick if (error == 0) 31242863Smckusick error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); 31342863Smckusick RETURN (error); 31413044Ssam } 31513044Ssam 3167422Sroot /* 3177497Sroot * Allocate a user file descriptor. 3187422Sroot */ 31937728Smckusick ufalloc(want, result) 32037728Smckusick register int want; 32137728Smckusick int *result; 3227422Sroot { 3237497Sroot 32439733Smckusick for (; want < NOFILE; want++) { 32537728Smckusick if (u.u_ofile[want] == NULL) { 32637728Smckusick u.u_pofile[want] = 0; 32737728Smckusick if (want > u.u_lastfile) 32837728Smckusick u.u_lastfile = want; 32939733Smckusick *result = want; 33037728Smckusick return (0); 3317497Sroot } 33239733Smckusick } 33337728Smckusick return (EMFILE); 3347497Sroot } 3357497Sroot 33642863Smckusick /* 33742863Smckusick * Check to see if any user file descriptors are available. 33842863Smckusick */ 33912748Ssam ufavail() 34012748Ssam { 34112748Ssam register int i, avail = 0; 34212748Ssam 34312748Ssam for (i = 0; i < NOFILE; i++) 34412748Ssam if (u.u_ofile[i] == NULL) 34512748Ssam avail++; 34612748Ssam return (avail); 34712748Ssam } 34812748Ssam 3497497Sroot struct file *lastf; 3507497Sroot /* 3517497Sroot * Allocate a user file descriptor 3527497Sroot * and a file structure. 3537497Sroot * Initialize the descriptor 3547497Sroot * to point at the file structure. 3557497Sroot */ 35637728Smckusick falloc(resultfp, resultfd) 35737728Smckusick struct file **resultfp; 35837728Smckusick int *resultfd; 3597497Sroot { 3607422Sroot register struct file *fp; 36137728Smckusick int error, i; 3627422Sroot 36337728Smckusick if (error = ufalloc(0, &i)) 36437728Smckusick return (error); 3657497Sroot if (lastf == 0) 3667497Sroot lastf = file; 3677497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3687497Sroot if (fp->f_count == 0) 3697497Sroot goto slot; 3707497Sroot for (fp = file; fp < lastf; fp++) 3717497Sroot if (fp->f_count == 0) 3727497Sroot goto slot; 3737497Sroot tablefull("file"); 37437728Smckusick return (ENFILE); 3757497Sroot slot: 3767497Sroot u.u_ofile[i] = fp; 37712748Ssam fp->f_count = 1; 37812748Ssam fp->f_data = 0; 3797497Sroot fp->f_offset = 0; 38037728Smckusick fp->f_cred = u.u_cred; 38137728Smckusick crhold(fp->f_cred); 3827497Sroot lastf = fp + 1; 38337728Smckusick if (resultfp) 38437728Smckusick *resultfp = fp; 38537728Smckusick if (resultfd) 38637728Smckusick *resultfd = i; 38737728Smckusick return (0); 3887497Sroot } 38912748Ssam 3907497Sroot /* 3917497Sroot * Internal form of close. 39212748Ssam * Decrement reference count on file structure. 3937497Sroot */ 39413044Ssam closef(fp) 3957497Sroot register struct file *fp; 3967497Sroot { 39739354Smckusick int error; 3987497Sroot 3997422Sroot if (fp == NULL) 40039354Smckusick return (0); 4017497Sroot if (fp->f_count > 1) { 4027497Sroot fp->f_count--; 40339354Smckusick return (0); 4047422Sroot } 40537728Smckusick if (fp->f_count < 1) 40637728Smckusick panic("closef: count < 1"); 40739354Smckusick error = (*fp->f_ops->fo_close)(fp); 40837728Smckusick crfree(fp->f_cred); 4097497Sroot fp->f_count = 0; 41039354Smckusick return (error); 4117422Sroot } 41213044Ssam 41313044Ssam /* 41413044Ssam * Apply an advisory lock on a file descriptor. 41513044Ssam */ 41642863Smckusick /* ARGSUSED */ 41742863Smckusick flock(p, uap, retval) 41842863Smckusick struct proc *p; 41942863Smckusick register struct args { 42037728Smckusick int fdes; 42113044Ssam int how; 42242863Smckusick } *uap; 42342863Smckusick int *retval; 42442863Smckusick { 42513044Ssam register struct file *fp; 42613044Ssam 42737728Smckusick if ((unsigned)uap->fdes >= NOFILE || 42837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 42937728Smckusick RETURN (EBADF); 43042863Smckusick if (fp->f_type != DTYPE_VNODE) 43142863Smckusick RETURN (EOPNOTSUPP); 43213101Ssam if (uap->how & LOCK_UN) { 43337728Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 43442863Smckusick RETURN (0); 43513044Ssam } 43617434Skarels if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 43742863Smckusick RETURN (0); /* error? */ 43817998Skarels if (uap->how & LOCK_EX) 43917998Skarels uap->how &= ~LOCK_SH; 44013101Ssam /* avoid work... */ 44117998Skarels if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 44217998Skarels (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 44342863Smckusick RETURN (0); 44442863Smckusick RETURN (vn_lock(fp, uap->how)); 44513044Ssam } 44637586Smarc 44737586Smarc /* 44837586Smarc * File Descriptor pseudo-device driver (/dev/fd/). 44937586Smarc * 45037586Smarc * Opening minor device N dup()s the file (if any) connected to file 45137586Smarc * descriptor N belonging to the calling process. Note that this driver 45237586Smarc * consists of only the ``open()'' routine, because all subsequent 45337586Smarc * references to this file will be direct to the other driver. 45437586Smarc */ 45537728Smckusick /* ARGSUSED */ 45637728Smckusick fdopen(dev, mode, type) 45737586Smarc dev_t dev; 45837728Smckusick int mode, type; 45937586Smarc { 460*43406Smckusick struct proc *p = u.u_procp; /* XXX */ 46137586Smarc 46237586Smarc /* 463*43406Smckusick * XXX Kludge: set p->p_devtmp to contain the value of the 464*43406Smckusick * the file descriptor being sought for duplication. The error 465*43406Smckusick * return ensures that the vnode for this device will be released 466*43406Smckusick * by vn_open. Open will detect this special error and take the 467*43406Smckusick * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 468*43406Smckusick * will simply report the error. 46937586Smarc */ 470*43406Smckusick p->p_devtmp = minor(dev); 471*43406Smckusick return (ENODEV); 472*43406Smckusick } 47340873Sbostic 474*43406Smckusick /* 475*43406Smckusick * Duplicate the specified descriptor to a free descriptor. 476*43406Smckusick */ 477*43406Smckusick dupfdopen(indx, dfd, mode) 478*43406Smckusick register int indx, dfd; 479*43406Smckusick int mode; 480*43406Smckusick { 481*43406Smckusick register struct file *wfp; 482*43406Smckusick struct file *fp; 483*43406Smckusick 48437586Smarc /* 485*43406Smckusick * If the to-be-dup'd fd number is greater than the allowed number 486*43406Smckusick * of file descriptors, or the fd to be dup'd has already been 487*43406Smckusick * closed, reject. Note, check for new == old is necessary as 488*43406Smckusick * falloc could allocate an already closed to-be-dup'd descriptor 489*43406Smckusick * as the new descriptor. 49037586Smarc */ 491*43406Smckusick fp = u.u_ofile[indx]; 49240873Sbostic if ((u_int)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL || 49340873Sbostic fp == wfp) 49437586Smarc return (EBADF); 49540873Sbostic 49637586Smarc /* 49740873Sbostic * Check that the mode the file is being opened for is a subset 49840873Sbostic * of the mode of the existing descriptor. 49937586Smarc */ 500*43406Smckusick if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 50137586Smarc return (EACCES); 50242863Smckusick u.u_ofile[indx] = wfp; 50342863Smckusick u.u_pofile[indx] = u.u_pofile[dfd]; 50442863Smckusick wfp->f_count++; 50542863Smckusick if (indx > u.u_lastfile) 50642863Smckusick u.u_lastfile = indx; 507*43406Smckusick return (0); 50837586Smarc } 509