1*21101Skarels /* kern_descrip.c 6.10 85/05/27 */ 27422Sroot 317089Sbloom #include "param.h" 417089Sbloom #include "systm.h" 517089Sbloom #include "dir.h" 617089Sbloom #include "user.h" 717089Sbloom #include "kernel.h" 817089Sbloom #include "inode.h" 917089Sbloom #include "proc.h" 1017089Sbloom #include "file.h" 1117089Sbloom #include "socket.h" 1217089Sbloom #include "socketvar.h" 1317089Sbloom #include "mount.h" 1417089Sbloom #include "stat.h" 157422Sroot 1617089Sbloom #include "ioctl.h" 177497Sroot 187422Sroot /* 197497Sroot * Descriptor management. 207422Sroot */ 217497Sroot 227497Sroot /* 237497Sroot * TODO: 2412748Ssam * eliminate u.u_error side effects 257497Sroot */ 267497Sroot 277497Sroot /* 287497Sroot * System calls on descriptors. 297497Sroot */ 308029Sroot getdtablesize() 317497Sroot { 327497Sroot 337497Sroot u.u_r.r_val1 = NOFILE; 347497Sroot } 357497Sroot 368098Sroot getdopt() 378098Sroot { 388098Sroot 398098Sroot } 408098Sroot 418098Sroot setdopt() 428098Sroot { 438098Sroot 448098Sroot } 458098Sroot 467422Sroot dup() 477422Sroot { 487497Sroot register struct a { 497497Sroot int i; 507497Sroot } *uap = (struct a *) u.u_ap; 517696Ssam struct file *fp; 527696Ssam int j; 537497Sroot 547497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 557497Sroot 5617003Smckusick GETF(fp, uap->i); 5712748Ssam j = ufalloc(0); 587497Sroot if (j < 0) 597497Sroot return; 6017435Skarels dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 617497Sroot } 627497Sroot 637497Sroot dup2() 647497Sroot { 657422Sroot register struct a { 667497Sroot int i, j; 677497Sroot } *uap = (struct a *) u.u_ap; 687497Sroot register struct file *fp; 697422Sroot 7017003Smckusick GETF(fp, uap->i); 717497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 727497Sroot u.u_error = EBADF; 737497Sroot return; 747422Sroot } 757497Sroot u.u_r.r_val1 = uap->j; 767497Sroot if (uap->i == uap->j) 777497Sroot return; 787497Sroot if (u.u_ofile[uap->j]) { 798945Sroot if (u.u_pofile[uap->j] & UF_MAPPED) 808945Sroot munmapfd(uap->j); 8113101Ssam closef(u.u_ofile[uap->j]); 827422Sroot if (u.u_error) 837422Sroot return; 847422Sroot } 8517435Skarels dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 867696Ssam } 877696Ssam 8813101Ssam dupit(fd, fp, flags) 897696Ssam int fd; 907696Ssam register struct file *fp; 9113101Ssam register int flags; 927696Ssam { 937696Ssam 947696Ssam u.u_ofile[fd] = fp; 9513101Ssam u.u_pofile[fd] = flags; 967497Sroot fp->f_count++; 97*21101Skarels if (fd > u.u_lastfile) 98*21101Skarels u.u_lastfile = fd; 997422Sroot } 1007422Sroot 10112748Ssam /* 10212748Ssam * The file control system call. 10312748Ssam */ 10412748Ssam fcntl() 1057497Sroot { 1067497Sroot register struct file *fp; 1077497Sroot register struct a { 10812748Ssam int fdes; 10912748Ssam int cmd; 11012748Ssam int arg; 11112748Ssam } *uap; 11212748Ssam register i; 11312748Ssam register char *pop; 1147497Sroot 11512748Ssam uap = (struct a *)u.u_ap; 11617003Smckusick GETF(fp, uap->fdes); 11712748Ssam pop = &u.u_pofile[uap->fdes]; 11812748Ssam switch(uap->cmd) { 11915076Skarels case F_DUPFD: 12012748Ssam i = uap->arg; 12117434Skarels if (i < 0 || i >= NOFILE) { 12212748Ssam u.u_error = EINVAL; 12312748Ssam return; 12412748Ssam } 12512748Ssam if ((i = ufalloc(i)) < 0) 12612748Ssam return; 12717435Skarels dupit(i, fp, *pop &~ UF_EXCLOSE); 12812748Ssam break; 1297497Sroot 13015076Skarels case F_GETFD: 13112748Ssam u.u_r.r_val1 = *pop & 1; 13212748Ssam break; 1337422Sroot 13415076Skarels case F_SETFD: 13512748Ssam *pop = (*pop &~ 1) | (uap->arg & 1); 13612748Ssam break; 1378145Sroot 13815076Skarels case F_GETFL: 13912748Ssam u.u_r.r_val1 = fp->f_flag+FOPEN; 14012748Ssam break; 1418145Sroot 14215076Skarels case F_SETFL: 14312748Ssam fp->f_flag &= FCNTLCANT; 14412748Ssam fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 14512748Ssam u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 1469995Ssam if (u.u_error) 14712748Ssam break; 14812748Ssam u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 14912748Ssam if (u.u_error) 15012748Ssam (void) fset(fp, FNDELAY, 0); 15112748Ssam break; 1527422Sroot 15315076Skarels case F_GETOWN: 15415076Skarels u.u_error = fgetown(fp, &u.u_r.r_val1); 15512748Ssam break; 1567422Sroot 15715076Skarels case F_SETOWN: 15815076Skarels u.u_error = fsetown(fp, uap->arg); 1597422Sroot break; 1608115Sroot 16112748Ssam default: 16212748Ssam u.u_error = EINVAL; 1637422Sroot } 1647422Sroot } 1657422Sroot 16612748Ssam fset(fp, bit, value) 16712748Ssam struct file *fp; 16812748Ssam int bit, value; 1697422Sroot { 1707422Sroot 17112748Ssam if (value) 17212748Ssam fp->f_flag |= bit; 17312748Ssam else 17412748Ssam fp->f_flag &= ~bit; 17512748Ssam return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 17612748Ssam (caddr_t)&value)); 17712748Ssam } 1787422Sroot 17912748Ssam fgetown(fp, valuep) 18012748Ssam struct file *fp; 18112748Ssam int *valuep; 18212748Ssam { 18312748Ssam int error; 1848115Sroot 18512748Ssam switch (fp->f_type) { 1868115Sroot 18712748Ssam case DTYPE_SOCKET: 18812748Ssam *valuep = ((struct socket *)fp->f_data)->so_pgrp; 18912748Ssam return (0); 1907497Sroot 19112748Ssam default: 19212748Ssam error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 19312748Ssam *valuep = -*valuep; 19412748Ssam return (error); 1957422Sroot } 1967422Sroot } 1977422Sroot 19812748Ssam fsetown(fp, value) 19912748Ssam struct file *fp; 20012748Ssam int value; 2017422Sroot { 2027422Sroot 20312748Ssam if (fp->f_type == DTYPE_SOCKET) { 20412748Ssam ((struct socket *)fp->f_data)->so_pgrp = value; 20512748Ssam return (0); 20612748Ssam } 20712748Ssam if (value > 0) { 20812748Ssam struct proc *p = pfind(value); 20912748Ssam if (p == 0) 21012748Ssam return (EINVAL); 21112748Ssam value = p->p_pgrp; 21212748Ssam } else 21312748Ssam value = -value; 21412748Ssam return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 2157422Sroot } 2167422Sroot 21712748Ssam fioctl(fp, cmd, value) 21812748Ssam struct file *fp; 21912748Ssam int cmd; 22012748Ssam caddr_t value; 2217422Sroot { 2227422Sroot 22312748Ssam return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 2247422Sroot } 2257422Sroot 22612748Ssam close() 2278029Sroot { 228*21101Skarels struct a { 22912748Ssam int i; 23012748Ssam } *uap = (struct a *)u.u_ap; 231*21101Skarels register int i = uap->i; 23212748Ssam register struct file *fp; 23313044Ssam register u_char *pf; 2348029Sroot 235*21101Skarels GETF(fp, i); 236*21101Skarels pf = (u_char *)&u.u_pofile[i]; 23713044Ssam if (*pf & UF_MAPPED) 238*21101Skarels munmapfd(i); 239*21101Skarels u.u_ofile[i] = NULL; 240*21101Skarels while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 241*21101Skarels u.u_lastfile--; 24215550Skarels *pf = 0; 24313044Ssam closef(fp); 24412748Ssam /* WHAT IF u.u_error ? */ 2458029Sroot } 2468029Sroot 24713044Ssam fstat() 24813044Ssam { 24913044Ssam register struct file *fp; 25013044Ssam register struct a { 25113044Ssam int fdes; 25213044Ssam struct stat *sb; 25313044Ssam } *uap; 25413044Ssam struct stat ub; 25513044Ssam 25613044Ssam uap = (struct a *)u.u_ap; 25717003Smckusick GETF(fp, uap->fdes); 25813044Ssam switch (fp->f_type) { 25913044Ssam 26013044Ssam case DTYPE_INODE: 26113044Ssam u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 26213044Ssam break; 26313044Ssam 26413044Ssam case DTYPE_SOCKET: 26513044Ssam u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 26613044Ssam break; 26713044Ssam 26813044Ssam default: 26913044Ssam panic("fstat"); 27013044Ssam /*NOTREACHED*/ 27113044Ssam } 27213044Ssam if (u.u_error == 0) 27313101Ssam u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 27413101Ssam sizeof (ub)); 27513044Ssam } 27613044Ssam 2777422Sroot /* 2787497Sroot * Allocate a user file descriptor. 2797422Sroot */ 28012748Ssam ufalloc(i) 28112748Ssam register int i; 2827422Sroot { 2837497Sroot 28412748Ssam for (; i < NOFILE; i++) 2857497Sroot if (u.u_ofile[i] == NULL) { 2867497Sroot u.u_r.r_val1 = i; 2877497Sroot u.u_pofile[i] = 0; 288*21101Skarels if (i > u.u_lastfile) 289*21101Skarels u.u_lastfile = i; 2907497Sroot return (i); 2917497Sroot } 2927497Sroot u.u_error = EMFILE; 2937497Sroot return (-1); 2947497Sroot } 2957497Sroot 29612748Ssam ufavail() 29712748Ssam { 29812748Ssam register int i, avail = 0; 29912748Ssam 30012748Ssam for (i = 0; i < NOFILE; i++) 30112748Ssam if (u.u_ofile[i] == NULL) 30212748Ssam avail++; 30312748Ssam return (avail); 30412748Ssam } 30512748Ssam 3067497Sroot struct file *lastf; 3077497Sroot /* 3087497Sroot * Allocate a user file descriptor 3097497Sroot * and a file structure. 3107497Sroot * Initialize the descriptor 3117497Sroot * to point at the file structure. 3127497Sroot */ 3137497Sroot struct file * 3147497Sroot falloc() 3157497Sroot { 3167422Sroot register struct file *fp; 3177497Sroot register i; 3187422Sroot 31912748Ssam i = ufalloc(0); 3207497Sroot if (i < 0) 3217497Sroot return (NULL); 3227497Sroot if (lastf == 0) 3237497Sroot lastf = file; 3247497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3257497Sroot if (fp->f_count == 0) 3267497Sroot goto slot; 3277497Sroot for (fp = file; fp < lastf; fp++) 3287497Sroot if (fp->f_count == 0) 3297497Sroot goto slot; 3307497Sroot tablefull("file"); 3317497Sroot u.u_error = ENFILE; 3327497Sroot return (NULL); 3337497Sroot slot: 3347497Sroot u.u_ofile[i] = fp; 33512748Ssam fp->f_count = 1; 33612748Ssam fp->f_data = 0; 3377497Sroot fp->f_offset = 0; 3387497Sroot lastf = fp + 1; 3397497Sroot return (fp); 3407497Sroot } 34112748Ssam 3427497Sroot /* 3437497Sroot * Convert a user supplied file descriptor into a pointer 3447497Sroot * to a file structure. Only task is to check range of the descriptor. 34512748Ssam * Critical paths should use the GETF macro. 3467497Sroot */ 3477497Sroot struct file * 3487497Sroot getf(f) 3497497Sroot register int f; 3507497Sroot { 3517497Sroot register struct file *fp; 3527497Sroot 3537497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 3547497Sroot u.u_error = EBADF; 3557497Sroot return (NULL); 3567497Sroot } 3577497Sroot return (fp); 3587497Sroot } 3597497Sroot 3607497Sroot /* 3617497Sroot * Internal form of close. 36212748Ssam * Decrement reference count on file structure. 36312748Ssam * If last reference not going away, but no more 36412748Ssam * references except in message queues, run a 36512748Ssam * garbage collect. This would better be done by 36612748Ssam * forcing a gc() to happen sometime soon, rather 36712748Ssam * than running one each time. 3687497Sroot */ 36913044Ssam closef(fp) 3707497Sroot register struct file *fp; 3717497Sroot { 3727497Sroot 3737422Sroot if (fp == NULL) 3747422Sroot return; 3757497Sroot if (fp->f_count > 1) { 3767497Sroot fp->f_count--; 37712748Ssam if (fp->f_count == fp->f_msgcount) 37812748Ssam unp_gc(); 3797422Sroot return; 3807422Sroot } 38113044Ssam (*fp->f_ops->fo_close)(fp); 3827497Sroot fp->f_count = 0; 3837422Sroot } 38413044Ssam 38513044Ssam /* 38613044Ssam * Apply an advisory lock on a file descriptor. 38713044Ssam */ 38813044Ssam flock() 38913044Ssam { 39013044Ssam register struct a { 39113044Ssam int fd; 39213044Ssam int how; 39313044Ssam } *uap = (struct a *)u.u_ap; 39413044Ssam register struct file *fp; 39513044Ssam 39617003Smckusick GETF(fp, uap->fd); 39713101Ssam if (fp->f_type != DTYPE_INODE) { 39813101Ssam u.u_error = EOPNOTSUPP; 39913044Ssam return; 40013044Ssam } 40113101Ssam if (uap->how & LOCK_UN) { 40213101Ssam ino_unlock(fp, FSHLOCK|FEXLOCK); 40313044Ssam return; 40413044Ssam } 40517434Skarels if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 40617434Skarels return; /* error? */ 40717998Skarels if (uap->how & LOCK_EX) 40817998Skarels uap->how &= ~LOCK_SH; 40913101Ssam /* avoid work... */ 41017998Skarels if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 41117998Skarels (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 41213044Ssam return; 41313101Ssam u.u_error = ino_lock(fp, uap->how); 41413044Ssam } 415