1*17998Skarels /* kern_descrip.c 6.8 85/02/16 */ 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 "conf.h" 1117089Sbloom #include "file.h" 1217089Sbloom #include "socket.h" 1317089Sbloom #include "socketvar.h" 1417089Sbloom #include "mount.h" 1517089Sbloom #include "stat.h" 167422Sroot 1717089Sbloom #include "ioctl.h" 187497Sroot 197422Sroot /* 207497Sroot * Descriptor management. 217422Sroot */ 227497Sroot 237497Sroot /* 247497Sroot * TODO: 2512748Ssam * increase NOFILE 2612748Ssam * eliminate u.u_error side effects 277497Sroot */ 287497Sroot 297497Sroot /* 307497Sroot * System calls on descriptors. 317497Sroot */ 328029Sroot getdtablesize() 337497Sroot { 347497Sroot 357497Sroot u.u_r.r_val1 = NOFILE; 367497Sroot } 377497Sroot 388098Sroot getdopt() 398098Sroot { 408098Sroot 418098Sroot } 428098Sroot 438098Sroot setdopt() 448098Sroot { 458098Sroot 468098Sroot } 478098Sroot 487422Sroot dup() 497422Sroot { 507497Sroot register struct a { 517497Sroot int i; 527497Sroot } *uap = (struct a *) u.u_ap; 537696Ssam struct file *fp; 547696Ssam int j; 557497Sroot 567497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 577497Sroot 5817003Smckusick GETF(fp, uap->i); 5912748Ssam j = ufalloc(0); 607497Sroot if (j < 0) 617497Sroot return; 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; 717422Sroot 7217003Smckusick GETF(fp, uap->i); 737497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 747497Sroot u.u_error = EBADF; 757497Sroot return; 767422Sroot } 777497Sroot u.u_r.r_val1 = uap->j; 787497Sroot if (uap->i == uap->j) 797497Sroot return; 807497Sroot if (u.u_ofile[uap->j]) { 818945Sroot if (u.u_pofile[uap->j] & UF_MAPPED) 828945Sroot munmapfd(uap->j); 8313101Ssam closef(u.u_ofile[uap->j]); 847422Sroot if (u.u_error) 857422Sroot return; 867422Sroot } 8717435Skarels dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 887696Ssam } 897696Ssam 9013101Ssam dupit(fd, fp, flags) 917696Ssam int fd; 927696Ssam register struct file *fp; 9313101Ssam register int flags; 947696Ssam { 957696Ssam 967696Ssam u.u_ofile[fd] = fp; 9713101Ssam u.u_pofile[fd] = flags; 987497Sroot fp->f_count++; 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 { 22812748Ssam register struct a { 22912748Ssam int i; 23012748Ssam } *uap = (struct a *)u.u_ap; 23112748Ssam register struct file *fp; 23213044Ssam register u_char *pf; 2338029Sroot 23417003Smckusick GETF(fp, uap->i); 23513044Ssam pf = (u_char *)&u.u_pofile[uap->i]; 23613044Ssam if (*pf & UF_MAPPED) 23712748Ssam munmapfd(uap->i); 23815550Skarels u.u_ofile[uap->i] = NULL; 23915550Skarels *pf = 0; 24013044Ssam closef(fp); 24112748Ssam /* WHAT IF u.u_error ? */ 2428029Sroot } 2438029Sroot 24413044Ssam fstat() 24513044Ssam { 24613044Ssam register struct file *fp; 24713044Ssam register struct a { 24813044Ssam int fdes; 24913044Ssam struct stat *sb; 25013044Ssam } *uap; 25113044Ssam struct stat ub; 25213044Ssam 25313044Ssam uap = (struct a *)u.u_ap; 25417003Smckusick GETF(fp, uap->fdes); 25513044Ssam switch (fp->f_type) { 25613044Ssam 25713044Ssam case DTYPE_INODE: 25813044Ssam u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 25913044Ssam break; 26013044Ssam 26113044Ssam case DTYPE_SOCKET: 26213044Ssam u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 26313044Ssam break; 26413044Ssam 26513044Ssam default: 26613044Ssam panic("fstat"); 26713044Ssam /*NOTREACHED*/ 26813044Ssam } 26913044Ssam if (u.u_error == 0) 27013101Ssam u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 27113101Ssam sizeof (ub)); 27213044Ssam } 27313044Ssam 2747422Sroot /* 2757497Sroot * Allocate a user file descriptor. 2767422Sroot */ 27712748Ssam ufalloc(i) 27812748Ssam register int i; 2797422Sroot { 2807497Sroot 28112748Ssam for (; i < NOFILE; i++) 2827497Sroot if (u.u_ofile[i] == NULL) { 2837497Sroot u.u_r.r_val1 = i; 2847497Sroot u.u_pofile[i] = 0; 2857497Sroot return (i); 2867497Sroot } 2877497Sroot u.u_error = EMFILE; 2887497Sroot return (-1); 2897497Sroot } 2907497Sroot 29112748Ssam ufavail() 29212748Ssam { 29312748Ssam register int i, avail = 0; 29412748Ssam 29512748Ssam for (i = 0; i < NOFILE; i++) 29612748Ssam if (u.u_ofile[i] == NULL) 29712748Ssam avail++; 29812748Ssam return (avail); 29912748Ssam } 30012748Ssam 3017497Sroot struct file *lastf; 3027497Sroot /* 3037497Sroot * Allocate a user file descriptor 3047497Sroot * and a file structure. 3057497Sroot * Initialize the descriptor 3067497Sroot * to point at the file structure. 3077497Sroot */ 3087497Sroot struct file * 3097497Sroot falloc() 3107497Sroot { 3117422Sroot register struct file *fp; 3127497Sroot register i; 3137422Sroot 31412748Ssam i = ufalloc(0); 3157497Sroot if (i < 0) 3167497Sroot return (NULL); 3177497Sroot if (lastf == 0) 3187497Sroot lastf = file; 3197497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3207497Sroot if (fp->f_count == 0) 3217497Sroot goto slot; 3227497Sroot for (fp = file; fp < lastf; fp++) 3237497Sroot if (fp->f_count == 0) 3247497Sroot goto slot; 3257497Sroot tablefull("file"); 3267497Sroot u.u_error = ENFILE; 3277497Sroot return (NULL); 3287497Sroot slot: 3297497Sroot u.u_ofile[i] = fp; 33012748Ssam fp->f_count = 1; 33112748Ssam fp->f_data = 0; 3327497Sroot fp->f_offset = 0; 3337497Sroot lastf = fp + 1; 3347497Sroot return (fp); 3357497Sroot } 33612748Ssam 3377497Sroot /* 3387497Sroot * Convert a user supplied file descriptor into a pointer 3397497Sroot * to a file structure. Only task is to check range of the descriptor. 34012748Ssam * Critical paths should use the GETF macro. 3417497Sroot */ 3427497Sroot struct file * 3437497Sroot getf(f) 3447497Sroot register int f; 3457497Sroot { 3467497Sroot register struct file *fp; 3477497Sroot 3487497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 3497497Sroot u.u_error = EBADF; 3507497Sroot return (NULL); 3517497Sroot } 3527497Sroot return (fp); 3537497Sroot } 3547497Sroot 3557497Sroot /* 3567497Sroot * Internal form of close. 35712748Ssam * Decrement reference count on file structure. 35812748Ssam * If last reference not going away, but no more 35912748Ssam * references except in message queues, run a 36012748Ssam * garbage collect. This would better be done by 36112748Ssam * forcing a gc() to happen sometime soon, rather 36212748Ssam * than running one each time. 3637497Sroot */ 36413044Ssam closef(fp) 3657497Sroot register struct file *fp; 3667497Sroot { 3677497Sroot 3687422Sroot if (fp == NULL) 3697422Sroot return; 3707497Sroot if (fp->f_count > 1) { 3717497Sroot fp->f_count--; 37212748Ssam if (fp->f_count == fp->f_msgcount) 37312748Ssam unp_gc(); 3747422Sroot return; 3757422Sroot } 37613044Ssam (*fp->f_ops->fo_close)(fp); 3777497Sroot fp->f_count = 0; 3787422Sroot } 37913044Ssam 38013044Ssam /* 38113044Ssam * Apply an advisory lock on a file descriptor. 38213044Ssam */ 38313044Ssam flock() 38413044Ssam { 38513044Ssam register struct a { 38613044Ssam int fd; 38713044Ssam int how; 38813044Ssam } *uap = (struct a *)u.u_ap; 38913044Ssam register struct file *fp; 39013044Ssam 39117003Smckusick GETF(fp, uap->fd); 39213101Ssam if (fp->f_type != DTYPE_INODE) { 39313101Ssam u.u_error = EOPNOTSUPP; 39413044Ssam return; 39513044Ssam } 39613101Ssam if (uap->how & LOCK_UN) { 39713101Ssam ino_unlock(fp, FSHLOCK|FEXLOCK); 39813044Ssam return; 39913044Ssam } 40017434Skarels if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 40117434Skarels return; /* error? */ 402*17998Skarels if (uap->how & LOCK_EX) 403*17998Skarels uap->how &= ~LOCK_SH; 40413101Ssam /* avoid work... */ 405*17998Skarels if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 406*17998Skarels (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 40713044Ssam return; 40813101Ssam u.u_error = ino_lock(fp, uap->how); 40913044Ssam } 410