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*40873Sbostic * @(#)kern_descrip.c 7.10 (Berkeley) 04/10/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 "mount.h" 3017089Sbloom #include "stat.h" 317422Sroot 3217089Sbloom #include "ioctl.h" 337497Sroot 347422Sroot /* 357497Sroot * Descriptor management. 367422Sroot */ 377497Sroot 387497Sroot /* 397497Sroot * System calls on descriptors. 407497Sroot */ 418029Sroot getdtablesize() 427497Sroot { 437497Sroot 447497Sroot u.u_r.r_val1 = NOFILE; 457497Sroot } 467497Sroot 477422Sroot dup() 487422Sroot { 497497Sroot register struct a { 507497Sroot int i; 517497Sroot } *uap = (struct a *) u.u_ap; 527696Ssam struct file *fp; 537696Ssam int j; 547497Sroot 557497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 567497Sroot 5737728Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 5837728Smckusick RETURN (EBADF); 5937728Smckusick if (u.u_error = ufalloc(0, &j)) 607497Sroot return; 6137728Smckusick u.u_r.r_val1 = j; 6217435Skarels dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 637497Sroot } 647497Sroot 657497Sroot dup2() 667497Sroot { 677422Sroot register struct a { 687497Sroot int i, j; 697497Sroot } *uap = (struct a *) u.u_ap; 707497Sroot register struct file *fp; 7139354Smckusick int error; 727422Sroot 7337728Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 7437728Smckusick RETURN (EBADF); 7539354Smckusick if (uap->j < 0 || uap->j >= NOFILE) 7639354Smckusick RETURN (EBADF); 777497Sroot u.u_r.r_val1 = uap->j; 787497Sroot if (uap->i == uap->j) 7939354Smckusick RETURN (0); 807497Sroot if (u.u_ofile[uap->j]) { 818945Sroot if (u.u_pofile[uap->j] & UF_MAPPED) 828945Sroot munmapfd(uap->j); 8339354Smckusick error = closef(u.u_ofile[uap->j]); 847422Sroot } 8517435Skarels dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 8639354Smckusick /* 8739354Smckusick * dup2() must succeed even though the close had an error. 8839354Smckusick */ 8939354Smckusick error = 0; /* XXX */ 9039354Smckusick RETURN (error); 917696Ssam } 927696Ssam 9313101Ssam dupit(fd, fp, flags) 947696Ssam int fd; 957696Ssam register struct file *fp; 9613101Ssam register int flags; 977696Ssam { 987696Ssam 997696Ssam u.u_ofile[fd] = fp; 10013101Ssam u.u_pofile[fd] = flags; 1017497Sroot fp->f_count++; 10221101Skarels if (fd > u.u_lastfile) 10321101Skarels u.u_lastfile = fd; 1047422Sroot } 1057422Sroot 10612748Ssam /* 10712748Ssam * The file control system call. 10812748Ssam */ 10912748Ssam fcntl() 1107497Sroot { 1117497Sroot register struct file *fp; 1127497Sroot register struct a { 11312748Ssam int fdes; 11412748Ssam int cmd; 11512748Ssam int arg; 11637728Smckusick } *uap = (struct a *)u.u_ap; 11712748Ssam register char *pop; 11837728Smckusick int i; 1197497Sroot 12037728Smckusick if ((unsigned)uap->fdes >= NOFILE || 12137728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 12237728Smckusick RETURN (EBADF); 12312748Ssam pop = &u.u_pofile[uap->fdes]; 12412748Ssam switch(uap->cmd) { 12515076Skarels case F_DUPFD: 12637728Smckusick if (uap->arg < 0 || uap->arg >= NOFILE) { 12712748Ssam u.u_error = EINVAL; 12812748Ssam return; 12912748Ssam } 13037728Smckusick if (u.u_error = ufalloc(uap->arg, &i)) 13112748Ssam return; 13237728Smckusick u.u_r.r_val1 = i; 13317435Skarels dupit(i, fp, *pop &~ UF_EXCLOSE); 13412748Ssam break; 1357497Sroot 13615076Skarels case F_GETFD: 13712748Ssam u.u_r.r_val1 = *pop & 1; 13812748Ssam break; 1397422Sroot 14015076Skarels case F_SETFD: 14112748Ssam *pop = (*pop &~ 1) | (uap->arg & 1); 14212748Ssam break; 1438145Sroot 14415076Skarels case F_GETFL: 14512748Ssam u.u_r.r_val1 = fp->f_flag+FOPEN; 14612748Ssam break; 1478145Sroot 14815076Skarels case F_SETFL: 14912748Ssam fp->f_flag &= FCNTLCANT; 15012748Ssam fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 15112748Ssam u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 1529995Ssam if (u.u_error) 15312748Ssam break; 15412748Ssam u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 15512748Ssam if (u.u_error) 15612748Ssam (void) fset(fp, FNDELAY, 0); 15712748Ssam break; 1587422Sroot 15915076Skarels case F_GETOWN: 16015076Skarels u.u_error = fgetown(fp, &u.u_r.r_val1); 16112748Ssam break; 1627422Sroot 16315076Skarels case F_SETOWN: 16415076Skarels u.u_error = fsetown(fp, uap->arg); 1657422Sroot break; 1668115Sroot 16712748Ssam default: 16812748Ssam u.u_error = EINVAL; 1697422Sroot } 1707422Sroot } 1717422Sroot 17212748Ssam fset(fp, bit, value) 17312748Ssam struct file *fp; 17412748Ssam int bit, value; 1757422Sroot { 1767422Sroot 17712748Ssam if (value) 17812748Ssam fp->f_flag |= bit; 17912748Ssam else 18012748Ssam fp->f_flag &= ~bit; 18112748Ssam return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 18212748Ssam (caddr_t)&value)); 18312748Ssam } 1847422Sroot 18512748Ssam fgetown(fp, valuep) 18612748Ssam struct file *fp; 18712748Ssam int *valuep; 18812748Ssam { 18912748Ssam int error; 1908115Sroot 19112748Ssam switch (fp->f_type) { 1928115Sroot 19312748Ssam case DTYPE_SOCKET: 19435810Smarc *valuep = ((struct socket *)fp->f_data)->so_pgid; 19512748Ssam return (0); 1967497Sroot 19712748Ssam default: 19812748Ssam error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 19912748Ssam *valuep = -*valuep; 20012748Ssam return (error); 2017422Sroot } 2027422Sroot } 2037422Sroot 20412748Ssam fsetown(fp, value) 20512748Ssam struct file *fp; 20612748Ssam int value; 2077422Sroot { 20837728Smckusick 20912748Ssam if (fp->f_type == DTYPE_SOCKET) { 21035810Smarc ((struct socket *)fp->f_data)->so_pgid = value; 21112748Ssam return (0); 21212748Ssam } 21312748Ssam if (value > 0) { 21412748Ssam struct proc *p = pfind(value); 21512748Ssam if (p == 0) 21628201Skarels return (ESRCH); 21735810Smarc value = p->p_pgrp->pg_id; 21812748Ssam } else 21912748Ssam value = -value; 22012748Ssam return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 2217422Sroot } 2227422Sroot 22312748Ssam fioctl(fp, cmd, value) 22412748Ssam struct file *fp; 22512748Ssam int cmd; 22612748Ssam caddr_t value; 2277422Sroot { 2287422Sroot 22912748Ssam return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 2307422Sroot } 2317422Sroot 23212748Ssam close() 2338029Sroot { 23421101Skarels struct a { 23537728Smckusick int fdes; 23612748Ssam } *uap = (struct a *)u.u_ap; 23712748Ssam register struct file *fp; 23813044Ssam register u_char *pf; 2398029Sroot 24037728Smckusick if ((unsigned)uap->fdes >= NOFILE || 24137728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 24237728Smckusick RETURN (EBADF); 24337728Smckusick pf = (u_char *)&u.u_pofile[uap->fdes]; 24413044Ssam if (*pf & UF_MAPPED) 24537728Smckusick munmapfd(uap->fdes); 24637728Smckusick u.u_ofile[uap->fdes] = NULL; 24721101Skarels while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 24821101Skarels u.u_lastfile--; 24915550Skarels *pf = 0; 25039354Smckusick RETURN (closef(fp)); 2518029Sroot } 2528029Sroot 25313044Ssam fstat() 25413044Ssam { 25513044Ssam register struct file *fp; 25613044Ssam register struct a { 25713044Ssam int fdes; 25813044Ssam struct stat *sb; 25937728Smckusick } *uap = (struct a *)u.u_ap; 26013044Ssam struct stat ub; 26113044Ssam 26237728Smckusick if ((unsigned)uap->fdes >= NOFILE || 26337728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 26437728Smckusick RETURN (EBADF); 26513044Ssam switch (fp->f_type) { 26613044Ssam 26737728Smckusick case DTYPE_VNODE: 26837728Smckusick u.u_error = vn_stat((struct vnode *)fp->f_data, &ub); 26913044Ssam break; 27013044Ssam 27113044Ssam case DTYPE_SOCKET: 27213044Ssam u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 27313044Ssam break; 27413044Ssam 27513044Ssam default: 27613044Ssam panic("fstat"); 27713044Ssam /*NOTREACHED*/ 27813044Ssam } 27913044Ssam if (u.u_error == 0) 28013101Ssam u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 28113101Ssam sizeof (ub)); 28213044Ssam } 28313044Ssam 2847422Sroot /* 2857497Sroot * Allocate a user file descriptor. 2867422Sroot */ 28737728Smckusick ufalloc(want, result) 28837728Smckusick register int want; 28937728Smckusick int *result; 2907422Sroot { 2917497Sroot 29239733Smckusick for (; want < NOFILE; want++) { 29337728Smckusick if (u.u_ofile[want] == NULL) { 29437728Smckusick u.u_pofile[want] = 0; 29537728Smckusick if (want > u.u_lastfile) 29637728Smckusick u.u_lastfile = want; 29739733Smckusick *result = want; 29837728Smckusick return (0); 2997497Sroot } 30039733Smckusick } 30137728Smckusick return (EMFILE); 3027497Sroot } 3037497Sroot 30412748Ssam ufavail() 30512748Ssam { 30612748Ssam register int i, avail = 0; 30712748Ssam 30812748Ssam for (i = 0; i < NOFILE; i++) 30912748Ssam if (u.u_ofile[i] == NULL) 31012748Ssam avail++; 31112748Ssam return (avail); 31212748Ssam } 31312748Ssam 3147497Sroot struct file *lastf; 3157497Sroot /* 3167497Sroot * Allocate a user file descriptor 3177497Sroot * and a file structure. 3187497Sroot * Initialize the descriptor 3197497Sroot * to point at the file structure. 3207497Sroot */ 32137728Smckusick falloc(resultfp, resultfd) 32237728Smckusick struct file **resultfp; 32337728Smckusick int *resultfd; 3247497Sroot { 3257422Sroot register struct file *fp; 32637728Smckusick int error, i; 3277422Sroot 32837728Smckusick if (error = ufalloc(0, &i)) 32937728Smckusick return (error); 3307497Sroot if (lastf == 0) 3317497Sroot lastf = file; 3327497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3337497Sroot if (fp->f_count == 0) 3347497Sroot goto slot; 3357497Sroot for (fp = file; fp < lastf; fp++) 3367497Sroot if (fp->f_count == 0) 3377497Sroot goto slot; 3387497Sroot tablefull("file"); 33937728Smckusick return (ENFILE); 3407497Sroot slot: 3417497Sroot u.u_ofile[i] = fp; 34212748Ssam fp->f_count = 1; 34312748Ssam fp->f_data = 0; 3447497Sroot fp->f_offset = 0; 34537728Smckusick fp->f_cred = u.u_cred; 34637728Smckusick crhold(fp->f_cred); 3477497Sroot lastf = fp + 1; 34837728Smckusick if (resultfp) 34937728Smckusick *resultfp = fp; 35037728Smckusick if (resultfd) 35137728Smckusick *resultfd = i; 35237728Smckusick return (0); 3537497Sroot } 35412748Ssam 3557497Sroot /* 3567497Sroot * Internal form of close. 35712748Ssam * Decrement reference count on file structure. 3587497Sroot */ 35913044Ssam closef(fp) 3607497Sroot register struct file *fp; 3617497Sroot { 36239354Smckusick int error; 3637497Sroot 3647422Sroot if (fp == NULL) 36539354Smckusick return (0); 3667497Sroot if (fp->f_count > 1) { 3677497Sroot fp->f_count--; 36839354Smckusick return (0); 3697422Sroot } 37037728Smckusick if (fp->f_count < 1) 37137728Smckusick panic("closef: count < 1"); 37239354Smckusick error = (*fp->f_ops->fo_close)(fp); 37337728Smckusick crfree(fp->f_cred); 3747497Sroot fp->f_count = 0; 37539354Smckusick return (error); 3767422Sroot } 37713044Ssam 37813044Ssam /* 37913044Ssam * Apply an advisory lock on a file descriptor. 38013044Ssam */ 38113044Ssam flock() 38213044Ssam { 38313044Ssam register struct a { 38437728Smckusick int fdes; 38513044Ssam int how; 38613044Ssam } *uap = (struct a *)u.u_ap; 38713044Ssam register struct file *fp; 38813044Ssam 38937728Smckusick if ((unsigned)uap->fdes >= NOFILE || 39037728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 39137728Smckusick RETURN (EBADF); 39237728Smckusick if (fp->f_type != DTYPE_VNODE) { 39313101Ssam u.u_error = EOPNOTSUPP; 39413044Ssam return; 39513044Ssam } 39613101Ssam if (uap->how & LOCK_UN) { 39737728Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 39813044Ssam return; 39913044Ssam } 40017434Skarels if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 40117434Skarels return; /* error? */ 40217998Skarels if (uap->how & LOCK_EX) 40317998Skarels uap->how &= ~LOCK_SH; 40413101Ssam /* avoid work... */ 40517998Skarels if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 40617998Skarels (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 40713044Ssam return; 40837728Smckusick u.u_error = vn_lock(fp, uap->how); 40913044Ssam } 41037586Smarc 41137586Smarc /* 41237586Smarc * File Descriptor pseudo-device driver (/dev/fd/). 41337586Smarc * 41437586Smarc * Fred Blonder - U of Maryland 11-Sep-1984 41537586Smarc * 41637586Smarc * Opening minor device N dup()s the file (if any) connected to file 41737586Smarc * descriptor N belonging to the calling process. Note that this driver 41837586Smarc * consists of only the ``open()'' routine, because all subsequent 41937586Smarc * references to this file will be direct to the other driver. 42037586Smarc */ 42137728Smckusick /* ARGSUSED */ 42237728Smckusick fdopen(dev, mode, type) 42337586Smarc dev_t dev; 42437728Smckusick int mode, type; 42537586Smarc { 42637586Smarc struct file *fp, *wfp; 427*40873Sbostic int indx, dfd; 42837586Smarc 42937586Smarc /* 430*40873Sbostic * XXX 431*40873Sbostic * Horrid kludge: u.u_r.r_val1 contains the value of the new file 432*40873Sbostic * descriptor, which was set before the call to vn_open() by copen() 433*40873Sbostic * in vfs_syscalls.c. 43437586Smarc */ 435*40873Sbostic indx = u.u_r.r_val1; 436*40873Sbostic fp = u.u_ofile[indx]; 437*40873Sbostic 43837586Smarc /* 439*40873Sbostic * File system device minor number is the to-be-dup'd fd number. 440*40873Sbostic * If it is greater than the allowed number of file descriptors, 441*40873Sbostic * or the fd to be dup'd has already been closed, reject. Note, 442*40873Sbostic * check for new == old is necessary as u_falloc could allocate 443*40873Sbostic * an already closed to-be-dup'd descriptor as the new descriptor. 44437586Smarc */ 445*40873Sbostic dfd = minor(dev); 446*40873Sbostic if ((u_int)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL || 447*40873Sbostic fp == wfp) 44837586Smarc return (EBADF); 449*40873Sbostic 45037586Smarc /* 451*40873Sbostic * Check that the mode the file is being opened for is a subset 452*40873Sbostic * of the mode of the existing descriptor. 45337586Smarc */ 454*40873Sbostic if ((mode & (FREAD|FWRITE) | wfp->f_flag) != wfp->f_flag) 45537586Smarc return (EACCES); 45637728Smckusick dupit(indx, wfp, u.u_pofile[dfd]); 457*40873Sbostic 45839498Smckusick /* 459*40873Sbostic * Delete references to this pseudo-device by returning a special 460*40873Sbostic * error (EJUSTRETURN) that will cause all resources to be freed, 461*40873Sbostic * then detected and cleared by copen(). 46239498Smckusick */ 46340704Skarels return (EJUSTRETURN); /* XXX */ 46437586Smarc } 465