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*44404Skarels * @(#)kern_descrip.c 7.15 (Berkeley) 06/28/90 1823367Smckusick */ 197422Sroot 2017089Sbloom #include "param.h" 2117089Sbloom #include "systm.h" 22*44404Skarels #include "user.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 327422Sroot /* 337497Sroot * Descriptor management. 347422Sroot */ 357497Sroot 367497Sroot /* 377497Sroot * System calls on descriptors. 387497Sroot */ 3942863Smckusick /* ARGSUSED */ 4042863Smckusick getdtablesize(p, uap, retval) 4142863Smckusick struct proc *p; 4242863Smckusick struct args *uap; 4342863Smckusick int *retval; 447497Sroot { 457497Sroot 4642863Smckusick *retval = NOFILE; 47*44404Skarels return (0); 487497Sroot } 497497Sroot 5042863Smckusick /* 5142863Smckusick * Duplicate a file descriptor. 5242863Smckusick */ 5342863Smckusick /* ARGSUSED */ 5442863Smckusick dup(p, uap, retval) 5542863Smckusick struct proc *p; 5642863Smckusick struct args { 5742863Smckusick int i; 5842863Smckusick } *uap; 5942863Smckusick int *retval; 607422Sroot { 617696Ssam struct file *fp; 6242863Smckusick int fd, error; 637497Sroot 6442863Smckusick /* 6542863Smckusick * XXX Compatibility 6642863Smckusick */ 67*44404Skarels if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); } 687497Sroot 6937728Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 70*44404Skarels return (EBADF); 7142863Smckusick if (error = ufalloc(0, &fd)) 72*44404Skarels return (error); 7342863Smckusick u.u_ofile[fd] = fp; 7442863Smckusick u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 7542863Smckusick fp->f_count++; 7642863Smckusick if (fd > u.u_lastfile) 7742863Smckusick u.u_lastfile = fd; 7842863Smckusick *retval = fd; 79*44404Skarels return (0); 807497Sroot } 817497Sroot 8242863Smckusick /* 8342863Smckusick * Duplicate a file descriptor to a particular value. 8442863Smckusick */ 8542863Smckusick /* ARGSUSED */ 8642863Smckusick dup2(p, uap, retval) 8742863Smckusick struct proc *p; 8842863Smckusick register struct args { 8942863Smckusick int i; 9042863Smckusick int j; 9142863Smckusick } *uap; 9242863Smckusick int *retval; 937497Sroot { 947497Sroot register struct file *fp; 9539354Smckusick int error; 967422Sroot 9737728Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 98*44404Skarels return (EBADF); 9939354Smckusick if (uap->j < 0 || uap->j >= NOFILE) 100*44404Skarels return (EBADF); 10142863Smckusick *retval = uap->j; 1027497Sroot if (uap->i == uap->j) 103*44404Skarels return (0); 1047497Sroot if (u.u_ofile[uap->j]) { 1058945Sroot if (u.u_pofile[uap->j] & UF_MAPPED) 1068945Sroot munmapfd(uap->j); 10739354Smckusick error = closef(u.u_ofile[uap->j]); 1087422Sroot } 10942863Smckusick u.u_ofile[uap->j] = fp; 11042863Smckusick u.u_pofile[uap->j] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 11142863Smckusick fp->f_count++; 11242863Smckusick if (uap->j > u.u_lastfile) 11342863Smckusick u.u_lastfile = uap->j; 11439354Smckusick /* 11539354Smckusick * dup2() must succeed even though the close had an error. 11639354Smckusick */ 11739354Smckusick error = 0; /* XXX */ 118*44404Skarels return (error); 1197696Ssam } 1207696Ssam 12112748Ssam /* 12212748Ssam * The file control system call. 12312748Ssam */ 12442863Smckusick /* ARGSUSED */ 12542863Smckusick fcntl(p, uap, retval) 12642863Smckusick struct proc *p; 12742863Smckusick register struct args { 12812748Ssam int fdes; 12912748Ssam int cmd; 13012748Ssam int arg; 13142863Smckusick } *uap; 13242863Smckusick int *retval; 13342863Smckusick { 13442863Smckusick register struct file *fp; 13512748Ssam register char *pop; 13642863Smckusick int i, error; 1377497Sroot 13837728Smckusick if ((unsigned)uap->fdes >= NOFILE || 13937728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 140*44404Skarels return (EBADF); 14112748Ssam pop = &u.u_pofile[uap->fdes]; 14212748Ssam switch(uap->cmd) { 14315076Skarels case F_DUPFD: 14442863Smckusick if (uap->arg < 0 || uap->arg >= NOFILE) 145*44404Skarels return (EINVAL); 14642863Smckusick if (error = ufalloc(uap->arg, &i)) 147*44404Skarels return (error); 14842863Smckusick u.u_ofile[i] = fp; 14942863Smckusick u.u_pofile[i] = *pop &~ UF_EXCLOSE; 15042863Smckusick fp->f_count++; 15142863Smckusick if (i > u.u_lastfile) 15242863Smckusick u.u_lastfile = i; 15342863Smckusick *retval = i; 154*44404Skarels return (0); 1557497Sroot 15615076Skarels case F_GETFD: 15742863Smckusick *retval = *pop & 1; 158*44404Skarels return (0); 1597422Sroot 16015076Skarels case F_SETFD: 16112748Ssam *pop = (*pop &~ 1) | (uap->arg & 1); 162*44404Skarels return (0); 1638145Sroot 16415076Skarels case F_GETFL: 16542863Smckusick *retval = fp->f_flag + FOPEN; 166*44404Skarels return (0); 1678145Sroot 16815076Skarels case F_SETFL: 16912748Ssam fp->f_flag &= FCNTLCANT; 17012748Ssam fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 17142863Smckusick if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY)) 172*44404Skarels return (error); 17342863Smckusick if (error = fset(fp, FASYNC, fp->f_flag & FASYNC)) 17412748Ssam (void) fset(fp, FNDELAY, 0); 175*44404Skarels return (error); 1767422Sroot 17715076Skarels case F_GETOWN: 178*44404Skarels return (fgetown(fp, retval)); 1797422Sroot 18015076Skarels case F_SETOWN: 181*44404Skarels return (fsetown(fp, uap->arg)); 1828115Sroot 18312748Ssam default: 184*44404Skarels return (EINVAL); 1857422Sroot } 18642863Smckusick /* NOTREACHED */ 1877422Sroot } 1887422Sroot 18912748Ssam fset(fp, bit, value) 19012748Ssam struct file *fp; 19112748Ssam int bit, value; 1927422Sroot { 1937422Sroot 19412748Ssam if (value) 19512748Ssam fp->f_flag |= bit; 19612748Ssam else 19712748Ssam fp->f_flag &= ~bit; 19812748Ssam return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 19912748Ssam (caddr_t)&value)); 20012748Ssam } 2017422Sroot 20212748Ssam fgetown(fp, valuep) 20312748Ssam struct file *fp; 20412748Ssam int *valuep; 20512748Ssam { 20612748Ssam int error; 2078115Sroot 20812748Ssam switch (fp->f_type) { 2098115Sroot 21012748Ssam case DTYPE_SOCKET: 21135810Smarc *valuep = ((struct socket *)fp->f_data)->so_pgid; 21212748Ssam return (0); 2137497Sroot 21412748Ssam default: 21512748Ssam error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 21612748Ssam *valuep = -*valuep; 21712748Ssam return (error); 2187422Sroot } 2197422Sroot } 2207422Sroot 22112748Ssam fsetown(fp, value) 22212748Ssam struct file *fp; 22312748Ssam int value; 2247422Sroot { 22537728Smckusick 22612748Ssam if (fp->f_type == DTYPE_SOCKET) { 22735810Smarc ((struct socket *)fp->f_data)->so_pgid = value; 22812748Ssam return (0); 22912748Ssam } 23012748Ssam if (value > 0) { 23112748Ssam struct proc *p = pfind(value); 23212748Ssam if (p == 0) 23328201Skarels return (ESRCH); 23435810Smarc value = p->p_pgrp->pg_id; 23512748Ssam } else 23612748Ssam value = -value; 23712748Ssam return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 2387422Sroot } 2397422Sroot 24012748Ssam fioctl(fp, cmd, value) 24112748Ssam struct file *fp; 24212748Ssam int cmd; 24312748Ssam caddr_t value; 2447422Sroot { 2457422Sroot 24612748Ssam return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 2477422Sroot } 2487422Sroot 24942863Smckusick /* 25042863Smckusick * Close a file descriptor. 25142863Smckusick */ 25242863Smckusick /* ARGSUSED */ 25342863Smckusick close(p, uap, retval) 25442863Smckusick struct proc *p; 25542863Smckusick struct args { 25642863Smckusick int fdes; 25742863Smckusick } *uap; 25842863Smckusick int *retval; 2598029Sroot { 26012748Ssam register struct file *fp; 26113044Ssam register u_char *pf; 2628029Sroot 26337728Smckusick if ((unsigned)uap->fdes >= NOFILE || 26437728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 265*44404Skarels return (EBADF); 26637728Smckusick pf = (u_char *)&u.u_pofile[uap->fdes]; 26713044Ssam if (*pf & UF_MAPPED) 26837728Smckusick munmapfd(uap->fdes); 26937728Smckusick u.u_ofile[uap->fdes] = NULL; 27021101Skarels while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 27121101Skarels u.u_lastfile--; 27215550Skarels *pf = 0; 273*44404Skarels return (closef(fp)); 2748029Sroot } 2758029Sroot 27642863Smckusick /* 27742863Smckusick * Return status information about a file descriptor. 27842863Smckusick */ 27942863Smckusick /* ARGSUSED */ 28042863Smckusick fstat(p, uap, retval) 28142863Smckusick struct proc *p; 28242863Smckusick register struct args { 28342863Smckusick int fdes; 28442863Smckusick struct stat *sb; 28542863Smckusick } *uap; 28642863Smckusick int *retval; 28713044Ssam { 28813044Ssam register struct file *fp; 28913044Ssam struct stat ub; 29042863Smckusick int error; 29113044Ssam 29237728Smckusick if ((unsigned)uap->fdes >= NOFILE || 29337728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 294*44404Skarels return (EBADF); 29513044Ssam switch (fp->f_type) { 29613044Ssam 29737728Smckusick case DTYPE_VNODE: 29842863Smckusick error = vn_stat((struct vnode *)fp->f_data, &ub); 29913044Ssam break; 30013044Ssam 30113044Ssam case DTYPE_SOCKET: 30242863Smckusick error = soo_stat((struct socket *)fp->f_data, &ub); 30313044Ssam break; 30413044Ssam 30513044Ssam default: 30613044Ssam panic("fstat"); 30713044Ssam /*NOTREACHED*/ 30813044Ssam } 30942863Smckusick if (error == 0) 31042863Smckusick error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); 311*44404Skarels return (error); 31213044Ssam } 31313044Ssam 3147422Sroot /* 3157497Sroot * Allocate a user file descriptor. 3167422Sroot */ 31737728Smckusick ufalloc(want, result) 31837728Smckusick register int want; 31937728Smckusick int *result; 3207422Sroot { 3217497Sroot 32239733Smckusick for (; want < NOFILE; want++) { 32337728Smckusick if (u.u_ofile[want] == NULL) { 32437728Smckusick u.u_pofile[want] = 0; 32537728Smckusick if (want > u.u_lastfile) 32637728Smckusick u.u_lastfile = want; 32739733Smckusick *result = want; 32837728Smckusick return (0); 3297497Sroot } 33039733Smckusick } 33137728Smckusick return (EMFILE); 3327497Sroot } 3337497Sroot 33442863Smckusick /* 33542863Smckusick * Check to see if any user file descriptors are available. 33642863Smckusick */ 33712748Ssam ufavail() 33812748Ssam { 33912748Ssam register int i, avail = 0; 34012748Ssam 34112748Ssam for (i = 0; i < NOFILE; i++) 34212748Ssam if (u.u_ofile[i] == NULL) 34312748Ssam avail++; 34412748Ssam return (avail); 34512748Ssam } 34612748Ssam 3477497Sroot struct file *lastf; 3487497Sroot /* 3497497Sroot * Allocate a user file descriptor 3507497Sroot * and a file structure. 3517497Sroot * Initialize the descriptor 3527497Sroot * to point at the file structure. 3537497Sroot */ 35437728Smckusick falloc(resultfp, resultfd) 35537728Smckusick struct file **resultfp; 35637728Smckusick int *resultfd; 3577497Sroot { 3587422Sroot register struct file *fp; 35937728Smckusick int error, i; 3607422Sroot 36137728Smckusick if (error = ufalloc(0, &i)) 36237728Smckusick return (error); 3637497Sroot if (lastf == 0) 3647497Sroot lastf = file; 3657497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3667497Sroot if (fp->f_count == 0) 3677497Sroot goto slot; 3687497Sroot for (fp = file; fp < lastf; fp++) 3697497Sroot if (fp->f_count == 0) 3707497Sroot goto slot; 3717497Sroot tablefull("file"); 37237728Smckusick return (ENFILE); 3737497Sroot slot: 3747497Sroot u.u_ofile[i] = fp; 37512748Ssam fp->f_count = 1; 37612748Ssam fp->f_data = 0; 3777497Sroot fp->f_offset = 0; 37837728Smckusick fp->f_cred = u.u_cred; 37937728Smckusick crhold(fp->f_cred); 3807497Sroot lastf = fp + 1; 38137728Smckusick if (resultfp) 38237728Smckusick *resultfp = fp; 38337728Smckusick if (resultfd) 38437728Smckusick *resultfd = i; 38537728Smckusick return (0); 3867497Sroot } 38712748Ssam 3887497Sroot /* 3897497Sroot * Internal form of close. 39012748Ssam * Decrement reference count on file structure. 3917497Sroot */ 39213044Ssam closef(fp) 3937497Sroot register struct file *fp; 3947497Sroot { 39539354Smckusick int error; 3967497Sroot 3977422Sroot if (fp == NULL) 39839354Smckusick return (0); 3997497Sroot if (fp->f_count > 1) { 4007497Sroot fp->f_count--; 40139354Smckusick return (0); 4027422Sroot } 40337728Smckusick if (fp->f_count < 1) 40437728Smckusick panic("closef: count < 1"); 40539354Smckusick error = (*fp->f_ops->fo_close)(fp); 40637728Smckusick crfree(fp->f_cred); 4077497Sroot fp->f_count = 0; 40839354Smckusick return (error); 4097422Sroot } 41013044Ssam 41113044Ssam /* 41213044Ssam * Apply an advisory lock on a file descriptor. 41313044Ssam */ 41442863Smckusick /* ARGSUSED */ 41542863Smckusick flock(p, uap, retval) 41642863Smckusick struct proc *p; 41742863Smckusick register struct args { 41837728Smckusick int fdes; 41913044Ssam int how; 42042863Smckusick } *uap; 42142863Smckusick int *retval; 42242863Smckusick { 42313044Ssam register struct file *fp; 42413044Ssam 42537728Smckusick if ((unsigned)uap->fdes >= NOFILE || 42637728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 427*44404Skarels return (EBADF); 42842863Smckusick if (fp->f_type != DTYPE_VNODE) 429*44404Skarels return (EOPNOTSUPP); 43013101Ssam if (uap->how & LOCK_UN) { 43137728Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 432*44404Skarels return (0); 43313044Ssam } 43417434Skarels if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 435*44404Skarels return (0); /* error? */ 43617998Skarels if (uap->how & LOCK_EX) 43717998Skarels uap->how &= ~LOCK_SH; 43813101Ssam /* avoid work... */ 43917998Skarels if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 44017998Skarels (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 441*44404Skarels return (0); 442*44404Skarels return (vn_lock(fp, uap->how)); 44313044Ssam } 44437586Smarc 44537586Smarc /* 44637586Smarc * File Descriptor pseudo-device driver (/dev/fd/). 44737586Smarc * 44837586Smarc * Opening minor device N dup()s the file (if any) connected to file 44937586Smarc * descriptor N belonging to the calling process. Note that this driver 45037586Smarc * consists of only the ``open()'' routine, because all subsequent 45137586Smarc * references to this file will be direct to the other driver. 45237586Smarc */ 45337728Smckusick /* ARGSUSED */ 45437728Smckusick fdopen(dev, mode, type) 45537586Smarc dev_t dev; 45637728Smckusick int mode, type; 45737586Smarc { 45843406Smckusick struct proc *p = u.u_procp; /* XXX */ 45937586Smarc 46037586Smarc /* 46143449Smckusick * XXX Kludge: set p->p_dupfd to contain the value of the 46243406Smckusick * the file descriptor being sought for duplication. The error 46343406Smckusick * return ensures that the vnode for this device will be released 46443406Smckusick * by vn_open. Open will detect this special error and take the 46543406Smckusick * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 46643406Smckusick * will simply report the error. 46737586Smarc */ 46843449Smckusick p->p_dupfd = minor(dev); 46943406Smckusick return (ENODEV); 47043406Smckusick } 47140873Sbostic 47243406Smckusick /* 47343406Smckusick * Duplicate the specified descriptor to a free descriptor. 47443406Smckusick */ 47543406Smckusick dupfdopen(indx, dfd, mode) 47643406Smckusick register int indx, dfd; 47743406Smckusick int mode; 47843406Smckusick { 47943406Smckusick register struct file *wfp; 48043406Smckusick struct file *fp; 48143406Smckusick 48237586Smarc /* 48343406Smckusick * If the to-be-dup'd fd number is greater than the allowed number 48443406Smckusick * of file descriptors, or the fd to be dup'd has already been 48543406Smckusick * closed, reject. Note, check for new == old is necessary as 48643406Smckusick * falloc could allocate an already closed to-be-dup'd descriptor 48743406Smckusick * as the new descriptor. 48837586Smarc */ 48943406Smckusick fp = u.u_ofile[indx]; 49040873Sbostic if ((u_int)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL || 49140873Sbostic fp == wfp) 49237586Smarc return (EBADF); 49340873Sbostic 49437586Smarc /* 49540873Sbostic * Check that the mode the file is being opened for is a subset 49640873Sbostic * of the mode of the existing descriptor. 49737586Smarc */ 49843406Smckusick if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 49937586Smarc return (EACCES); 50042863Smckusick u.u_ofile[indx] = wfp; 50142863Smckusick u.u_pofile[indx] = u.u_pofile[dfd]; 50242863Smckusick wfp->f_count++; 50342863Smckusick if (indx > u.u_lastfile) 50442863Smckusick u.u_lastfile = indx; 50543406Smckusick return (0); 50637586Smarc } 507