1*23367Smckusick /* 2*23367Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23367Smckusick * All rights reserved. The Berkeley software License Agreement 4*23367Smckusick * specifies the terms and conditions for redistribution. 5*23367Smckusick * 6*23367Smckusick * @(#)kern_descrip.c 6.11 (Berkeley) 06/08/85 7*23367Smckusick */ 87422Sroot 917089Sbloom #include "param.h" 1017089Sbloom #include "systm.h" 1117089Sbloom #include "dir.h" 1217089Sbloom #include "user.h" 1317089Sbloom #include "kernel.h" 1417089Sbloom #include "inode.h" 1517089Sbloom #include "proc.h" 1617089Sbloom #include "file.h" 1717089Sbloom #include "socket.h" 1817089Sbloom #include "socketvar.h" 1917089Sbloom #include "mount.h" 2017089Sbloom #include "stat.h" 217422Sroot 2217089Sbloom #include "ioctl.h" 237497Sroot 247422Sroot /* 257497Sroot * Descriptor management. 267422Sroot */ 277497Sroot 287497Sroot /* 297497Sroot * TODO: 3012748Ssam * eliminate u.u_error side effects 317497Sroot */ 327497Sroot 337497Sroot /* 347497Sroot * System calls on descriptors. 357497Sroot */ 368029Sroot getdtablesize() 377497Sroot { 387497Sroot 397497Sroot u.u_r.r_val1 = NOFILE; 407497Sroot } 417497Sroot 428098Sroot getdopt() 438098Sroot { 448098Sroot 458098Sroot } 468098Sroot 478098Sroot setdopt() 488098Sroot { 498098Sroot 508098Sroot } 518098Sroot 527422Sroot dup() 537422Sroot { 547497Sroot register struct a { 557497Sroot int i; 567497Sroot } *uap = (struct a *) u.u_ap; 577696Ssam struct file *fp; 587696Ssam int j; 597497Sroot 607497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 617497Sroot 6217003Smckusick GETF(fp, uap->i); 6312748Ssam j = ufalloc(0); 647497Sroot if (j < 0) 657497Sroot return; 6617435Skarels dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 677497Sroot } 687497Sroot 697497Sroot dup2() 707497Sroot { 717422Sroot register struct a { 727497Sroot int i, j; 737497Sroot } *uap = (struct a *) u.u_ap; 747497Sroot register struct file *fp; 757422Sroot 7617003Smckusick GETF(fp, uap->i); 777497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 787497Sroot u.u_error = EBADF; 797497Sroot return; 807422Sroot } 817497Sroot u.u_r.r_val1 = uap->j; 827497Sroot if (uap->i == uap->j) 837497Sroot return; 847497Sroot if (u.u_ofile[uap->j]) { 858945Sroot if (u.u_pofile[uap->j] & UF_MAPPED) 868945Sroot munmapfd(uap->j); 8713101Ssam closef(u.u_ofile[uap->j]); 887422Sroot if (u.u_error) 897422Sroot return; 907422Sroot } 9117435Skarels dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 927696Ssam } 937696Ssam 9413101Ssam dupit(fd, fp, flags) 957696Ssam int fd; 967696Ssam register struct file *fp; 9713101Ssam register int flags; 987696Ssam { 997696Ssam 1007696Ssam u.u_ofile[fd] = fp; 10113101Ssam u.u_pofile[fd] = flags; 1027497Sroot fp->f_count++; 10321101Skarels if (fd > u.u_lastfile) 10421101Skarels u.u_lastfile = fd; 1057422Sroot } 1067422Sroot 10712748Ssam /* 10812748Ssam * The file control system call. 10912748Ssam */ 11012748Ssam fcntl() 1117497Sroot { 1127497Sroot register struct file *fp; 1137497Sroot register struct a { 11412748Ssam int fdes; 11512748Ssam int cmd; 11612748Ssam int arg; 11712748Ssam } *uap; 11812748Ssam register i; 11912748Ssam register char *pop; 1207497Sroot 12112748Ssam uap = (struct a *)u.u_ap; 12217003Smckusick GETF(fp, uap->fdes); 12312748Ssam pop = &u.u_pofile[uap->fdes]; 12412748Ssam switch(uap->cmd) { 12515076Skarels case F_DUPFD: 12612748Ssam i = uap->arg; 12717434Skarels if (i < 0 || i >= NOFILE) { 12812748Ssam u.u_error = EINVAL; 12912748Ssam return; 13012748Ssam } 13112748Ssam if ((i = ufalloc(i)) < 0) 13212748Ssam return; 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: 19412748Ssam *valuep = ((struct socket *)fp->f_data)->so_pgrp; 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 { 2087422Sroot 20912748Ssam if (fp->f_type == DTYPE_SOCKET) { 21012748Ssam ((struct socket *)fp->f_data)->so_pgrp = value; 21112748Ssam return (0); 21212748Ssam } 21312748Ssam if (value > 0) { 21412748Ssam struct proc *p = pfind(value); 21512748Ssam if (p == 0) 21612748Ssam return (EINVAL); 21712748Ssam value = p->p_pgrp; 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 { 23512748Ssam int i; 23612748Ssam } *uap = (struct a *)u.u_ap; 23721101Skarels register int i = uap->i; 23812748Ssam register struct file *fp; 23913044Ssam register u_char *pf; 2408029Sroot 24121101Skarels GETF(fp, i); 24221101Skarels pf = (u_char *)&u.u_pofile[i]; 24313044Ssam if (*pf & UF_MAPPED) 24421101Skarels munmapfd(i); 24521101Skarels u.u_ofile[i] = NULL; 24621101Skarels while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 24721101Skarels u.u_lastfile--; 24815550Skarels *pf = 0; 24913044Ssam closef(fp); 25012748Ssam /* WHAT IF u.u_error ? */ 2518029Sroot } 2528029Sroot 25313044Ssam fstat() 25413044Ssam { 25513044Ssam register struct file *fp; 25613044Ssam register struct a { 25713044Ssam int fdes; 25813044Ssam struct stat *sb; 25913044Ssam } *uap; 26013044Ssam struct stat ub; 26113044Ssam 26213044Ssam uap = (struct a *)u.u_ap; 26317003Smckusick GETF(fp, uap->fdes); 26413044Ssam switch (fp->f_type) { 26513044Ssam 26613044Ssam case DTYPE_INODE: 26713044Ssam u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 26813044Ssam break; 26913044Ssam 27013044Ssam case DTYPE_SOCKET: 27113044Ssam u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 27213044Ssam break; 27313044Ssam 27413044Ssam default: 27513044Ssam panic("fstat"); 27613044Ssam /*NOTREACHED*/ 27713044Ssam } 27813044Ssam if (u.u_error == 0) 27913101Ssam u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 28013101Ssam sizeof (ub)); 28113044Ssam } 28213044Ssam 2837422Sroot /* 2847497Sroot * Allocate a user file descriptor. 2857422Sroot */ 28612748Ssam ufalloc(i) 28712748Ssam register int i; 2887422Sroot { 2897497Sroot 29012748Ssam for (; i < NOFILE; i++) 2917497Sroot if (u.u_ofile[i] == NULL) { 2927497Sroot u.u_r.r_val1 = i; 2937497Sroot u.u_pofile[i] = 0; 29421101Skarels if (i > u.u_lastfile) 29521101Skarels u.u_lastfile = i; 2967497Sroot return (i); 2977497Sroot } 2987497Sroot u.u_error = EMFILE; 2997497Sroot return (-1); 3007497Sroot } 3017497Sroot 30212748Ssam ufavail() 30312748Ssam { 30412748Ssam register int i, avail = 0; 30512748Ssam 30612748Ssam for (i = 0; i < NOFILE; i++) 30712748Ssam if (u.u_ofile[i] == NULL) 30812748Ssam avail++; 30912748Ssam return (avail); 31012748Ssam } 31112748Ssam 3127497Sroot struct file *lastf; 3137497Sroot /* 3147497Sroot * Allocate a user file descriptor 3157497Sroot * and a file structure. 3167497Sroot * Initialize the descriptor 3177497Sroot * to point at the file structure. 3187497Sroot */ 3197497Sroot struct file * 3207497Sroot falloc() 3217497Sroot { 3227422Sroot register struct file *fp; 3237497Sroot register i; 3247422Sroot 32512748Ssam i = ufalloc(0); 3267497Sroot if (i < 0) 3277497Sroot return (NULL); 3287497Sroot if (lastf == 0) 3297497Sroot lastf = file; 3307497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3317497Sroot if (fp->f_count == 0) 3327497Sroot goto slot; 3337497Sroot for (fp = file; fp < lastf; fp++) 3347497Sroot if (fp->f_count == 0) 3357497Sroot goto slot; 3367497Sroot tablefull("file"); 3377497Sroot u.u_error = ENFILE; 3387497Sroot return (NULL); 3397497Sroot slot: 3407497Sroot u.u_ofile[i] = fp; 34112748Ssam fp->f_count = 1; 34212748Ssam fp->f_data = 0; 3437497Sroot fp->f_offset = 0; 3447497Sroot lastf = fp + 1; 3457497Sroot return (fp); 3467497Sroot } 34712748Ssam 3487497Sroot /* 3497497Sroot * Convert a user supplied file descriptor into a pointer 3507497Sroot * to a file structure. Only task is to check range of the descriptor. 35112748Ssam * Critical paths should use the GETF macro. 3527497Sroot */ 3537497Sroot struct file * 3547497Sroot getf(f) 3557497Sroot register int f; 3567497Sroot { 3577497Sroot register struct file *fp; 3587497Sroot 3597497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 3607497Sroot u.u_error = EBADF; 3617497Sroot return (NULL); 3627497Sroot } 3637497Sroot return (fp); 3647497Sroot } 3657497Sroot 3667497Sroot /* 3677497Sroot * Internal form of close. 36812748Ssam * Decrement reference count on file structure. 36912748Ssam * If last reference not going away, but no more 37012748Ssam * references except in message queues, run a 37112748Ssam * garbage collect. This would better be done by 37212748Ssam * forcing a gc() to happen sometime soon, rather 37312748Ssam * than running one each time. 3747497Sroot */ 37513044Ssam closef(fp) 3767497Sroot register struct file *fp; 3777497Sroot { 3787497Sroot 3797422Sroot if (fp == NULL) 3807422Sroot return; 3817497Sroot if (fp->f_count > 1) { 3827497Sroot fp->f_count--; 38312748Ssam if (fp->f_count == fp->f_msgcount) 38412748Ssam unp_gc(); 3857422Sroot return; 3867422Sroot } 38713044Ssam (*fp->f_ops->fo_close)(fp); 3887497Sroot fp->f_count = 0; 3897422Sroot } 39013044Ssam 39113044Ssam /* 39213044Ssam * Apply an advisory lock on a file descriptor. 39313044Ssam */ 39413044Ssam flock() 39513044Ssam { 39613044Ssam register struct a { 39713044Ssam int fd; 39813044Ssam int how; 39913044Ssam } *uap = (struct a *)u.u_ap; 40013044Ssam register struct file *fp; 40113044Ssam 40217003Smckusick GETF(fp, uap->fd); 40313101Ssam if (fp->f_type != DTYPE_INODE) { 40413101Ssam u.u_error = EOPNOTSUPP; 40513044Ssam return; 40613044Ssam } 40713101Ssam if (uap->how & LOCK_UN) { 40813101Ssam ino_unlock(fp, FSHLOCK|FEXLOCK); 40913044Ssam return; 41013044Ssam } 41117434Skarels if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 41217434Skarels return; /* error? */ 41317998Skarels if (uap->how & LOCK_EX) 41417998Skarels uap->how &= ~LOCK_SH; 41513101Ssam /* avoid work... */ 41617998Skarels if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 41717998Skarels (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 41813044Ssam return; 41913101Ssam u.u_error = ino_lock(fp, uap->how); 42013044Ssam } 421